From 1f0221fad7e7888ada87eda511dcbfd701de7d21 Mon Sep 17 00:00:00 2001 From: Cosmin Truta Date: Sun, 5 Aug 2018 19:40:09 -0400 Subject: [PATCH] pngminus: Fix a buffer overflow in tokenizer --- contrib/pngminus/pnm2png.c | 51 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/contrib/pngminus/pnm2png.c b/contrib/pngminus/pnm2png.c index 0d2caef96..e72008540 100644 --- a/contrib/pngminus/pnm2png.c +++ b/contrib/pngminus/pnm2png.c @@ -8,6 +8,7 @@ * 1.3 - 2017.08.24 - Fix potential overflow in buffer-size check * (Glenn Randers-Pehrson) * 1.4 - 2017.08.28 - Add PNGMINUS_UNUSED (Christian Hesse) + * 1.5 - 2018.08.05 - Fix buffer overflow in tokenizer (Cosmin Truta) * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, @@ -66,7 +67,7 @@ int main (int argc, char *argv[]); void usage (); BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha); -void get_token(FILE *pnm_file, char *token); +void get_token(FILE *pnm_file, char *token_buf, size_t token_buf_size); png_uint_32 get_data (FILE *pnm_file, int depth); png_uint_32 get_value (FILE *pnm_file, int depth); @@ -235,7 +236,7 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, /* read header of PNM file */ - get_token(pnm_file, type_token); + get_token(pnm_file, type_token, sizeof (type_token)); if (type_token[0] != 'P') { return FALSE; @@ -245,10 +246,10 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, #if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) raw = (type_token[1] == '4'); color_type = PNG_COLOR_TYPE_GRAY; - get_token(pnm_file, width_token); + get_token(pnm_file, width_token, sizeof (width_token)); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token(pnm_file, height_token); + get_token(pnm_file, height_token, sizeof (height_token)); sscanf (height_token, "%lu", &ul_height); height = (png_uint_32) ul_height; bit_depth = 1; @@ -262,13 +263,13 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, { raw = (type_token[1] == '5'); color_type = PNG_COLOR_TYPE_GRAY; - get_token(pnm_file, width_token); + get_token(pnm_file, width_token, sizeof (width_token)); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token(pnm_file, height_token); + get_token(pnm_file, height_token, sizeof (height_token)); sscanf (height_token, "%lu", &ul_height); height = (png_uint_32) ul_height; - get_token(pnm_file, maxval_token); + get_token(pnm_file, maxval_token, sizeof (maxval_token)); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; @@ -287,13 +288,13 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, { raw = (type_token[1] == '6'); color_type = PNG_COLOR_TYPE_RGB; - get_token(pnm_file, width_token); + get_token(pnm_file, width_token, sizeof (width_token)); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token(pnm_file, height_token); + get_token(pnm_file, height_token, sizeof (height_token)); sscanf (height_token, "%lu", &ul_height); height = (png_uint_32) ul_height; - get_token(pnm_file, maxval_token); + get_token(pnm_file, maxval_token, sizeof (maxval_token)); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; if (maxval <= 1) @@ -321,7 +322,7 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, if (color_type == PNG_COLOR_TYPE_RGB) color_type = PNG_COLOR_TYPE_RGB_ALPHA; - get_token(alpha_file, type_token); + get_token(alpha_file, type_token, sizeof (type_token)); if (type_token[0] != 'P') { return FALSE; @@ -329,17 +330,17 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, else if ((type_token[1] == '2') || (type_token[1] == '5')) { alpha_raw = (type_token[1] == '5'); - get_token(alpha_file, width_token); + get_token(alpha_file, width_token, sizeof (width_token)); sscanf (width_token, "%lu", &ul_alpha_width); alpha_width=(png_uint_32) ul_alpha_width; if (alpha_width != width) return FALSE; - get_token(alpha_file, height_token); + get_token(alpha_file, height_token, sizeof (height_token)); sscanf (height_token, "%lu", &ul_alpha_height); alpha_height = (png_uint_32) ul_alpha_height; if (alpha_height != height) return FALSE; - get_token(alpha_file, maxval_token); + get_token(alpha_file, maxval_token, sizeof (maxval_token)); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; if (maxval <= 1) @@ -532,9 +533,9 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, * get_token() - gets the first string after whitespace */ -void get_token(FILE *pnm_file, char *token) +void get_token(FILE *pnm_file, char *token_buf, size_t token_buf_size) { - int i = 0; + size_t i = 0; int ret; /* remove white-space and comment lines */ @@ -551,21 +552,21 @@ void get_token(FILE *pnm_file, char *token) while ((ret != '\n') && (ret != '\r') && (ret != EOF)); } if (ret == EOF) break; - token[i] = (unsigned char) ret; + token_buf[i] = (char) ret; } - while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); + while ((ret == '\n') || (ret == '\r') || (ret == ' ')); /* read string */ do { ret = fgetc(pnm_file); if (ret == EOF) break; - i++; - token[i] = (unsigned char) ret; + if (++i == token_buf_size - 1) break; + token_buf[i] = (char) ret; } - while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); + while ((ret != '\n') && (ret != '\r') && (ret != ' ')); - token[i] = '\0'; + token_buf[i] = '\0'; return; } @@ -612,7 +613,7 @@ png_uint_32 get_data (FILE *pnm_file, int depth) png_uint_32 get_value (FILE *pnm_file, int depth) { static png_uint_32 mask = 0; - png_byte token[16]; + char token[16]; unsigned long ul_ret_value; png_uint_32 ret_value; int i = 0; @@ -621,8 +622,8 @@ png_uint_32 get_value (FILE *pnm_file, int depth) for (i = 0; i < depth; i++) mask = (mask << 1) | 0x01; - get_token (pnm_file, (char *) token); - sscanf ((const char *) token, "%lu", &ul_ret_value); + get_token (pnm_file, token, sizeof (token)); + sscanf (token, "%lu", &ul_ret_value); ret_value = (png_uint_32) ul_ret_value; ret_value &= mask;