Fixed some infinite loops that a maliciously-crafted .iso can trigger. stable-3.0
authorRyan C. Gordon <icculus@icculus.org>
Mon, 23 Oct 2017 14:58:54 -0400
branchstable-3.0
changeset 1623 2f3059329d19
parent 1622 059e6cc0039d
child 1624 e6921cdff303
Fixed some infinite loops that a maliciously-crafted .iso can trigger.

These bugs exposed by American Fuzzy Lop (AFL), a powerful fuzzer.

http://lcamtuf.coredump.cx/afl/
(transplanted from 4f1bf89597e5b76c1c317fbeb2b472481090b4e4)
src/physfs_archiver_iso9660.c
--- a/src/physfs_archiver_iso9660.c	Mon Oct 23 12:40:59 2017 -0400
+++ b/src/physfs_archiver_iso9660.c	Mon Oct 23 14:58:54 2017 -0400
@@ -151,18 +151,25 @@
 
         /* recordlen = 0 -> no more entries or fill entry */
         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &recordlen, 1), 0);
-        if (recordlen == 0)
+        if (recordlen > 0)
+            readpos += recordlen;  /* ready to seek to next record. */
+        else
         {
+            PHYSFS_uint64 nextpos;
+
             /* if we are in the last sector of the directory & it's 0 -> end */
             if ((dirend - 2048) <= (readpos - 1))
                 break; /* finished */
 
             /* else skip to the next sector & continue; */
-            readpos = (((readpos - 1) / 2048) + 1) * 2048;
-            continue;
-        } /* if */
+            nextpos = (((readpos - 1) / 2048) + 1) * 2048;
 
-        readpos += recordlen;  /* ready to seek to next record. */
+            /* whoops, can't make forward progress! */
+            BAIL_IF(nextpos == readpos, PHYSFS_ERR_CORRUPT, 0);
+
+            readpos = nextpos;
+            continue;  /* start back at upper loop. */
+        } /* else */
 
         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &extattrlen, 1), 0);
         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &extent, 4), 0);
@@ -203,6 +210,10 @@
         timestamp = (PHYSFS_sint64) mktime(&t);
 
         extent += extattrlen;  /* skip extended attribute record. */
+
+        /* infinite loop, corrupt file? */
+        BAIL_IF((extent * 2048) == dirstart, PHYSFS_ERR_CORRUPT, 0);
+
         if (!iso9660AddEntry(io, joliet, isdir, base, fname, fnamelen,
                              timestamp, extent * 2048, datalen, unpkarc))
         {