CVE-2022-23596: Loop with Unreachable Exit Condition ('Infinite Loop') (CWE-835)
value: Junrar is an open source java RAR archive library. In affected versions A carefully crafted RAR archive can trigger an infinite loop while extracting said archive. The impact depends solely on how the application uses the library, and whether files can be provided by malignant users. The problem is patched in 7.4.1. There are no known workarounds and users are advised to upgrade as soon as possible.
CWE description: The product contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.
CVSS v3 base score: 7.5
Published: 2022-02-01T12:15Z
Repository: https://github.com/junrar/junrar
Language: Java
Files changed: src/main/java/com/github/junrar/Archive.java, src/test/java/com/github/junrar/AbnormalFilesTest.java
Commit date: 2022-01-27 12:08:38 +0800
Commit message: fix: invalid subheader type would throw npe and make the extract loop

closes #73

Diff: diff --git a/src/main/java/com/github/junrar/Archive.java b/src/main/java/com/github/junrar/Archive.java
index 7af74a57..47baa3ed 100644
--- a/src/main/java/com/github/junrar/Archive.java
+++ b/src/main/java/com/github/junrar/Archive.java
@@ -43,10 +43,11 @@ import com.github.junrar.rarfile.MainHeader;
 import com.github.junrar.rarfile.MarkHeader;
 import com.github.junrar.rarfile.ProtectHeader;
 import com.github.junrar.rarfile.RARVersion;
 import com.github.junrar.rarfile.SignHeader;
 import com.github.junrar.rarfile.SubBlockHeader;
+import com.github.junrar.rarfile.SubBlockHeaderType;
 import com.github.junrar.rarfile.UnixOwnersHeader;
 import com.github.junrar.rarfile.UnrarHeadertype;
 import com.github.junrar.unpack.ComprDataIO;
 import com.github.junrar.unpack.Unpack;
 import com.github.junrar.volume.FileVolumeManager;
@@ -447,11 +448,13 @@ public class Archive implements Closeable, Iterable<FileHeader> {
                             final byte[] subHeadbuffer = safelyAllocate(SubBlockHeader.SubBlockHeaderSize, MAX_HEADER_SIZE);
                             rawData.readFully(subHeadbuffer, subHeadbuffer.length);
                             final SubBlockHeader subHead = new SubBlockHeader(blockHead,
                                 subHeadbuffer);
                             subHead.print();
-                            switch (subHead.getSubType()) {
+                            SubBlockHeaderType subType = subHead.getSubType();
+                            if (subType == null) break;
+                            switch (subType) {
                                 case MAC_HEAD: {
                                     final byte[] macHeaderbuffer = safelyAllocate(MacInfoHeader.MacInfoHeaderSize, MAX_HEADER_SIZE);
                                     rawData.readFully(macHeaderbuffer, macHeaderbuffer.length);
                                     final MacInfoHeader macHeader = new MacInfoHeader(subHead,
                                         macHeaderbuffer);
diff --git a/src/test/java/com/github/junrar/AbnormalFilesTest.java b/src/test/java/com/github/junrar/AbnormalFilesTest.java
index 405bc9f3..fa09f484 100644
--- a/src/test/java/com/github/junrar/AbnormalFilesTest.java
+++ b/src/test/java/com/github/junrar/AbnormalFilesTest.java
@@ -56,9 +56,10 @@ public class AbnormalFilesTest {
     }
 
     private static Stream<Arguments> provideFilesAndExpectedExceptionType() {
         return Stream.of(
             Arguments.of("abnormal/corrupt-header.rar", CorruptHeaderException.class),
-            Arguments.of("abnormal/mainHeaderNull.rar", BadRarArchiveException.class)
+            Arguments.of("abnormal/mainHeaderNull.rar", BadRarArchiveException.class),
+            Arguments.of("abnormal/loop.rar", CorruptHeaderException.class)
         );
     }
 }
diff --git a/src/test/resources/com/github/junrar/abnormal/loop.rar b/src/test/resources/com/github/junrar/abnormal/loop.rar
new file mode 100644
index 00000000..8f9db1f6
Binary files /dev/null and b/src/test/resources/com/github/junrar/abnormal/loop.rar differ

Vulnerable code:                             switch (subHead.getSubType()) {
            Arguments.of("abnormal/mainHeaderNull.rar", BadRarArchiveException.class)
Fixed code: import com.github.junrar.rarfile.SubBlockHeaderType;
                            SubBlockHeaderType subType = subHead.getSubType();
                            if (subType == null) break;
                            switch (subType) {
            Arguments.of("abnormal/mainHeaderNull.rar", BadRarArchiveException.class),
            Arguments.of("abnormal/loop.rar", CorruptHeaderException.class)