]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
iso9660: Fail when expected Rockridge extensions is missing
authorDaniel Axtens <dja@axtens.net>
Tue, 1 Jan 2019 06:10:49 +0000 (17:10 +1100)
committerDaniel Axtens <dja@axtens.net>
Wed, 16 Jan 2019 05:31:47 +0000 (16:31 +1100)
A corrupted or malicious ISO9660 image can cause read_CE() to loop
forever.

read_CE() calls parse_rockridge(), expecting a Rockridge extension
to be read. However, parse_rockridge() is structured as a while
loop starting with a sanity check, and if the sanity check fails
before the loop has run, the function returns ARCHIVE_OK without
advancing the position in the file. This causes read_CE() to retry
indefinitely.

Make parse_rockridge() return ARCHIVE_WARN if it didn't read an
extension. As someone with no real knowledge of the format, this
seems more apt than ARCHIVE_FATAL, but both the call-sites escalate
it to a fatal error immediately anyway.

Found with a combination of AFL, afl-rb (FairFuzz) and qsym.

libarchive/archive_read_support_format_iso9660.c

index 28acfefbba8acdd2d8edccfec034fb679b0bf0e4..bad8f1dfef3a8b59a6eccd99c909b74a9741c5b0 100644 (file)
@@ -2102,6 +2102,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
     const unsigned char *p, const unsigned char *end)
 {
        struct iso9660 *iso9660;
+       int entry_seen = 0;
 
        iso9660 = (struct iso9660 *)(a->format->data);
 
@@ -2257,8 +2258,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
                }
 
                p += p[2];
+               entry_seen = 1;
+       }
+
+       if (entry_seen)
+               return (ARCHIVE_OK);
+       else {
+               archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                                 "Tried to parse Rockridge extensions, but none found");
+               return (ARCHIVE_WARN);
        }
-       return (ARCHIVE_OK);
 }
 
 static int