about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-10-24 02:21:11 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-10-24 02:21:11 +0000
commit55f6dc129c5c2be1035039ee1c348fbd2abde2b5 (patch)
tree54c8f0d79500bc434e8db190e140982bac7e9009
parent92bbdd2b0a68168b42d1d8381978ebedb098dafb (diff)
downloadnetpbm-mirror-55f6dc129c5c2be1035039ee1c348fbd2abde2b5.tar.gz
netpbm-mirror-55f6dc129c5c2be1035039ee1c348fbd2abde2b5.tar.xz
netpbm-mirror-55f6dc129c5c2be1035039ee1c348fbd2abde2b5.zip
Fix handling of non-NUL-terminated strings in input file
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3091 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/ppm/sldtoppm.c162
-rw-r--r--doc/HISTORY3
2 files changed, 105 insertions, 60 deletions
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index 9a41cde3..7a03e237 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -154,85 +154,127 @@ vscale(int * const px,
 
 
 
+static void
+upcase(const char * const sname,
+       char *       const uname) {
+
+    unsigned int i;
+    const char * ip;
+
+    for (i = 0, ip = sname; i < 31; ++i) {
+        char const ch = *ip++;
+
+        if (ch != EOS)
+            uname[i] = islower(ch) ? toupper(ch) : ch;
+    }
+    uname[i] = EOS;
+}
+
+
+
+static void
+skipBytes(FILE *       const fileP,
+          unsigned int const count) {
+
+    unsigned int i;
+
+    for (i = 0; i < count; ++i)
+        getc(fileP);
+}
+
+
+
+static void
+scanDirectory(FILE *       const slFileP,
+              long         const dirPos,
+              bool         const dirOnly,
+              const char * const uname,
+              bool *       const foundP) {
+/*----------------------------------------------------------------------------
+   Scan the directory at the current position in *slFileP, either listing
+   the directory ('dirOnly' true) or searching for a slide named
+   'uname' ('dirOnly' false).
+
+   'dirPos' is the offset in the file of the directory, i.e. the current
+   position of *slFileP.
+
+   In the latter case, return as *foundP whether the slide name is there.
+-----------------------------------------------------------------------------*/
+    bool found;
+    bool eof;
+    long pos;
+    unsigned char libent[36];
+
+    for (found = false, eof = false, pos = dirPos; !found && !eof; ) {
+        size_t readCt;
+        readCt = fread(libent, 36, 1, slFileP);
+        if (readCt != 1)
+            eof = true;
+        else {
+            /* The directory entry is 32 bytes of NUL-terminated slide name
+               followed by 4 bytes of offset of the next directory entry.
+            */
+            const char * const slideName = (const char *)(&libent[0]);
+            if (strnlen(slideName, 32) == 32)
+                pm_error("Invalid input: slide name field is not "
+                         "nul-terminated");
+            else {
+                if (strlen(slideName) == 0)
+                    eof = true;
+                else {
+                    pos += 36;
+                    if (dirOnly) {
+                        pm_message("  %s", slideName);
+                    } else if (streq(slideName, uname)) {
+                        long const dpos =
+                            (((((libent[35] << 8) | libent[34]) << 8) |
+                              libent[33]) << 8) | libent[32];
+
+                        if ((slFileP == stdin) ||
+                            (fseek(slFileP, dpos, 0) == -1)) {
+
+                            skipBytes(slFileP, dpos - pos);
+                        }
+                        found = true;
+                    }
+                }
+            }
+        }
+    }
+    *foundP = found;
+}
+
 /*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
            nonzero, print a directory listing of the  library.
            If  UCASEN  is nonzero, the requested slide name is
            converted to upper case. */
 
 static void
-slidefind(const char * const sname,
-          bool         const dironly,
+slidefind(const char * const slideName,
+          bool         const dirOnly,
           bool         const ucasen) {
 
-    char uname[32];
-    unsigned char libent[36];
-    long pos;
+    char uname[32];  /* upper case translation of 'slideName' */
+    char header[32]; /* (supposed) header read from file */
     bool found;
-    bool eof;
 
-    if (dironly)
+    if (dirOnly)
         pm_message("Slides in library:");
     else {
-        unsigned int i;
-        const char * ip;
-
-        ip = sname; /* initial value */
-
-        for (i = 0; i < 31; ++i) {
-            char const ch = *ip++;
-            if (ch == EOS)
-                break;
-
-            {
-                char const upperCh =
-                    ucasen && islower(ch) ? toupper(ch) : ch;
-
-                uname[i] = upperCh;
-            }
-        }
-        uname[i] = EOS;
+        upcase(slideName, uname);
     }
 
     /* Read slide library header and verify. */
 
-    if ((fread(libent, 32, 1, slfile) != 1) ||
-        (!streq((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
+    if ((fread(header, 32, 1, slfile) != 1) ||
+        (!STRSEQ(header, "AutoCAD Slide Library 1.0\015\012\32"))) {
         pm_error("not an AutoCAD slide library file.");
     }
-    pos = 32;
-
-    /* Search for a slide with the requested name or list the directory */
-
-    for (found = false, eof = false; !found && !eof; ) {
-        size_t readCt;
-        readCt = fread(libent, 36, 1, slfile);
-        if (readCt != 1)
-            eof = true;
-        else if (strlen((char *)libent) == 0)
-            eof = true;
-
-        if (!eof) {
-            pos += 36;
-            if (dironly) {
-                pm_message("  %s", libent);
-            } else if (streq((char *)libent, uname)) {
-                long dpos;
 
-                dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                         libent[33]) << 8) | libent[32];
+    scanDirectory(slfile, 32, dirOnly, ucasen ? uname : slideName, &found);
 
-                if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
-                    dpos -= pos;
-
-                    while (dpos-- > 0)
-                        getc(slfile);
-                }
-                found = true;
-            }
-        }
-    }
-    if (!found && !dironly)
-        pm_error("slide '%s' not in library.", sname);
+    if (!found && !dirOnly)
+        pm_error("slide '%s' not in library.", slideName);
 }
 
 
@@ -350,7 +392,7 @@ slider(slvecfn   slvec,
 
     /* Verify that slide format is compatible with this program. */
 
-    if (!streq(slfrof.slh, slhi.slh))
+    if (!STRSEQ(slfrof.slh, slhi.slh))
         pm_error("this is not an AutoCAD slide file.");
 
     /* Verify that the number format and file level in the header  are
diff --git a/doc/HISTORY b/doc/HISTORY
index 9e327490..b3acbce4 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -13,6 +13,9 @@ not yet  BJH  Release 10.81.00
               slide file.  Broken after Netpbm 10.26 (January 2005), but no
               later than 10.35 (August 2006).
 
+              sldtoppm: fix bug: wild memory accesses, weird messages when
+              invalid input file has unterminated strings.
+              
 17.09.30 BJH  Release 10.80.00
 
               pnmtopalm: Refuse to create a compressed image with more than 8