From f053508f6fc26aa95839f747bc7cbf257bd43996 Mon Sep 17 00:00:00 2001 From: Matthieu Darbois Date: Thu, 22 Sep 2016 00:30:34 +0200 Subject: [PATCH] Fix PNM file reading (#847) 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 | 67 +++++++++++-------------- tests/nonregression/test_suite.ctest.in | 2 + 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/bin/jp2/convert.c b/src/bin/jp2/convert.c index c130b3bf..deee4f6e 100644 --- a/src/bin/jp2/convert.c +++ b/src/bin/jp2/convert.c @@ -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) + ph->ok = 1; + if(format == 1 || format == 4) { - if(ph->width && ph->height && ph->maxval) ph->ok = 1; - } - else - { - if(ph->width && ph->height) ph->ok = 1; ph->maxval = 255; } } diff --git a/tests/nonregression/test_suite.ctest.in b/tests/nonregression/test_suite.ctest.in index bd22c91f..9ffae145 100644 --- a/tests/nonregression/test_suite.ctest.in +++ b/tests/nonregression/test_suite.ctest.in @@ -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