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
This commit is contained in:
Matthieu Darbois 2016-09-22 00:30:34 +02:00 committed by Mathieu Malaterre
parent 7a5fb35b8d
commit f053508f6f
2 changed files with 30 additions and 39 deletions

View File

@ -1328,11 +1328,14 @@ struct pnm_header
static char *skip_white(char *s) static char *skip_white(char *s)
{ {
while(*s) if (s != NULL)
{ {
if(*s == '\n' || *s == '\r') return NULL; while(*s)
if(isspace(*s)) { ++s; continue; } {
return s; if(*s == '\n' || *s == '\r') return NULL;
if(isspace(*s)) { ++s; continue; }
return s;
}
} }
return NULL; 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) 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 idf[256], type[256];
char line[256]; char line[256];
@ -1398,11 +1401,12 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
return; return;
} }
ph->format = format; ph->format = format;
ttype = end = have_wh = 0; ttype = end = 0;
while(fgets(line, 250, reader)) while(fgets(line, 250, reader))
{ {
char *s; char *s;
int allow_null = 0;
if(*line == '#') continue; if(*line == '#') continue;
@ -1478,36 +1482,25 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
return; return;
} /* if(format == 7) */ } /* if(format == 7) */
if( !have_wh) /* Here format is in range [1,6] */
{ if (ph->width == 0) {
s = skip_int(s, &ph->width); 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); s = skip_int(s, &ph->height);
if ((s == NULL) && allow_null) continue;
have_wh = 1; if ((s == NULL) || (*s == 0) || (ph->height < 1)) return;
if(format == 1 || format == 4) {
if(format == 1 || format == 4) break; break;
if(format == 2 || format == 3 || format == 5 || format == 6)
{
if (skip_int(s, &ph->maxval) != NULL) {
if(ph->maxval > 65535) {
return;
}
else {
break;
}
}
} }
continue; allow_null = 1;
}
if(format == 2 || format == 3 || format == 5 || format == 6)
{
/* P2, P3, P5, P6: */
s = skip_int(s, &ph->maxval);
if(ph->maxval > 65535) return;
} }
/* 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; break;
}/* while(fgets( ) */ }/* while(fgets( ) */
if(format == 2 || format == 3 || format > 4) 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->depth < 1 || ph->depth > 4) return;
if(ph->width && ph->height && ph->depth && ph->maxval && ttype) if (ttype)
ph->ok = 1; ph->ok = 1;
} }
else 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; ph->maxval = 255;
} }
} }

View 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-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 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 # DECODER TEST SUITE
opj_decompress -i @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx opj_decompress -i @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx