diff options
Diffstat (limited to 'contrib/pngminus/pnm2png.c')
-rw-r--r-- | contrib/pngminus/pnm2png.c | 258 |
1 files changed, 138 insertions, 120 deletions
diff --git a/contrib/pngminus/pnm2png.c b/contrib/pngminus/pnm2png.c index a2c2551da..0d2caef96 100644 --- a/contrib/pngminus/pnm2png.c +++ b/contrib/pngminus/pnm2png.c @@ -1,14 +1,29 @@ /* * pnm2png.c --- conversion from PBM/PGM/PPM-file to PNG-file - * copyright (C) 1999-2019 by Willem van Schaik <willem at schaik dot com> + * copyright (C) 1999,2015,2017 by Willem van Schaik <willem at schaik.com> * - * This software is released under the MIT license. For conditions of - * distribution and use, see the LICENSE file part of this package. + * version 1.0 - 1999.10.15 - First version. + * version 1.1 - 2015.07.29 - Fixed leaks (Glenn Randers-Pehrson) + * version 1.2 - 2017.04.22 - Add buffer-size check + * 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) + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. This software is provided "as is" without + * express or implied warranty. */ #include <stdio.h> #include <stdlib.h> +#ifdef __TURBOC__ +#include <mem.h> #include <fcntl.h> +#endif +#include <zlib.h> #ifndef BOOL #define BOOL unsigned char @@ -20,20 +35,38 @@ #define FALSE (BOOL) 0 #endif -/* make pnm2png verbose so we can find problems (needs to be before png.h) */ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +/* to make pnm2png verbose so we can find problems (needs to be before png.h) */ #ifndef PNG_DEBUG #define PNG_DEBUG 0 #endif #include "png.h" +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +#ifndef PNGMINUS_UNUSED +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). + */ +# define PNGMINUS_UNUSED(param) (void)param +#endif + + /* function prototypes */ -int main (int argc, char *argv[]); +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_buf, size_t token_buf_size); +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); @@ -41,7 +74,7 @@ png_uint_32 get_value (FILE *pnm_file, int depth); * main */ -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { FILE *fp_rd = stdin; FILE *fp_al = NULL; @@ -66,20 +99,20 @@ int main (int argc, char *argv[]) { fprintf (stderr, "PNM2PNG\n"); fprintf (stderr, "Error: alpha-channel file %s does not exist\n", - argv[argi]); + argv[argi]); exit (1); } break; case 'h': case '?': - usage (); - exit (0); + usage(); + exit(0); break; default: fprintf (stderr, "PNM2PNG\n"); fprintf (stderr, "Error: unknown option %s\n", argv[argi]); - usage (); - exit (1); + usage(); + exit(1); break; } /* end switch */ } @@ -97,7 +130,7 @@ int main (int argc, char *argv[]) if ((fp_wr = fopen (argv[argi], "wb")) == NULL) { fprintf (stderr, "PNM2PNG\n"); - fprintf (stderr, "Error: cannot create PNG-file %s\n", argv[argi]); + fprintf (stderr, "Error: can not create PNG-file %s\n", argv[argi]); exit (1); } } @@ -105,19 +138,21 @@ int main (int argc, char *argv[]) { fprintf (stderr, "PNM2PNG\n"); fprintf (stderr, "Error: too many parameters\n"); - usage (); + usage(); exit (1); } } /* end for */ -#if defined(O_BINARY) && (O_BINARY != 0) - /* set stdin/stdout to binary, - * we're reading the PNM always! in binary format - */ +#ifdef __TURBOC__ + /* set stdin/stdout to binary, we're reading the PNM always! in binary format */ if (fp_rd == stdin) - setmode (fileno (stdin), O_BINARY); + { + setmode (STDIN, O_BINARY); + } if (fp_wr == stdout) - setmode (fileno (stdout), O_BINARY); + { + setmode (STDOUT, O_BINARY); + } #endif /* call the conversion program itself */ @@ -143,10 +178,15 @@ int main (int argc, char *argv[]) * usage */ -void usage () +void usage() { fprintf (stderr, "PNM2PNG\n"); fprintf (stderr, " by Willem van Schaik, 1999\n"); +#ifdef __TURBOC__ + fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); +#else + fprintf (stderr, " for Linux (and Unix) compilers\n"); +#endif fprintf (stderr, "Usage: pnm2png [options] <file>.<pnm> [<file>.png]\n"); fprintf (stderr, " or: ... | pnm2png [options]\n"); fprintf (stderr, "Options:\n"); @@ -160,31 +200,31 @@ 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; - volatile 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]; - 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; + 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; - volatile int bit_depth = 0; - int channels = 0; + volatile int bit_depth = 0; + int channels=0; int alpha_depth = 0; - int alpha_present = 0; + int alpha_present=0; int row, col; BOOL raw, alpha_raw = FALSE; #if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) @@ -195,7 +235,7 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, /* read header of PNM file */ - get_token (pnm_file, type_token, sizeof (type_token)); + get_token(pnm_file, type_token); if (type_token[0] != 'P') { return FALSE; @@ -205,31 +245,30 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, #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, sizeof (width_token)); + get_token(pnm_file, width_token); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token (pnm_file, height_token, sizeof (height_token)); + 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, "PNM2PNG built without PNG_WRITE_INVERT_SUPPORTED and \n"); fprintf (stderr, "PNG_WRITE_PACK_SUPPORTED can't read PBM (P1,P4) files\n"); - return FALSE; #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, sizeof (width_token)); + get_token(pnm_file, width_token); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token (pnm_file, height_token, sizeof (height_token)); + get_token(pnm_file, height_token); sscanf (height_token, "%lu", &ul_height); height = (png_uint_32) ul_height; - get_token (pnm_file, maxval_token, sizeof (maxval_token)); + get_token(pnm_file, maxval_token); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; @@ -241,22 +280,20 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, bit_depth = 4; else if (maxval <= 255) bit_depth = 8; - else if (maxval <= 65535U) + else /* if (maxval <= 65535) */ bit_depth = 16; - else /* maxval > 65535U */ - return FALSE; } else if ((type_token[1] == '3') || (type_token[1] == '6')) { raw = (type_token[1] == '6'); color_type = PNG_COLOR_TYPE_RGB; - get_token (pnm_file, width_token, sizeof (width_token)); + get_token(pnm_file, width_token); sscanf (width_token, "%lu", &ul_width); width = (png_uint_32) ul_width; - get_token (pnm_file, height_token, sizeof (height_token)); + get_token(pnm_file, height_token); sscanf (height_token, "%lu", &ul_height); height = (png_uint_32) ul_height; - get_token (pnm_file, maxval_token, sizeof (maxval_token)); + get_token(pnm_file, maxval_token); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; if (maxval <= 1) @@ -267,10 +304,8 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, bit_depth = 4; else if (maxval <= 255) bit_depth = 8; - else if (maxval <= 65535U) + else /* if (maxval <= 65535) */ bit_depth = 16; - else /* maxval > 65535U */ - return FALSE; } else { @@ -286,7 +321,7 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, if (color_type == PNG_COLOR_TYPE_RGB) color_type = PNG_COLOR_TYPE_RGB_ALPHA; - get_token (alpha_file, type_token, sizeof (type_token)); + get_token(alpha_file, type_token); if (type_token[0] != 'P') { return FALSE; @@ -294,17 +329,17 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, else if ((type_token[1] == '2') || (type_token[1] == '5')) { alpha_raw = (type_token[1] == '5'); - get_token (alpha_file, width_token, sizeof (width_token)); + get_token(alpha_file, width_token); sscanf (width_token, "%lu", &ul_alpha_width); - alpha_width = (png_uint_32) ul_alpha_width; + alpha_width=(png_uint_32) ul_alpha_width; if (alpha_width != width) return FALSE; - get_token (alpha_file, height_token, sizeof (height_token)); + get_token(alpha_file, 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, sizeof (maxval_token)); + get_token(alpha_file, maxval_token); sscanf (maxval_token, "%lu", &ul_maxval); maxval = (png_uint_32) ul_maxval; if (maxval <= 1) @@ -315,10 +350,8 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, alpha_depth = 4; else if (maxval <= 255) alpha_depth = 8; - else if (maxval <= 65535U) + else /* if (maxval <= 65535) */ alpha_depth = 16; - else /* maxval > 65535U */ - return FALSE; if (alpha_depth != bit_depth) return FALSE; } @@ -346,29 +379,21 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, #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 is the width x number of channels x (bit-depth / 8) */ row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); - } - if ((row_bytes == 0) || - ((size_t) height > (size_t) (-1) / (size_t) row_bytes)) + if ((row_bytes == 0 || (size_t)height > ((size_t)(-1))/(size_t)row_bytes)) { - /* too big */ + /* too big */ return FALSE; } if ((png_pixels = (png_byte *) - malloc ((size_t) row_bytes * (size_t) height)) == NULL) - { - /* out of memory */ + malloc ((size_t)row_bytes * (size_t)height * sizeof (png_byte))) == NULL) return FALSE; - } /* read data from PNM file */ pix_ptr = png_pixels; @@ -379,12 +404,9 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, 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 + } else #endif { for (col = 0; col < (int) width; col++) @@ -392,15 +414,10 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, for (i = 0; i < (channels - alpha_present); i++) { if (raw) - { *pix_ptr++ = get_data (pnm_file, bit_depth); - } else - { if (bit_depth <= 8) - { *pix_ptr++ = get_value (pnm_file, bit_depth); - } else { tmp16 = get_value (pnm_file, bit_depth); @@ -409,46 +426,41 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, *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); - } else { tmp16 = get_value (alpha_file, bit_depth); *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); *pix_ptr++ = (png_byte) (tmp16 & 0xFF); } - } - } /* end if alpha */ - } /* end if packed_bitmap */ + } /* if alpha */ + } /* if packed_bitmap */ } /* end for col */ } /* end for row */ /* prepare the standard PNG structures */ - png_ptr = png_create_write_struct (png_get_libpng_ver(NULL), - 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, NULL); + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); free (png_pixels); + png_pixels = NULL; return FALSE; } @@ -460,10 +472,12 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, } #endif - if (setjmp (png_jmpbuf (png_ptr))) + /* 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, &info_ptr); free (png_pixels); + png_pixels = NULL; return FALSE; } @@ -472,20 +486,21 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, /* we're going to write more or less the same PNG as the input file */ png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, - (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* write the file header information */ png_write_info (png_ptr, info_ptr); /* if needed we will allocate memory for an new array of row-pointers */ - if (row_pointers == NULL) + if (row_pointers == (unsigned char**) NULL) { if ((row_pointers = (png_byte **) - malloc (height * sizeof (png_byte *))) == NULL) + malloc (height * sizeof (png_bytep))) == NULL) { png_destroy_write_struct (&png_ptr, &info_ptr); free (png_pixels); + png_pixels = NULL; return FALSE; } } @@ -503,60 +518,62 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, /* clean up after the write, and free any memory allocated */ png_destroy_write_struct (&png_ptr, &info_ptr); - if (row_pointers != NULL) + if (row_pointers != (unsigned char**) NULL) free (row_pointers); - if (png_pixels != NULL) + if (png_pixels != (unsigned char*) NULL) free (png_pixels); + PNGMINUS_UNUSED(raw); /* Quiet a Coverity defect */ + return TRUE; } /* end of pnm2png */ /* - * get_token - gets the first string after whitespace + * get_token() - gets the first string after whitespace */ -void get_token (FILE *pnm_file, char *token_buf, size_t token_buf_size) +void get_token(FILE *pnm_file, char *token) { - size_t i = 0; + int i = 0; int ret; /* remove white-space and comment lines */ do { - ret = fgetc (pnm_file); + ret = fgetc(pnm_file); if (ret == '#') { /* the rest of this line is a comment */ do { - ret = fgetc (pnm_file); + ret = fgetc(pnm_file); } while ((ret != '\n') && (ret != '\r') && (ret != EOF)); } if (ret == EOF) break; - token_buf[i] = (char) ret; + token[i] = (unsigned char) ret; } - while ((ret == '\n') || (ret == '\r') || (ret == ' ')); + while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); /* read string */ do { - ret = fgetc (pnm_file); + ret = fgetc(pnm_file); if (ret == EOF) break; - if (++i == token_buf_size - 1) break; - token_buf[i] = (char) ret; + i++; + token[i] = (unsigned char) ret; } - while ((ret != '\n') && (ret != '\r') && (ret != ' ')); + while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); - token_buf[i] = '\0'; + token[i] = '\0'; return; } /* - * get_data - takes first byte and converts into next pixel value, - * taking as much bits as defined by bit-depth and - * using the bit-depth to fill up a byte (0Ah -> AAh) + * get_data() - takes first byte and converts into next pixel value, + * taking as much bits as defined by bit-depth and + * using the bit-depth to fill up a byte (0Ah -> AAh) */ png_uint_32 get_data (FILE *pnm_file, int depth) @@ -588,14 +605,14 @@ png_uint_32 get_data (FILE *pnm_file, int depth) } /* - * get_value - takes first (numeric) string and converts into number, - * using the bit-depth to fill up a byte (0Ah -> AAh) + * get_value() - takes first (numeric) string and converts into number, + * using the bit-depth to fill up a byte (0Ah -> AAh) */ png_uint_32 get_value (FILE *pnm_file, int depth) { static png_uint_32 mask = 0; - char token[16]; + png_byte token[16]; unsigned long ul_ret_value; png_uint_32 ret_value; int i = 0; @@ -604,8 +621,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, token, sizeof (token)); - sscanf (token, "%lu", &ul_ret_value); + get_token (pnm_file, (char *) token); + sscanf ((const char *) token, "%lu", &ul_ret_value); ret_value = (png_uint_32) ul_ret_value; ret_value &= mask; @@ -618,3 +635,4 @@ png_uint_32 get_value (FILE *pnm_file, int depth) } /* end of source */ + |