Fix PNM file reading (#847)
authorMatthieu Darbois <mayeut@users.noreply.github.com>
Wed, 21 Sep 2016 22:30:34 +0000 (00:30 +0200)
committerMathieu Malaterre <mathieu.malaterre@gmail.com>
Thu, 22 Sep 2016 06:16:36 +0000 (08:16 +0200)
Malformed PNM file could cause a crash in opj_compress.
Checks were added to prevent this.

Fixes #843
Updates #440

src/bin/jp2/convert.c
tests/nonregression/test_suite.ctest.in

index c130b3bfbc2ed2453388f16db05cd595954c6943..deee4f6e051ffcaf4c13173861f3ea6c30122a0d 100644 (file)
@@ -1328,11 +1328,14 @@ struct pnm_header
 
 static char *skip_white(char *s)
 {
-    while(*s)
+    if (s != NULL)
     {
-        if(*s == '\n' || *s == '\r') return NULL;
-        if(isspace(*s)) { ++s; continue; }
-        return s;
+        while(*s)
+        {
+            if(*s == '\n' || *s == '\r') return NULL;
+            if(isspace(*s)) { ++s; continue; }
+            return s;
+        }
     }
     return NULL;
 }
@@ -1377,7 +1380,7 @@ static char *skip_idf(char *start, char out_idf[256])
 
 static void read_pnm_header(FILE *reader, struct pnm_header *ph)
 {
-    int format, have_wh, end, ttype;
+    int format, end, ttype;
     char idf[256], type[256];
     char line[256];
 
@@ -1398,11 +1401,12 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
         return;
     }
     ph->format = format;
-    ttype = end = have_wh = 0;
+    ttype = end = 0;
 
     while(fgets(line, 250, reader))
     {
         char *s;
+        int allow_null = 0;
 
         if(*line == '#') continue;
 
@@ -1478,36 +1482,25 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
             return;
         } /* if(format == 7) */
 
-        if( !have_wh)
-        {
+        /* Here format is in range [1,6] */
+        if (ph->width == 0) {
             s = skip_int(s, &ph->width);
-
+            if ((s == NULL) || (*s == 0) || (ph->width < 1)) return;
+            allow_null = 1;
+        }
+        if (ph->height == 0) {
             s = skip_int(s, &ph->height);
-
-            have_wh = 1;
-
-            if(format == 1 || format == 4) break;
-                                       
-            if(format == 2 || format == 3 || format == 5 || format == 6)
-            {
-                if (skip_int(s, &ph->maxval) != NULL) {
-                    if(ph->maxval > 65535) {
-                        return;
-                    }
-                    else {
-                        break;
-                    }
-                }
+            if ((s == NULL) && allow_null) continue;
+            if ((s == NULL) || (*s == 0) || (ph->height < 1)) return;
+            if(format == 1 || format == 4) {
+                break;
             }
-            continue;
-        }
-        if(format == 2 || format == 3 || format == 5 || format == 6)
-        {
-            /* P2, P3, P5, P6: */
-            s = skip_int(s, &ph->maxval);
-
-            if(ph->maxval > 65535) return;
+            allow_null = 1;
         }
+        /* here, format is in P2, P3, P5, P6 */
+        s = skip_int(s, &ph->maxval);
+        if ((s == NULL) && allow_null) continue;
+        if ((s == NULL) || (*s == 0)) return;
         break;
     }/* while(fgets( ) */
     if(format == 2 || format == 3 || format > 4)
@@ -1524,18 +1517,14 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
         }
         if(ph->depth < 1 || ph->depth > 4) return;
 
-        if(ph->width && ph->height && ph->depth && ph->maxval && ttype)
+        if (ttype)
             ph->ok = 1;
     }
     else
     {
-        if(format != 1 && format != 4)
-        {
-            if(ph->width && ph->height && ph->maxval) ph->ok = 1;
-        }
-        else
+        ph->ok = 1;
+        if(format == 1 || format == 4)
         {
-            if(ph->width && ph->height) ph->ok = 1;
             ph->maxval = 255;
         }
     }
index bd22c91f9827c8089df78408083a08377c36444a..9ffae14574f56ab17cc0f8014613fcafcb3e8de1 100644 (file)
@@ -146,6 +146,8 @@ opj_compress -i @INPUT_NR_PATH@/flower-minisblack-11.tif -o @TEMP_PATH@/flower-m
 opj_compress -i @INPUT_NR_PATH@/flower-minisblack-13.tif -o @TEMP_PATH@/flower-minisblack-13.tif.jp2
 opj_compress -i @INPUT_NR_PATH@/flower-minisblack-15.tif -o @TEMP_PATH@/flower-minisblack-15.tif.jp2
 
+# issue 843 Crash with invalid ppm file
+!opj_compress -i @INPUT_NR_PATH@/issue843.ppm -o @TEMP_PATH@/issue843.ppm.jp2
 
 # DECODER TEST SUITE
 opj_decompress -i  @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx