about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2020-06-27 17:03:16 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2020-06-27 17:03:16 +0000
commit5d96d3c0c22088d20528fb0f0b126d175ec8a09f (patch)
treea2f504de6f6f9865e8e16d9a2a6f56fcb1c67945
parent425de32af6e224afeabeda763c20ec944c3b029c (diff)
downloadnetpbm-mirror-5d96d3c0c22088d20528fb0f0b126d175ec8a09f.tar.gz
netpbm-mirror-5d96d3c0c22088d20528fb0f0b126d175ec8a09f.tar.xz
netpbm-mirror-5d96d3c0c22088d20528fb0f0b126d175ec8a09f.zip
Release 10.73.32
git-svn-id: http://svn.code.sf.net/p/netpbm/code/super_stable@3869 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rwxr-xr-xbuildtools/debian/mkdeb43
-rw-r--r--converter/other/cameratopam/identify.c5
-rw-r--r--converter/pbm/pbmtonokia.c3
-rw-r--r--converter/ppm/picttoppm.c3
-rw-r--r--converter/ppm/pjtoppm.c26
-rw-r--r--converter/ppm/ppmtompeg/iframe.c8
-rw-r--r--converter/ppm/ppmtompeg/mpeg.c5
-rw-r--r--converter/ppm/ppmtompeg/opts.c23
-rw-r--r--converter/ppm/ppmtompeg/param.c14
-rw-r--r--converter/ppm/ppmtompeg/specifics.c32
-rw-r--r--converter/ppm/winico.h11
-rw-r--r--converter/ppm/winicontoppm.c347
-rw-r--r--converter/ppm/xim.h6
-rw-r--r--converter/ppm/ximtoppm.c29
-rw-r--r--doc/HISTORY38
-rw-r--r--version.mk2
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 <stdbool.h>
+
 #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 <sys/types.h>
 #include <sys/param.h>
+
+#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 <string.h>
 #include <stdlib.h>
 #include <math.h>
+
+#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 <stdio.h>
-#include <string.h>
 #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