From 5d96d3c0c22088d20528fb0f0b126d175ec8a09f Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 27 Jun 2020 17:03:16 +0000 Subject: Release 10.73.32 git-svn-id: http://svn.code.sf.net/p/netpbm/code/super_stable@3869 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- buildtools/debian/mkdeb | 43 +++- converter/other/cameratopam/identify.c | 5 +- converter/pbm/pbmtonokia.c | 3 +- converter/ppm/picttoppm.c | 3 +- converter/ppm/pjtoppm.c | 26 ++- converter/ppm/ppmtompeg/iframe.c | 8 +- converter/ppm/ppmtompeg/mpeg.c | 5 +- converter/ppm/ppmtompeg/opts.c | 23 ++- converter/ppm/ppmtompeg/param.c | 14 +- converter/ppm/ppmtompeg/specifics.c | 32 ++- converter/ppm/winico.h | 11 +- converter/ppm/winicontoppm.c | 347 +++++++++++++++++++-------------- converter/ppm/xim.h | 6 +- converter/ppm/ximtoppm.c | 29 +-- doc/HISTORY | 38 ++++ version.mk | 2 +- 16 files changed, 367 insertions(+), 228 deletions(-) diff --git a/buildtools/debian/mkdeb b/buildtools/debian/mkdeb index 4d3a4984..8ca0f738 100755 --- a/buildtools/debian/mkdeb +++ b/buildtools/debian/mkdeb @@ -3,13 +3,17 @@ # mkdeb ############################################################################### # -# This generates a Debian packge file (.deb) to install Sourceforge +# This generates a Debian package file (.deb) to install Sourceforge # Netpbm on a Debian system. # # This is especially useful because Debian does not have a good Debian # package (what Debian contains is derived from Sourceforge Netpbm ca. # 2002). # +# The dependencies this package declares are those that can be satisfied by +# Debian 8 (Jessie) and Debian 9 (Stretch). Netpbm works fine on other +# versions of Debian, but you may have to change the dependencies in this +# program or ignore dependencies at install time. ############################################################################### use strict; @@ -108,12 +112,30 @@ sub netpbmVersion($) { sub control($$) { my ($release, $architecture) = @_; +#----------------------------------------------------------------------------- +# The contents for the package control file, as a hash reference. In the +# referenced hash, there is one key for each line of the control file. The +# key and value in the hash are the key and value for the line of the control +# file. +#----------------------------------------------------------------------------- -# The Debian packaging system doesn't provide a way to express Netpbm's actual -# prerequisites. For example, Netpbm needs Version 6.2 or better of Libjpeg, -# but there is no way to state that here. Instead, we state Libjpeg 8. -# This makes the Netpbm package less useful. - + # Because developers of some of the dependent libraries frequently switch + # to distributing versions not backward compatible with what they + # previously distributed, and Debian always packages the currently + # distributed version, it is virtually impossible to produce a Netpbm + # package that works in multiple Debian versions. This program is coded + # to create a package that works on the Debian system the Netpbm + # maintainer currently uses to build the Debian packages he distributes. + # If you are building for any other version of Debian, you'll have to + # modify this code. + + # Note that the backward incompatibility is usually only at a binary + # level, not source level. And sometimes the only incompatibility for + # Netpbm purposes is that the soname has changed so that Linux will refuse + # to run a Netpbm program built for Debian N on Debian N-1. + + # The following is for Debian 9. + my %control; my $debianNativeNetpbm = @@ -134,9 +156,8 @@ sub control($$) { $control{'Depends'} = 'libc6, ' . 'libjpeg62, ' . - 'libpng12-0, ' . - 'libsvga1, ' . - 'libtiff4, ' . + 'libpng16-16, ' . + 'libtiff5, ' . 'libx11-6, ' . 'libxml2, ' . 'zlib1g, ' . @@ -423,7 +444,9 @@ sub buildDpkgBuildTree($$$$$) { makePkgConfig("$dpkgDirName/usr/lib/pkgconfig/netpbm.pc", $templateSubsR, $netpbmPkgDir); - makeManweb($dpkgDirName, $netpbmPkgDir); + # Beginning in Netpbm 10.78 (March 2017_, 'make package' doesn't package + # the manweb stuff, so we no longer put it in the Debian package. + #makeManweb($dpkgDirName, $netpbmPkgDir); } diff --git a/converter/other/cameratopam/identify.c b/converter/other/cameratopam/identify.c index 02208be6..39a9507e 100644 --- a/converter/other/cameratopam/identify.c +++ b/converter/other/cameratopam/identify.c @@ -233,7 +233,7 @@ adobeCoeff(const char * const make, double cc[4][4]; double cm[4][3]; double xyz[] = { 1,1,1 }; - char name[130]; + const char * name; unsigned int i; /* Make an identity matrix (1's on the diagonal) */ @@ -242,7 +242,7 @@ adobeCoeff(const char * const make, for (j = 0; j < 4; ++j) cc[i][j] = (i == j); } - sprintf (name, "%s %s", make, model); + pm_asprintf(&name, "%s %s", make, model); for (i = 0; i < ARRAY_SIZE(table); ++i) { const struct CoeffTableEntry * const entryP = &table[i]; @@ -256,6 +256,7 @@ adobeCoeff(const char * const make, break; } } + pm_strfree(name); } diff --git a/converter/pbm/pbmtonokia.c b/converter/pbm/pbmtonokia.c index bf3b9e41..5fb73701 100644 --- a/converter/pbm/pbmtonokia.c +++ b/converter/pbm/pbmtonokia.c @@ -415,7 +415,8 @@ convertToNpm(bit ** const image, header[ 3] = 0; header[ 4] = len; header[ 5] = 0; - memcpy(&header[5], text, len); + if (text) + memcpy(&header[6], text, len); header[ 6 + len] = cols; header[ 7 + len] = rows; header[ 8 + len] = 1; diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c index b14675c7..1a833b33 100644 --- a/converter/ppm/picttoppm.c +++ b/converter/ppm/picttoppm.c @@ -1204,7 +1204,7 @@ doDiffSize(struct Rect const clipsrc, struct rgbPlanes const dst, unsigned int const dstwid) { - unsigned int const dstadd = dstwid - xsize; + unsigned int const dstadd = dstwid - rectwidth(&clipdst); FILE * pamscalePipeP; const char * command; @@ -1962,6 +1962,7 @@ ClipRgn(struct canvas * const canvasP, */ readRect(&clip_rect); + rectinter(clip_rect, picFrame, &clip_rect); /* XXX should clip this by picFrame */ if (verbose) dumpRect("clipping to", clip_rect); diff --git a/converter/ppm/pjtoppm.c b/converter/ppm/pjtoppm.c index 7b694fb3..b89ce10f 100644 --- a/converter/ppm/pjtoppm.c +++ b/converter/ppm/pjtoppm.c @@ -10,6 +10,8 @@ ** implied warranty. */ +#include + #include "ppm.h" #include "mallocvar.h" @@ -33,12 +35,17 @@ main(argc, argv) { int cmd, val; char buffer[BUFSIZ]; - int planes = 3, rows = -1, cols = -1; + int planes = 3; + unsigned int rows; + unsigned int rowsX; + unsigned int cols; + bool colsIsSet; int r = 0, c = 0, p = 0, i; unsigned char **image = NULL; int *imlen; FILE *fp = stdin; int mode; + bool modeIsSet = false; int argn; unsigned char bf[3]; pixel *pixrow; @@ -93,10 +100,18 @@ main(argc, argv) case 'r': switch (c) { case 'S': /* width */ - cols = val; + if (val < 0) + pm_error("invalid width value"); + else { + cols = val; + colsIsSet = true; + } break; case 'T': /* height */ - rows = val; + if (val < 0) + pm_error ("invalid height value"); + else + rowsX = val; break; case 'U': /* planes */ planes = val; @@ -123,6 +138,7 @@ main(argc, argv) if (val != 0 && val != 1) pm_error("unimplemented trasmission mode %d", val); mode = val; + modeIsSet = true; break; case 'V': /* send plane */ case 'W': /* send last plane */ @@ -196,6 +212,10 @@ main(argc, argv) } } pm_close(fp); + + if (!modeIsSet) + pm_error("Input does not contain a 'bM' transmission mode order"); + rows = r; if (mode == 1) { unsigned char *buf; diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c index 7552f413..66f5ea3b 100644 --- a/converter/ppm/ppmtompeg/iframe.c +++ b/converter/ppm/ppmtompeg/iframe.c @@ -51,6 +51,9 @@ #include #include + +#include "netpbm/nstring.h" + #include "all.h" #include "mtypes.h" #include "frames.h" @@ -899,7 +902,7 @@ void WriteDecodedFrame(MpegFrame * const frame) { FILE * fpointer; - char fileName[256]; + const char * fileName; int width, height; int y; @@ -909,7 +912,7 @@ WriteDecodedFrame(MpegFrame * const frame) { width = Fsize_x; height = Fsize_y; - sprintf(fileName, "%s.decoded.%d", outputFileName, frame->id); + pm_asprintf(&fileName, "%s.decoded.%d", outputFileName, frame->id); if (!realQuiet) { fprintf(stdout, "Outputting to %s\n", fileName); @@ -931,6 +934,7 @@ WriteDecodedFrame(MpegFrame * const frame) { } fflush(fpointer); fclose(fpointer); + pm_strfree(fileName); } diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c index 24d337ed..2ddf3656 100644 --- a/converter/ppm/ppmtompeg/mpeg.c +++ b/converter/ppm/ppmtompeg/mpeg.c @@ -1667,14 +1667,14 @@ ReadDecodedRefFrame(MpegFrame * const frameP, unsigned int const frameNumber) { FILE *fpointer; - char fileName[256]; + const char * fileName; int width, height; register int y; width = Fsize_x; height = Fsize_y; - sprintf(fileName, "%s.decoded.%u", outputFileName, frameNumber); + pm_asprintf(&fileName, "%s.decoded.%u", outputFileName, frameNumber); if (! realQuiet) { fprintf(stdout, "reading %s\n", fileName); fflush(stdout); @@ -1714,6 +1714,7 @@ ReadDecodedRefFrame(MpegFrame * const frameP, pm_message("Could not read enough bytes from '%s'", fileName); } fclose(fpointer); + pm_strfree(fileName); } diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c index 841efdab..553e29d0 100644 --- a/converter/ppm/ppmtompeg/opts.c +++ b/converter/ppm/ppmtompeg/opts.c @@ -39,6 +39,9 @@ #include #include #include + +#include "netpbm/nstring.h" + #include "opts.h" #include "dct.h" @@ -316,14 +319,22 @@ SetupWriteDistortions(const char * const charPtr) collect_distortion_detailed = TRUE; break; case 't': { - char scratch[256]; collect_distortion_detailed = 2; for (i = 1; i < 32; i++) { - sprintf(scratch, "%srate%d", fname, i); - fp_table_rate[i-1] = fopen(scratch, "w"); - sprintf(scratch, "%sdist%d", fname, i); - fp_table_dist[i-1] = fopen(scratch, "w"); - }} + { + const char * scratch; + pm_asprintf(&scratch, "%srate%d", fname, i); + fp_table_rate[i-1] = fopen(scratch, "w"); + pm_strfree(scratch); + } + { + const char * scratch; + pm_asprintf(&scratch, "%sdist%d", fname, i); + fp_table_dist[i-1] = fopen(scratch, "w"); + pm_strfree(scratch); + } + } + } break; default: fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp); diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c index 45605981..c07a80a4 100644 --- a/converter/ppm/ppmtompeg/param.c +++ b/converter/ppm/ppmtompeg/param.c @@ -310,13 +310,13 @@ expandBackTickLine(const char * const input, struct inputSource * const inputSourceP) { FILE *fp; - char cmd[300]; + const char * cmd; const char * start; const char * end; - char cdcmd[110]; + const char * cdcmd; start = &input[1]; - end = &input[strlen(input)-1]; + end = &input[strlen(input)-1]; while (*end != '`') { end--; @@ -325,14 +325,14 @@ expandBackTickLine(const char * const input, end--; if (optionSeen[OPTION_INPUT_DIR]) - sprintf(cdcmd,"cd %s;",currentPath); + pm_asprintf(&cdcmd,"cd %s;", currentPath); else - strcpy(cdcmd,""); + cdcmd = pm_strdup(""); { char tmp[300]; strncpy(tmp,start,end-start+1); - sprintf(cmd,"(%s %s)", cdcmd, tmp); + pm_asprintf(&cmd, "(%s %s)", cdcmd, tmp); } fp = popen(cmd, "r"); @@ -346,6 +346,8 @@ expandBackTickLine(const char * const input, mergeInputSource(inputSourceP, &subInputSource); } + pm_strfree(cmd); + pm_strfree(cdcmd); } diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c index fb5e3649..59bd3473 100644 --- a/converter/ppm/ppmtompeg/specifics.c +++ b/converter/ppm/ppmtompeg/specifics.c @@ -36,6 +36,8 @@ * HEADER FILES * *==============*/ +#include "netpbm/nstring.h" + #include "all.h" #include "mtypes.h" #include "frames.h" @@ -43,8 +45,6 @@ #include "fsize.h" #include "dct.h" #include "specifics.h" -#include -#include #include "prototypes.h" #include "param.h" @@ -148,14 +148,21 @@ static char version = -1; void Specifics_Init() { - char command[1100]; FILE *specificsFP; - sprintf(command, "rm -f %s.cpp", specificsFile); - system(command); - sprintf(command, "cpp -P %s %s %s.cpp", - specificsDefines, specificsFile, specificsFile); - system(command); + { + const char * command; + pm_asprintf(&command, "rm -f %s.cpp", specificsFile); + system(command); + pm_strfree(command); + } + { + const char * command; + pm_asprintf(&command, "cpp -P %s %s %s.cpp", + specificsDefines, specificsFile, specificsFile); + system(command); + pm_strfree(command); + } strcat(specificsFile, ".cpp"); if ((specificsFP = fopen(specificsFile, "r")) == NULL) { fprintf(stderr, "Error with specifics file, cannot open %s\n", @@ -163,9 +170,14 @@ Specifics_Init() { exit(1); } printf("Specifics file: %s\n", specificsFile); + Parse_Specifics_File(specificsFP); - sprintf(command, "rm -f %s.cpp", specificsFile); - system(command); + { + const char * command; + pm_asprintf(&command, "rm -f %s.cpp", specificsFile); + system(command); + pm_strfree(command); + } } diff --git a/converter/ppm/winico.h b/converter/ppm/winico.h index 4b8ac38b..c6133ef0 100644 --- a/converter/ppm/winico.h +++ b/converter/ppm/winico.h @@ -28,21 +28,22 @@ struct MS_Ico_ { struct IC_Entry_ { - u1 width; - u1 height; /* - * color_count is actually a byte (u1)... but 0 = 256, so I've used a short (u2). + * width, height, color_count are a byte in the format, but 0 = 256, + * so it takes a short (u2) to represent the value normally. */ + u2 width; + u2 height; u2 color_count; u1 reserved; u2 planes; - u2 bitcount; + u2 bitcount; /* 0, 1, 4, or 8 */ u4 size_in_bytes; u4 file_offset; IC_InfoHeader ih; IC_Color * colors; /* - * Below here, I have useful fields which aren't in the spec, but + * Below here, I have useful fields which aren't in the spec, but * save having to keep stoopid amounts of global data. */ u1 * andBitmap; /* Used in reader. */ diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c index 6b1376b2..05e1eaff 100644 --- a/converter/ppm/winicontoppm.c +++ b/converter/ppm/winicontoppm.c @@ -10,7 +10,7 @@ ** implied warranty. ** ** Changes: -** +** ** 03/2003 - Added 24+32 bpp capability. */ @@ -56,7 +56,7 @@ parseCommandLine (int argc, const char ** argv, struct cmdlineInfo *cmdlineP ) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + and argv. Return the information in the options as *cmdlineP. If command line is internally inconsistent (invalid options, etc.), issue error message to stderr and abort program. @@ -74,15 +74,15 @@ parseCommandLine (int argc, const char ** argv, MALLOCARRAY(option_def, 100); option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "allicons", OPT_FLAG, NULL, + OPTENT3(0, "allicons", OPT_FLAG, NULL, &cmdlineP->allicons, 0 ); - OPTENT3(0, "bestqual", OPT_FLAG, NULL, + OPTENT3(0, "bestqual", OPT_FLAG, NULL, &cmdlineP->bestqual, 0 ); - OPTENT3(0, "writeands", OPT_FLAG, NULL, + OPTENT3(0, "writeands", OPT_FLAG, NULL, &cmdlineP->writeands, 0 ); - OPTENT3(0, "multippm", OPT_FLAG, NULL, + OPTENT3(0, "multippm", OPT_FLAG, NULL, &cmdlineP->multippm, 0 ); - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0 ); opt.opt_table = option_def; @@ -92,14 +92,14 @@ parseCommandLine (int argc, const char ** argv, pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - if (argc-1 < 1) + if (argc-1 < 1) cmdlineP->inputFilespec = "-"; else cmdlineP->inputFilespec = argv[1]; if (argc-1 < 2) { cmdlineP->outputFilespec = "-"; - + if (cmdlineP->writeands || cmdlineP->allicons) pm_error("If you specify the -writeands or -allicons option, " "you must also specify an output file name argument."); @@ -115,49 +115,49 @@ parseCommandLine (int argc, const char ** argv, -static int +static int GetByte(FILE * const ifP) { int v; - + v = getc(ifP); if (v == EOF) pm_error(er_read, infname); - + return v; } - -static short + +static short GetShort(FILE * const ifP) { short v; - + pm_readlittleshort(ifP, &v); return v; } - -static long + +static long GetLong(FILE * const ifP) { long v; - + pm_readlittlelong(ifP, &v); - + return v; } - + /* - * These have no purpose but to wrapper the Byte, Short & Long + * These have no purpose but to wrapper the Byte, Short & Long * functions. */ -static u1 +static u1 readU1(FILE * const ifP) { ++fileOffset; @@ -167,17 +167,26 @@ readU1(FILE * const ifP) { -static u1 * +static u1 * readU1String (FILE * const ifP, unsigned int const length) { - + u1 * string; - + size_t rc; + MALLOCARRAY(string, length + 1); if (string == NULL) pm_error("out of memory"); - fread(string, sizeof(u1), length, ifP); + rc = fread(string, sizeof(u1), length, ifP); + if (rc < length) { + if (feof(ifP)) + pm_error("File read failed. Premature end of file"); + else + pm_error("File read failed. Errno=%d (%s)", + errno, strerror(errno)); + } + string[length] = 0; fileOffset += length * sizeof(u1); @@ -186,7 +195,7 @@ readU1String (FILE * const ifP, -static u2 +static u2 readU2 (FILE * const ifP) { fileOffset +=2; @@ -196,7 +205,7 @@ readU2 (FILE * const ifP) { -static u4 +static u4 readU4 (FILE * const ifP) { fileOffset += 4; @@ -206,62 +215,96 @@ readU4 (FILE * const ifP) { -static IC_Entry +static IC_Entry readICEntry(FILE * const ifP) { IC_Entry entryP; + u1 widthFld; /* 0 means 256 */ + u1 heightFld; /* 0 means 256 */ + u1 colorCtFld; /* 0 means 256 */ MALLOCVAR(entryP); if (entryP == NULL) - pm_error("Unable to allcoate memory for IC entry"); + pm_error("Unable to allocate memory for IC entry"); - entryP->width = readU1(ifP); - entryP->height = readU1(ifP); + widthFld = readU1(ifP); + heightFld = readU1(ifP); entryP->color_count = readU1(ifP); - entryP->reserved = readU1(ifP); - entryP->planes = readU2(ifP); - entryP->bitcount = readU2(ifP); - entryP->size_in_bytes = readU4(ifP); - entryP->file_offset = readU4(ifP); + entryP->reserved = readU1(ifP); /* never referenced (should be 0) */ + entryP->planes = readU2(ifP); /* never referenced */ + entryP->bitcount = readU2(ifP); /* must be 0, 1, 4, or 8 */ + entryP->size_in_bytes = readU4(ifP); /* never referenced */ + entryP->file_offset = readU4(ifP); /* never referenced */ entryP->colors = NULL; entryP->ih = NULL; entryP->xorBitmap = NULL; entryP->andBitmap = NULL; - + + entryP->width = widthFld == 0 ? 256 : widthFld; + entryP->height = heightFld == 0 ? 256 : heightFld; + entryP->color_count = colorCtFld == 0 ? 256 : colorCtFld; + + if (entryP->width != entryP->height) + pm_message("warning: icon is not square: %u x %u", + entryP->width, entryP->height); + return entryP; } -static IC_InfoHeader +static IC_InfoHeader readInfoHeader (FILE * const ifP, IC_Entry const entryP) { IC_InfoHeader ihP; MALLOCVAR(ihP); - + if (ihP == NULL) pm_error("Unable to allocate memory for info header"); - ihP->size = readU4(ifP); - ihP->width = readU4(ifP); - ihP->height = readU4(ifP); - ihP->planes = readU2(ifP); + ihP->size = readU4(ifP); /* never referenced */ + ihP->width = readU4(ifP); /* must equal entryP->width */ + ihP->height = readU4(ifP); /* must be 2 * entryP->height */ + ihP->planes = readU2(ifP); /* never referenced */ ihP->bitcount = readU2(ifP); ihP->compression = readU4(ifP); - ihP->imagesize = readU4(ifP); - ihP->x_pixels_per_m = readU4(ifP); - ihP->y_pixels_per_m = readU4(ifP); + ihP->imagesize = readU4(ifP); /* never referenced */ + ihP->x_pixels_per_m = readU4(ifP); /* never referenced */ + ihP->y_pixels_per_m = readU4(ifP); /* never referenced */ ihP->colors_used = readU4(ifP); + /* checked below, otherwise never referenced */ ihP->colors_important = readU4(ifP); - - if (!entryP->bitcount) - entryP->bitcount = ihP->bitcount; - - if (entryP->color_count == 0 && entryP->bitcount <= 8) - entryP->color_count = 256; + /* checked below, otherwise never referenced */ + + if ((entryP->width != ihP->width) + || (entryP->height != ihP->height / 2)) { + pm_error("mismatch in header and image dimensions " + "(%u x %u vs. %u x %u)", + entryP->width, entryP->height, + ihP->width, ihP->height / 2); + } else if (ihP->height % 2 != 0) + pm_error("invalid image height value %u (cannot be an odd number)", + ihP->height); + + if (ihP->bitcount > 8) + pm_error("abnormal bit per pixel value %u", ihP->bitcount); + + if ((entryP->bitcount != 0) && (entryP->bitcount != ihP->bitcount)) { + pm_error("mismatch in header and image bpp value" + "(%u vs. %u)", + entryP->bitcount, ihP->bitcount); + } + + if (ihP->colors_used > entryP->color_count) + pm_error("'colors used' value %u exceeds total colors %u", + ihP->colors_used, entryP->color_count); + + if (ihP->colors_important > entryP->color_count) + pm_error("'important colors' value %u exceeds total colors %u", + ihP->colors_important, entryP->color_count); if (ihP->compression) { pm_error("Can't handle compressed icons"); @@ -271,7 +314,7 @@ readInfoHeader (FILE * const ifP, -static IC_Color +static IC_Color readICColor(FILE * const ifP) { IC_Color colorP; @@ -283,7 +326,7 @@ readICColor(FILE * const ifP) { /* I don't know why this isn't the same as the spec, it just isn't. The colors honestly seem to be stored BGR. Bizarre. - + I've checked this in the BMP code for bmptoppm and the gimp. Guess the spec I have is just plain wrong. */ @@ -295,10 +338,10 @@ readICColor(FILE * const ifP) { return colorP; } - -static u1 * + +static u1 * read1Bitmap (FILE * const ifP, unsigned int const width, unsigned int const height) { @@ -312,9 +355,9 @@ read1Bitmap (FILE * const ifP, if (bitmap == NULL) pm_error("out of memory"); - /* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the + /* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the encoding mechanism is different. - + 8bpp => 1 byte/palette index. 4bpp => High Nibble, Low Nibble 1bpp => 1 palette value per bit, high bit 1st. @@ -333,9 +376,9 @@ read1Bitmap (FILE * const ifP, unsigned int col; unsigned int rowByte; unsigned int xOrVal; - + for (col = 0, rowByte = 0, xOrVal = 0x80; col < width; ++col) { - *(bitmap+((height - row - 1) * width) + col) = + *(bitmap+((height - row - 1) * width) + col) = (imgRow[rowByte] & xOrVal) / xOrVal; if (xOrVal == 0x01) { xOrVal = 0x80; @@ -349,8 +392,8 @@ read1Bitmap (FILE * const ifP, } - -static u1 * + +static u1 * read4Bitmap (FILE * const ifP, unsigned int const width, unsigned int const height) { @@ -381,7 +424,7 @@ read4Bitmap (FILE * const ifP, for (col = 0, rowByte = 0, bottom = true; col < width; ++col) { /* 2 nibbles, 2 values */ if (bottom) { - *(bitmap + ((height - row - 1) * width) + col) = + *(bitmap + ((height - row - 1) * width) + col) = (imgRow[rowByte] & 0xF0) >> 4; } else { *(bitmap + ((height - row -1) * width) + col) = @@ -396,8 +439,8 @@ read4Bitmap (FILE * const ifP, } - -static u1 * + +static u1 * read8Bitmap (FILE * const ifP, unsigned int const width, unsigned int const height) { @@ -406,7 +449,7 @@ read8Bitmap (FILE * const ifP, unsigned int xByteCt; unsigned int wt; u1 * bitmap; - + MALLOCARRAY(bitmap, width * height); if (bitmap == NULL) pm_error("out of memory"); @@ -434,12 +477,12 @@ read8Bitmap (FILE * const ifP, static u1 * readXBitmap (FILE * const ifP, - unsigned int const width, - unsigned int const height, + unsigned int const width, + unsigned int const height, unsigned int const bpp) { /*---------------------------------------------------------------------------- Read a true color bitmap. (24/32 bits) - + The output routine deplanarizes it for us, we keep it flat here. -----------------------------------------------------------------------------*/ unsigned int const byteCt = bpp >> 3; @@ -457,7 +500,7 @@ readXBitmap (FILE * const ifP, u1 * bitcurptr; for (i = 0, bitcurptr = &bitmap[byteCt * width * (height-1)]; - i < height; + i < height; ++i, bitcurptr -= xByteCt) { u1 * const row = readU1String(ifP, xByteCt); @@ -470,7 +513,7 @@ readXBitmap (FILE * const ifP, -static MS_Ico +static MS_Ico readIconFile(FILE * const ifP, bool const verbose) { @@ -479,13 +522,23 @@ readIconFile(FILE * const ifP, MS_Ico MSIconData; MALLOCVAR(MSIconData); - + MSIconData->reserved = readU2(ifP); /* should be 0 */ - MSIconData->type = readU2(ifP); /* should be 1 */ + MSIconData->type = readU2(ifP); /* should be 1 (ICO) or 2 (CUR) */ MSIconData->count = readU2(ifP); /* # icons in file */ - if (verbose) - pm_message("Icon file contains %d icons.", MSIconData->count); + if (MSIconData->reserved != 0) + pm_message("Signature 'reserved' field is %u (should be 0)", + MSIconData->reserved); + + if (MSIconData->type != 1 && MSIconData->type != 2) + pm_error("Type %u file. Can handle only type 1 or 2.", + MSIconData->type); + + if (MSIconData->count == 0) + pm_error("Invalid image count: 0"); + else if (verbose) + pm_message("File contains %u images", MSIconData->count); MALLOCARRAY(MSIconData->entries, MSIconData->count); if (MSIconData->entries == NULL) @@ -498,16 +551,17 @@ readIconFile(FILE * const ifP, /* Read in the infoheader, color map (if any) and the actual bit/pix maps for the icons. */ - if (verbose) + if (verbose) pm_message("#\tColors\tBPP\tWidth\tHeight\n"); for (i = 0; i < MSIconData->count; ++i) { + IC_Entry const entryP = MSIconData->entries[i]; + unsigned int bpp; /* bits per pixel */ - MSIconData->entries[i]->ih = - readInfoHeader(ifP, MSIconData->entries[i]); - - bpp = MSIconData->entries[i]->bitcount; + entryP->ih = readInfoHeader(ifP, MSIconData->entries[i]); + + bpp = entryP->bitcount ? entryP->bitcount : entryP->ih->bitcount; /* Read the palette, if appropriate */ switch (bpp) { @@ -518,31 +572,29 @@ readIconFile(FILE * const ifP, default: { unsigned int j; - MALLOCARRAY(MSIconData->entries[i]->colors, - MSIconData->entries[i]->color_count); - if (MSIconData->entries[i]->colors == NULL) - pm_error("out of memory"); + MALLOCARRAY(entryP->colors, entryP->color_count); + if (!entryP->colors) + pm_error("Could get memory for %u colors", + entryP->color_count); - for (j = 0; j < MSIconData->entries[i]->color_count; ++j) - MSIconData->entries[i]->colors[j] = readICColor(ifP); + for (j = 0; j < entryP->color_count; ++j) + entryP->colors[j] = readICColor(ifP); } } if (verbose) { char colsText[10]; - sprintf (colsText, "%d", MSIconData->entries[i]->color_count); + sprintf (colsText, "%d", entryP->color_count); pm_message("%d\t%s\t%d\t%d\t%d\n", i, - MSIconData->entries[i]->color_count ? - colsText : "TRUE", - bpp, MSIconData->entries[i]->width, - MSIconData->entries[i]->height); + entryP->color_count ? colsText : "TRUE", + bpp, entryP->width, entryP->height); } /* Pixels are stored bottom-up, left-to-right. Pixel lines are * padded with zeros to end on a 32bit (4byte) boundary. Every * line will have the same number of bytes. Color indices are * zero based, meaning a pixel color of 0 represents the first * color table entry, a pixel color of 255 (if there are that - * many) represents the 256th entry. - * + * many) represents the 256th entry. + * * 24+32 bit (16 is an abomination, which I'll avoid, and expect * no-one to mind) are stored 1byte/plane with a spare (alpha?) * byte for 32 bit. @@ -553,29 +605,21 @@ readIconFile(FILE * const ifP, */ switch (bpp) { case 1: - MSIconData->entries[i]->xorBitmap = - read1Bitmap(ifP, - MSIconData->entries[i]->width, - MSIconData->entries[i]->height); + entryP->xorBitmap = + read1Bitmap(ifP, entryP->width, entryP->height); break; case 4: - MSIconData->entries[i]->xorBitmap = - read4Bitmap(ifP, - MSIconData->entries[i]->width, - MSIconData->entries[i]->height); + entryP->xorBitmap = + read4Bitmap(ifP, entryP->width, entryP->height); break; case 8: - MSIconData->entries[i]->xorBitmap = - read8Bitmap(ifP, - MSIconData->entries[i]->width, - MSIconData->entries[i]->height); + entryP->xorBitmap = + read8Bitmap(ifP, entryP->width, entryP->height); break; case 24: case 32: - MSIconData->entries[i]->xorBitmap = - readXBitmap(ifP, - MSIconData->entries[i]->width, - MSIconData->entries[i]->height,bpp); + entryP->xorBitmap = + readXBitmap(ifP, entryP->width, entryP->height,bpp); break; default: pm_error("Uncatered bit depth %u", bpp); @@ -583,19 +627,17 @@ readIconFile(FILE * const ifP, /* * Read AND Bitmap */ - MSIconData->entries[i]->andBitmap = - read1Bitmap(ifP, - MSIconData->entries[i]->width, - MSIconData->entries[i]->height); + entryP->andBitmap = + read1Bitmap(ifP, entryP->width, entryP->height); } - + } return MSIconData; } -static char * +static char * trimmedOutputName(const char inputName[]) { /* * Just trim off the final ".ppm", if there is one, else return as is. @@ -611,7 +653,7 @@ trimmedOutputName(const char inputName[]) { -static int +static int getBestQualityIcon(MS_Ico MSIconData) { unsigned int i; @@ -643,7 +685,7 @@ writeXors(FILE * const multiOutF, char * const outputFileBase, IC_Entry const entryP, int const entryNum, - bool const multiple, + bool const multiple, bool const xor) { /*---------------------------------------------------------------------------- Write an "xor" image (i.e. the main image) out. @@ -655,7 +697,7 @@ writeXors(FILE * const multiOutF, 'xor' means to include "xor" in the output file name. if 'multiOutF' is non-null, it is the stream descriptor of an open - stream to which we are to write the image. If it is null, + stream to which we are to write the image. If it is null, we are to open a file using outputFileBase[] and 'entryNum' and 'xor' to derive its name, and close it afterward. -----------------------------------------------------------------------------*/ @@ -672,16 +714,16 @@ writeXors(FILE * const multiOutF, if (multiple) { pm_asprintf(&outputFileName, "%s%s_%d.ppm", outputFileBase,(xor ? "_xor" : ""), entryNum); - } else { + } else { pm_asprintf(&outputFileName, "%s%s.ppm", outputFileBase,(xor ? "_xor" : "")); } } else outputFileName = strdup("-"); - + ofP = pm_openw(outputFileName); } - /* + /* Allocate an array to save the bmp data into. note that entry->height will be 1/2 entry->ih->height, as the latter adds "and" and "xor" height. @@ -704,31 +746,36 @@ writeXors(FILE * const multiOutF, unsigned int col; for (col = 0; col < entryP->width; ++col) { unsigned int const colorIndex = xorRow[col]; - IC_Color const colorP = entryP->colors[colorIndex]; - PPM_ASSIGN(pixArray[row][col], - colorP->red, colorP->green, colorP->blue); + if (colorIndex >= entryP->color_count) { + pm_error("Invalid color index %u (max is %u)", + colorIndex, entryP->color_count - 1); + } else { + IC_Color const colorP = entryP->colors[colorIndex]; + PPM_ASSIGN(pixArray[row][col], + colorP->red, colorP->green, colorP->blue); + } } } break; } - } - - ppm_writeppm(ofP, pixArray, entryP->width, entryP->height, + } + + ppm_writeppm(ofP, pixArray, entryP->width, entryP->height, 255 /* maxval */, false /* text */); ppm_freearray(pixArray, entryP->height); pm_strfree(outputFileName); - - if (!multiOutF) + + if (!multiOutF) pm_close(ofP); } - + static void -writeAnds(FILE * const multiOutF, +writeAnds(FILE * const multiOutF, char const outputFileBase[], IC_Entry const entryP, - unsigned int const entryNum, + unsigned int const entryNum, bool const multiple) { /*---------------------------------------------------------------------------- Write the "and" image (i.e. the alpha mask) of the image *entryP out. @@ -738,7 +785,7 @@ writeAnds(FILE * const multiOutF, we are writing. if 'multiOutF' is non-null, it is the stream descriptor of an open - stream to which we are to write the image. If it is null, + stream to which we are to write the image. If it is null, we are to open a file using outputFileBase[] and 'entryNum' and 'xor' to derive its name, and close it afterward. -----------------------------------------------------------------------------*/ @@ -753,10 +800,10 @@ writeAnds(FILE * const multiOutF, assert(outputFileBase); - if (multiple) + if (multiple) pm_asprintf(&outputFileName, "%s_and_%u.pbm", outputFileBase, entryNum); - else + else pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase); ofP = pm_openw(outputFileName); pm_strfree(outputFileName); @@ -781,7 +828,7 @@ writeAnds(FILE * const multiOutF, static void -openMultiXor(char const outputFileBase[], +openMultiXor(char const outputFileBase[], bool const writeands, FILE ** const multiOutFP) { @@ -809,7 +856,7 @@ openMultiAnd(char const outputFileBase[], assert(outputFileBase); pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase); - + *multiAndOutFP = pm_openw(outputFileName); pm_strfree(outputFileName); @@ -846,7 +893,7 @@ freeIcondata(MS_Ico const MSIconDataP) { -int +int main(int argc, const char *argv[]) { struct cmdlineInfo cmdline; @@ -856,7 +903,7 @@ main(int argc, const char *argv[]) { char * outputFileBase; FILE * multiOutF; FILE * multiAndOutF; - + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -864,7 +911,7 @@ main(int argc, const char *argv[]) { if (cmdline.bestqual && cmdline.allicons) pm_message("-bestqual doesn't make sense with -allicons. " "Ignoring -bestqual."); - + if (streq(cmdline.outputFilespec, "-")) outputFileBase = NULL; else @@ -879,10 +926,10 @@ main(int argc, const char *argv[]) { * Now we've read the icon file in (Hopefully! :) * Go through each of the entries, and write out files of the * form - * + * * fname_0_xor.ppm * fname_0_and.ppm - * + * * (or to stdout, depending on args parsing above). */ /* @@ -898,13 +945,13 @@ main(int argc, const char *argv[]) { else endEntry = 1; } - - if (cmdline.multippm) + + if (cmdline.multippm) openMultiXor(outputFileBase, cmdline.writeands, &multiOutF); else multiOutF = NULL; - if (cmdline.writeands && cmdline.multippm) + if (cmdline.writeands && cmdline.multippm) openMultiAnd(outputFileBase, &multiAndOutF); else multiAndOutF = NULL; @@ -915,18 +962,18 @@ main(int argc, const char *argv[]) { for (entryNum = startEntry; entryNum < endEntry; ++entryNum) { IC_Entry const entryP = MSIconDataP->entries[entryNum]; - writeXors(multiOutF, outputFileBase, entryP, entryNum, + writeXors(multiOutF, outputFileBase, entryP, entryNum, cmdline.allicons, cmdline.writeands); if (cmdline.writeands) - writeAnds(multiAndOutF, outputFileBase, + writeAnds(multiAndOutF, outputFileBase, entryP, entryNum, cmdline.allicons); } } if (multiOutF) - pm_close(multiOutF); + pm_close(multiOutF); if (multiAndOutF) pm_close(multiAndOutF); - + /* free up the image data here. */ freeIcondata(MSIconDataP); diff --git a/converter/ppm/xim.h b/converter/ppm/xim.h index 27556b30..70a9a761 100644 --- a/converter/ppm/xim.h +++ b/converter/ppm/xim.h @@ -63,9 +63,9 @@ typedef struct XimImage { short tpics, npics; /* number of images, total & left in file */ short ncolors; /* " " colors in the color table */ Color* colors; /* colortable, one byte per r/g/b & pixel */ - char* author; /* author credit, copyright, etc */ - char* date; /* date image was made, grabbed, etc. */ - char* program; /* program used to make this */ + const char* author; /* author credit, copyright, etc */ + const char* date; /* date image was made, grabbed, etc. */ + const char* program; /* program used to make this */ short ncomments; /* number of comments strings */ char** comments; /* pointers to null terminated strings */ char* offset; /* original offset in machine memory */ diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c index ce5e6396..dc04b363 100644 --- a/converter/ppm/ximtoppm.c +++ b/converter/ppm/ximtoppm.c @@ -116,32 +116,9 @@ ReadXimHeader(FILE * const in_fp, */ header->bits_channel = atoi(a_head.bits_per_channel); header->alpha_flag = atoi(a_head.alpha_channel); - if (strlen(a_head.author)) { - if (!(header->author = calloc((unsigned int)strlen(a_head.author)+1, - 1))) { - pm_message("ReadXimHeader: can't calloc author string" ); - return(0); - } - header->width = atoi(a_head.image_width); - strncpy(header->author, a_head.author, strlen(a_head.author)); - } - if (strlen(a_head.date)) { - if (!(header->date =calloc((unsigned int)strlen(a_head.date)+1,1))){ - pm_message("ReadXimHeader: can't calloc date string" ); - return(0); - } - header->width = atoi(a_head.image_width); - strncpy(header->date, a_head.date, strlen(a_head.date)); - } - if (strlen(a_head.program)) { - if (!(header->program = calloc( - (unsigned int)strlen(a_head.program) + 1, 1))) { - pm_message("ReadXimHeader: can't calloc program string" ); - return(0); - } - header->width = atoi(a_head.image_width); - strncpy(header->program, a_head.program,strlen(a_head.program)); - } + pm_asprintf(&header->author, a_head.author); + pm_asprintf(&header->date, a_head.date); + pm_asprintf(&header->program, a_head.program); /* Do double checking for bakwards compatibility */ if (header->npics == 0) header->npics = 1; diff --git a/doc/HISTORY b/doc/HISTORY index 15d186b3..a68a4a77 100644 --- a/doc/HISTORY +++ b/doc/HISTORY @@ -4,6 +4,44 @@ Netpbm. CHANGE HISTORY -------------- +20.06.27 BJH Release 10.73.32 + + winicontoppm: Fix undefined behavior for various invalid input. + Always broken. Winicontoppm was new in Netpbm 9.3 (June 2000). + + winicontoppm: Fix incorrect output with 256 pixel wide or high + image. Always broken. Winicontoppm was new in Netpbm 9.3 (June + 2000). + + pjtoppm: Handle input stream with no transmission mode command. + Always broken. Pjtoppm was in primordial Netpbm (1991). + + picttoppm: Fix bug with an input file that specifies a clip + region (ClipRgn opcode) that is not contained within the + picture frame. Result is invalid memory access. Broken + some time 1994-2002. + + picttoppm: Fix incorrect output (sheared) when a blit must be + scaled. Broken in Netpbm 10.34 (June 2006) or 10.35 (August + 2006). + + pbmtonokia: Fix incorrect output with -txt option. + + pbmtonokia: Fix incorrect output with newer compiler. + + cameratopam: Fix buffer overrun. Always present. (cameratopam + was new in Netpbm 10.28 (June 2005)). + + ppmtompeg: Fix buffer overruns with very long names in input + parameter files. Always broken. Ppmtompeg was new in + Netpbm 8.4 (April 2000). + + ximtoppm: Fix possible program crash due to invalid memory + reference. Always broken. ximtoppm was in primordial Netpbm, + ca 1989. + + Build: make deb: make prereqs be for Debian 9. + 20.03.26 BJH Release 10.73.31 pbmtopgm: Fix incorrect output when convolution area is not diff --git a/version.mk b/version.mk index ea2ed166..4f89ef21 100644 --- a/version.mk +++ b/version.mk @@ -1,3 +1,3 @@ NETPBM_MAJOR_RELEASE = 10 NETPBM_MINOR_RELEASE = 73 -NETPBM_POINT_RELEASE = 31 +NETPBM_POINT_RELEASE = 32 -- cgit 1.4.1