diff --git a/ANNOUNCE b/ANNOUNCE index 69fc981f..db820e0e 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -51,6 +51,9 @@ version 1.2.54beta01 [July 30, 2015] Avoid Coverity issue 80858 (REVERSE NULL) in pngtest.c PNG_DEBUG builds. Removed WRITE_WEIGHTED_FILTERED code. Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). + Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c + Use nanosleep() instead of usleep() in contrib/gregbook/rpng2-x.c + because usleep() is deprecated (port from libpng16). Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/CHANGES b/CHANGES index c6f64154..88a4b7e2 100644 --- a/CHANGES +++ b/CHANGES @@ -2866,6 +2866,9 @@ version 1.2.54beta01 [July 30, 2015] Avoid Coverity issue 80858 (REVERSE NULL) in pngtest.c PNG_DEBUG builds. Removed WRITE_WEIGHTED_FILTERED code. Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). + Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c + Use nanosleep() instead of usleep() in contrib/gregbook/rpng2-x.c + because usleep() is deprecated (port from libpng16). Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/contrib/pngminus/pnm2png.c b/contrib/pngminus/pnm2png.c index 4cdfad83..8fa64cd1 100644 --- a/contrib/pngminus/pnm2png.c +++ b/contrib/pngminus/pnm2png.c @@ -3,6 +3,7 @@ * copyright (C) 1999 by Willem van Schaik * * version 1.0 - 1999.10.15 - First version. + * version 1.1 - 2015.07.29 - Fixed leaks (Glenn Randers-Pehrson) * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, @@ -18,6 +19,7 @@ #include #include #endif +#include #ifndef BOOL #define BOOL unsigned char @@ -49,7 +51,8 @@ int main (int argc, char *argv[]); void usage (); -BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha); +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, + BOOL alpha); void get_token(FILE *pnm_file, char *token); png_uint_32 get_data (FILE *pnm_file, int depth); png_uint_32 get_value (FILE *pnm_file, int depth); @@ -175,7 +178,8 @@ void usage() fprintf (stderr, " or: ... | pnm2png [options]\n"); fprintf (stderr, "Options:\n"); fprintf (stderr, " -i[nterlace] write png-file with interlacing on\n"); - fprintf (stderr, " -a[lpha] .pgm read PNG alpha channel as pgm-file\n"); + fprintf (stderr, + " -a[lpha] .pgm read PNG alpha channel as pgm-file\n"); fprintf (stderr, " -h | -? print this help-information\n"); } @@ -183,29 +187,36 @@ void usage() * pnm2png */ -BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha) +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, + BOOL alpha) { png_struct *png_ptr = NULL; png_info *info_ptr = NULL; png_byte *png_pixels = NULL; png_byte **row_pointers = NULL; png_byte *pix_ptr = NULL; - png_uint_32 row_bytes; + volatile png_uint_32 row_bytes; char type_token[16]; char width_token[16]; char height_token[16]; char maxval_token[16]; - int color_type; - png_uint_32 width, alpha_width; - png_uint_32 height, alpha_height; + volatile int color_type=1; + unsigned long ul_width=0, ul_alpha_width=0; + unsigned long ul_height=0, ul_alpha_height=0; + unsigned long ul_maxval=0; + volatile png_uint_32 width=0, height=0; + volatile png_uint_32 alpha_width=0, alpha_height=0; png_uint_32 maxval; - int bit_depth = 0; - int channels; + volatile int bit_depth = 0; + int channels=0; int alpha_depth = 0; - int alpha_present; + int alpha_present=0; int row, col; BOOL raw, alpha_raw = FALSE; +#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) + BOOL packed_bitmap = FALSE; +#endif png_uint_32 tmp16; int i; @@ -218,20 +229,36 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, } else if ((type_token[1] == '1') || (type_token[1] == '4')) { +#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); + sscanf (width_token, "%lu", &ul_width); + width = (png_uint_32) ul_width; + get_token(pnm_file, height_token); + sscanf (height_token, "%lu", &ul_height); + height = (png_uint_32) ul_height; bit_depth = 1; + packed_bitmap = TRUE; +#else + fprintf (stderr, "PNM2PNG built without PNG_WRITE_INVERT_SUPPORTED and \n"); + fprintf (stderr, "PNG_WRITE_PACK_SUPPORTED can't read PBM (P1,P4) files\n"); +#endif } else if ((type_token[1] == '2') || (type_token[1] == '5')) { raw = (type_token[1] == '5'); color_type = PNG_COLOR_TYPE_GRAY; get_token(pnm_file, width_token); - sscanf (width_token, "%lu", &width); + sscanf (width_token, "%lu", &ul_width); + width = (png_uint_32) ul_width; get_token(pnm_file, height_token); - sscanf (height_token, "%lu", &height); + sscanf (height_token, "%lu", &ul_height); + height = (png_uint_32) ul_height; get_token(pnm_file, maxval_token); - sscanf (maxval_token, "%lu", &maxval); + sscanf (maxval_token, "%lu", &ul_maxval); + maxval = (png_uint_32) ul_maxval; + if (maxval <= 1) bit_depth = 1; else if (maxval <= 3) @@ -248,11 +275,14 @@ 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); - sscanf (width_token, "%lu", &width); + sscanf (width_token, "%lu", &ul_width); + width = (png_uint_32) ul_width; get_token(pnm_file, height_token); - sscanf (height_token, "%lu", &height); + sscanf (height_token, "%lu", &ul_height); + height = (png_uint_32) ul_height; get_token(pnm_file, maxval_token); - sscanf (maxval_token, "%lu", &maxval); + sscanf (maxval_token, "%lu", &ul_maxval); + maxval = (png_uint_32) ul_maxval; if (maxval <= 1) bit_depth = 1; else if (maxval <= 3) @@ -287,15 +317,18 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, { alpha_raw = (type_token[1] == '5'); get_token(alpha_file, width_token); - sscanf (width_token, "%lu", &alpha_width); + 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); - sscanf (height_token, "%lu", &alpha_height); + 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); - sscanf (maxval_token, "%lu", &maxval); + sscanf (maxval_token, "%lu", &ul_maxval); + maxval = (png_uint_32) ul_maxval; if (maxval <= 1) alpha_depth = 1; else if (maxval <= 3) @@ -324,76 +357,108 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, channels = 3; else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) channels = 4; +#if 0 else - channels = 0; /* should not happen */ + channels = 0; /* cannot happen */ +#endif alpha_present = (channels - 1) % 2; - /* row_bytes is the width x number of channels x (bit-depth / 8) */ - row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); +#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) + if (packed_bitmap) + /* row data is as many bytes as can fit width x channels x bit_depth */ + row_bytes = (width * channels * bit_depth + 7) / 8; + else +#endif + /* row_bytes is the width x number of channels x (bit-depth / 8) */ + row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); - if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) + if ((png_pixels = (png_byte *) + malloc (row_bytes * height * sizeof (png_byte))) == NULL) return FALSE; /* read data from PNM file */ pix_ptr = png_pixels; - for (row = 0; row < height; row++) + for (row = 0; row < (int) height; row++) { - for (col = 0; col < width; col++) +#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) + if (packed_bitmap) { + for (i = 0; i < (int) row_bytes; i++) + /* png supports this format natively so no conversion is needed */ + *pix_ptr++ = get_data (pnm_file, 8); + } else +#endif { - for (i = 0; i < (channels - alpha_present); i++) + for (col = 0; col < (int) width; col++) { - if (raw) - *pix_ptr++ = get_data (pnm_file, bit_depth); - else - if (bit_depth <= 8) - *pix_ptr++ = get_value (pnm_file, bit_depth); + for (i = 0; i < (channels - alpha_present); i++) + { + if (raw) + *pix_ptr++ = get_data (pnm_file, bit_depth); else - { - tmp16 = get_value (pnm_file, bit_depth); - *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF); - pix_ptr++; - *pix_ptr = (png_byte) (tmp16 & 0xFF); - pix_ptr++; - } - } + if (bit_depth <= 8) + *pix_ptr++ = get_value (pnm_file, bit_depth); + else + { + tmp16 = get_value (pnm_file, bit_depth); + *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF); + pix_ptr++; + *pix_ptr = (png_byte) (tmp16 & 0xFF); + pix_ptr++; + } + } - if (alpha) /* read alpha-channel from pgm file */ - { - if (alpha_raw) - *pix_ptr++ = get_data (alpha_file, alpha_depth); - else - if (alpha_depth <= 8) - *pix_ptr++ = get_value (alpha_file, bit_depth); + if (alpha) /* read alpha-channel from pgm file */ + { + if (alpha_raw) + *pix_ptr++ = get_data (alpha_file, alpha_depth); else - { - tmp16 = get_value (alpha_file, bit_depth); - *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); - *pix_ptr++ = (png_byte) (tmp16 & 0xFF); - } - } /* if alpha */ - + if (alpha_depth <= 8) + *pix_ptr++ = get_value (alpha_file, bit_depth); + else + { + tmp16 = get_value (alpha_file, bit_depth); + *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); + *pix_ptr++ = (png_byte) (tmp16 & 0xFF); + } + } /* if alpha */ + } /* if packed_bitmap */ } /* end for col */ } /* end for row */ /* prepare the standard PNG structures */ - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_write_struct (png_get_libpng_ver(NULL), NULL, NULL, + NULL); if (!png_ptr) { + free (png_pixels); + png_pixels = NULL; return FALSE; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + free (png_pixels); + png_pixels = NULL; return FALSE; } +#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) + if (packed_bitmap == TRUE) + { + png_set_packing (png_ptr); + png_set_invert_mono (png_ptr); + } +#endif + /* setjmp() must be called in every function that calls a PNG-reading libpng function */ if (setjmp (png_jmpbuf(png_ptr))) { - png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + png_destroy_write_struct (&png_ptr, &info_ptr); + free (png_pixels); + png_pixels = NULL; return FALSE; } @@ -411,25 +476,28 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, /* if needed we will allocate memory for an new array of row-pointers */ if (row_pointers == (unsigned char**) NULL) { - if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) + if ((row_pointers = (png_byte **) + malloc (height * sizeof (png_bytep))) == NULL) { - png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + png_destroy_write_struct (&png_ptr, &info_ptr); + free (png_pixels); + png_pixels = NULL; return FALSE; } } /* set the individual row_pointers to point at the correct offsets */ - for (i = 0; i < (height); i++) + for (i = 0; i < (int) height; i++) row_pointers[i] = png_pixels + i * row_bytes; /* write out the entire image data in one call */ png_write_image (png_ptr, row_pointers); - /* write the additional chuncks to the PNG file (not really needed) */ + /* write the additional chunks to the PNG file (not really needed) */ png_write_end (png_ptr, info_ptr); /* clean up after the write, and free any memory allocated */ - png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + png_destroy_write_struct (&png_ptr, &info_ptr); if (row_pointers != (unsigned char**) NULL) free (row_pointers); @@ -446,19 +514,32 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, void get_token(FILE *pnm_file, char *token) { int i = 0; + int ret; - /* remove white-space */ + /* remove white-space and comment lines */ do { - token[i] = (unsigned char) fgetc (pnm_file); + ret = fgetc(pnm_file); + if (ret == '#') { + /* the rest of this line is a comment */ + do + { + ret = fgetc(pnm_file); + } + while ((ret != '\n') && (ret != '\r') && (ret != EOF)); + } + if (ret == EOF) break; + token[i] = (unsigned char) ret; } while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); /* read string */ do { + ret = fgetc(pnm_file); + if (ret == EOF) break; i++; - token[i] = (unsigned char) fgetc (pnm_file); + token[i] = (unsigned char) ret; } while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); @@ -510,6 +591,7 @@ png_uint_32 get_value (FILE *pnm_file, int depth) { static png_uint_32 mask = 0; png_byte token[16]; + unsigned long ul_ret_value; png_uint_32 ret_value; int i = 0; @@ -518,7 +600,8 @@ png_uint_32 get_value (FILE *pnm_file, int depth) mask = (mask << 1) | 0x01; get_token (pnm_file, (char *) token); - sscanf ((const char *) token, "%lu", &ret_value); + sscanf ((const char *) token, "%lu", &ul_ret_value); + ret_value = (png_uint_32) ul_ret_value; ret_value &= mask;