about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2014-03-30 17:12:47 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2014-03-30 17:12:47 +0000
commit04afde0b11367018d95be801c543fdcf16420b5d (patch)
tree8c1ecbdf40aa57ff7fe47234708e3a2995d2b641 /lib
parentfbf4dcdf76bf004ea45a762e8399268cc388ae19 (diff)
downloadnetpbm-mirror-04afde0b11367018d95be801c543fdcf16420b5d.tar.gz
netpbm-mirror-04afde0b11367018d95be801c543fdcf16420b5d.tar.xz
netpbm-mirror-04afde0b11367018d95be801c543fdcf16420b5d.zip
Update to current Development release - 10.66.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2172 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile14
-rw-r--r--lib/libpamread.c51
-rw-r--r--lib/libpgm1.c60
-rw-r--r--lib/libpnm1.c20
-rw-r--r--lib/libppm1.c64
-rw-r--r--lib/standardppmdfont.c2
6 files changed, 178 insertions, 33 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 6512949f..d5f47813 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,7 +13,7 @@ else
 LIBNETPBM = $(NETPBMSHLIBPREFIX)netpbm$(DLLVER).$(NETPBMLIBSUFFIX)
 endif
 
-ifeq ($(STATICLIB_TOO),y)
+ifeq ($(STATICLIB_TOO),Y)
 EXTRA_STATICLIB = libnetpbm.$(STATICLIBSUFFIX)
 else
 EXTRA_STATICLIB =
@@ -130,7 +130,7 @@ libnetpbm.$(NETPBMLIBSUFFIX).$(MAJ).$(MIN): $(LIBOBJECTS) $(LIBOBJECTS_X)
 endif
 
 ifeq ($(NETPBMLIBTYPE),dll)
-ifeq ($(STATICLIB_TOO),y)
+ifeq ($(STATICLIB_TOO),Y)
 $(NETPBMSHLIBPREFIX)netpbm$(DLLVER).dll: $(LIBOBJECTS) $(LIBOBJECTS_X) libnetpbm.$(STATICLIBSUFFIX)
 else
 $(NETPBMSHLIBPREFIX)netpbm$(DLLVER).dll: $(LIBOBJECTS) $(LIBOBJECTS_X)
@@ -170,16 +170,16 @@ endif
 # STATICLIB_SUFFIX may just be arbitrary.
 #-----------------------------------------------------------------------------
 ifeq ($(NETPBMLIBTYPE),unixstatic)
-  BUILD_STATICLIB = y
+  BUILD_STATICLIB = Y
 else
-  ifeq ($(STATICLIB_TOO),y)
-    BUILD_STATICLIB = y
+  ifeq ($(STATICLIB_TOO),Y)
+    BUILD_STATICLIB = Y
   else
     BUILD_STATICLIB = n
   endif
 endif
 
-ifeq ($(BUILD_STATICLIB),y)
+ifeq ($(BUILD_STATICLIB),Y)
 libnetpbm.$(STATICLIBSUFFIX): $(LIBOBJECTS) $(LIBOBJECTS_X)
 	-rm -f $@
 	$(AR) rc $@ $(LIBOBJECTS) $(LIBOBJECTS_X)
@@ -190,7 +190,7 @@ endif
 # To avoid major hassles with having ppmdcfont available here, we just
 # ship a pre-made standardppmfont.c, so this rule will not normally be
 # used.
-standardppmdfont.c:standard.ppmdfont
+standardppmdfont.c: standard.ppmdfont
 	ppmdcfont <$< >$@
 
 # Note that we create a new compile.h only for the first make after a
diff --git a/lib/libpamread.c b/lib/libpamread.c
index 3c8e2e33..cbac18c1 100644
--- a/lib/libpamread.c
+++ b/lib/libpamread.c
@@ -202,6 +202,51 @@ parse4BpsRow(const struct pam *    const pamP,
 
 
 static void
+validatePamRow(const struct pam * const pamP,
+               tuple *            const tuplerow,
+               const char **      const errorP) {
+/*----------------------------------------------------------------------------
+  Check for sample values above maxval in input.  
+
+  Note: a program that wants to deal with invalid sample values itself can
+  simply make sure it sets pamP->maxval sufficiently high, so this validation
+  never fails.
+-----------------------------------------------------------------------------*/
+    /* To save time, skip the test for if the maxval is a saturated value
+       (255, 65535) or format is PBM.
+
+       This is an expensive test, but is skipped in most cases: in practice
+       maxvals other than 255 or 65535 are uncommon.  Thus we do this in a
+       separate pass through the row rather than while reading in the row.
+    */
+
+    if (pamP->maxval == (((sample) 0x1) << pamP->bytes_per_sample*8) - 1 ||
+        PAM_FORMAT_TYPE(pamP->format) == PBM_FORMAT) {
+        /* There's no way a sample can be invalid, so we don't need to
+           look at the samples individually.
+        */
+        *errorP = NULL;
+    } else {
+        unsigned int col;
+        for (col = 0; col < pamP->width; ++col) {
+            unsigned int plane;
+            for (plane = 0; plane < pamP->depth; ++plane) {
+                if (tuplerow[col][plane] > pamP->maxval) {
+                    pm_asprintf(errorP,
+                                "Plane %u sample value %lu exceeds the "
+                                "image maxval of %lu",
+                                plane, tuplerow[col][plane], pamP->maxval);
+                    return;
+                }
+            }
+        }
+        *errorP = NULL;
+    }
+}
+
+
+
+static void
 readRawNonPbmRow(const struct pam * const pamP,
                  tuple *            const tuplerow) {
 
@@ -234,8 +279,10 @@ readRawNonPbmRow(const struct pam * const pamP,
             case 4: parse4BpsRow(pamP, tuplerow, inbuf); break;
             default:
                 pm_asprintf(&error, "invalid bytes per sample passed to "
-                            "pnm_formatpamrow(): %u",  pamP->bytes_per_sample);
+                            "pnm_formatpamrow(): %u", pamP->bytes_per_sample);
             }
+            if (error == NULL)
+                validatePamRow(pamP, tuplerow, &error);
         }
     }
     pnm_freerowimage(inbuf);
@@ -264,7 +311,7 @@ pnm_readpamrow(const struct pam * const pamP,
     /* For speed, we don't check any of the inputs for consistency 
        here (unless it's necessary to avoid crashing).  Any consistency
        checking should have been done by a prior call to 
-       pnm_writepaminit().
+       pnm_readpaminit().
     */  
 
     /* Need a special case for raw PBM because it has multiple tuples (8)
diff --git a/lib/libpgm1.c b/lib/libpgm1.c
index 987ee04e..57344c16 100644
--- a/lib/libpgm1.c
+++ b/lib/libpgm1.c
@@ -100,10 +100,13 @@ validateComputableSize(unsigned int const cols,
    you expect.  That failed expectation can be disastrous if you use
    it to allocate memory.
 
+   It is very normal to allocate space for a pixel row, so we make sure
+   the size of a pixel row, in bytes, can be represented by an 'int'.
+
    A common operation is adding 1 or 2 to the highest row or
    column number in the image, so we make sure that's possible.
 -----------------------------------------------------------------------------*/
-    if (cols > INT_MAX - 2)
+    if (cols > INT_MAX / (sizeof(gray)) || cols > INT_MAX - 2)
         pm_error("image width (%u) too large to be processed", cols);
     if (rows > INT_MAX - 2)
         pm_error("image height (%u) too large to be processed", rows);
@@ -172,11 +175,44 @@ pgm_readpgminit(FILE * const fileP,
 
 
 static void
+validateRpgmRow(gray *         const grayrow, 
+                unsigned int   const cols,
+                gray           const maxval,
+                const char **  const errorP) {
+/*----------------------------------------------------------------------------
+  Check for sample values above maxval in input.  
+
+  Note: a program that wants to deal with invalid sample values itself can
+  simply make sure it uses a sufficiently high maxval on the read function
+  call, so this validation never fails.
+-----------------------------------------------------------------------------*/
+    if (maxval == 255 || maxval == 65535) {
+        /* There's no way a sample can be invalid, so we don't need to look at
+           the samples individually.
+        */
+        *errorP = NULL;
+    } else {
+        unsigned int col;
+        for (col = 0; col < cols; ++col) {
+            if (grayrow[col] > maxval) {
+                pm_asprintf(errorP,
+                            "gray value %u is greater than maxval (%u)",
+                            grayrow[col], maxval);
+                return;
+            }
+        }
+        *errorP = NULL;
+    }
+}  
+
+
+
+static void
 readRpgmRow(FILE * const fileP,
-               gray * const grayrow, 
-               int    const cols,
-               gray   const maxval,
-               int    const format) {
+            gray * const grayrow, 
+            int    const cols,
+            gray   const maxval,
+            int    const format) {
 
     unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
     int          const bytesPerRow    = cols * bytesPerSample;
@@ -198,7 +234,6 @@ readRpgmRow(FILE * const fileP,
             pm_asprintf(&error, "Error reading row.  Short read of %u bytes "
                         "instead of %u", (unsigned)rc, bytesPerRow);
         else {
-            error = NULL;
             if (maxval < 256) {
                 unsigned int col;
                 for (col = 0; col < cols; ++col)
@@ -218,6 +253,7 @@ readRpgmRow(FILE * const fileP,
                     grayrow[col] = g;
                 }
             }
+            validateRpgmRow(grayrow, cols, maxval, &error); 
         }
         free(rowBuffer);
     }
@@ -241,7 +277,7 @@ readPbmRow(FILE * const fileP,
     jmp_buf * origJmpbufP;
     bit * bitrow;
     
-    bitrow = pbm_allocrow(cols);
+    bitrow = pbm_allocrow_packed(cols);
     if (setjmp(jmpbuf) != 0) {
         pbm_freerow(bitrow);
         pm_setjmpbuf(origJmpbufP);
@@ -251,10 +287,14 @@ readPbmRow(FILE * const fileP,
 
         pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
 
-        pbm_readpbmrow(fileP, bitrow, cols, format);
-        for (col = 0; col < cols; ++col)
-            grayrow[col] = (bitrow[col] == PBM_WHITE ) ? maxval : 0;
+        pbm_readpbmrow_packed(fileP, bitrow, cols, format);
 
+        for (col = 0; col < cols; ++col) {
+            grayrow[col] =
+                ((bitrow[col/8] >> (7 - col%8)) & 0x1) == PBM_WHITE ?
+                maxval : 0
+                ;
+        }
         pm_setjmpbuf(origJmpbufP);
     }
     pbm_freerow(bitrow);
diff --git a/lib/libpnm1.c b/lib/libpnm1.c
index 536e5dc4..29fee13a 100644
--- a/lib/libpnm1.c
+++ b/lib/libpnm1.c
@@ -72,10 +72,13 @@ validateComputableSize(unsigned int const cols,
    you expect.  That failed expectation can be disastrous if you use
    it to allocate memory.
 
+   It is very normal to allocate space for a pixel row, so we make sure
+   the size of a pixel row, in bytes, can be represented by an 'int'.
+
    A common operation is adding 1 or 2 to the highest row or
    column number in the image, so we make sure that's possible.
 -----------------------------------------------------------------------------*/
-    if (cols > INT_MAX - 2)
+    if (cols > INT_MAX/(sizeof(pixval) * 3) || cols > INT_MAX - 2)
         pm_error("image width (%u) too large to be processed", cols);
     if (rows > INT_MAX - 2)
         pm_error("image height (%u) too large to be processed", rows);
@@ -178,10 +181,10 @@ readpbmrow(FILE * const fileP,
     jmp_buf * origJmpbufP;
     bit * bitrow;
 
-    bitrow = pbm_allocrow(cols);
+    bitrow = pbm_allocrow_packed(cols);
 
     if (setjmp(jmpbuf) != 0) {
-        pbm_freerow(bitrow);
+        pbm_freerow_packed(bitrow);
         pm_setjmpbuf(origJmpbufP);
         pm_longjmp();
     } else {
@@ -189,11 +192,14 @@ readpbmrow(FILE * const fileP,
 
         pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
 
-        pbm_readpbmrow(fileP, bitrow, cols, format);
-
-        for (col = 0; col < cols; ++col)
-            PNM_ASSIGN1(xelrow[col], bitrow[col] == PBM_BLACK ? 0 : maxval);
+        pbm_readpbmrow_packed(fileP, bitrow, cols, format);
 
+        for (col = 0; col < cols; ++col) {
+            pixval const g =
+                ((bitrow[col/8] >> (7 - col%8)) & 0x1) == PBM_WHITE ?
+                maxval : 0;
+            PNM_ASSIGN1(xelrow[col], g);
+        }
         pm_setjmpbuf(origJmpbufP);
     }
     pbm_freerow(bitrow);
diff --git a/lib/libppm1.c b/lib/libppm1.c
index 195aec70..ff940540 100644
--- a/lib/libppm1.c
+++ b/lib/libppm1.c
@@ -100,10 +100,13 @@ validateComputableSize(unsigned int const cols,
    you expect.  That failed expectation can be disastrous if you use
    it to allocate memory.
 
+   It is very normal to allocate space for a pixel row, so we make sure
+   the size of a pixel row, in bytes, can be represented by an 'int'.
+
    A common operation is adding 1 or 2 to the highest row or
    column number in the image, so we make sure that's possible.
 -----------------------------------------------------------------------------*/
-    if (cols > INT_MAX - 2)
+    if (cols > INT_MAX/(sizeof(pixval) * 3) || cols > INT_MAX - 2)
         pm_error("image width (%u) too large to be processed", cols);
     if (rows > INT_MAX - 2)
         pm_error("image height (%u) too large to be processed", rows);
@@ -224,6 +227,52 @@ interpRasterRowRaw(const unsigned char * const rowBuffer,
 
 
 static void
+validateRppmRow(pixel *       const pixelrow,
+                unsigned int  const cols,
+                pixval        const maxval,
+                const char ** const errorP) {
+/*----------------------------------------------------------------------------
+  Check for sample values above maxval in input.  
+
+  Note: a program that wants to deal with invalid sample values itself can
+  simply make sure it uses a sufficiently high maxval on the read function
+  call, so this validation never fails.
+-----------------------------------------------------------------------------*/
+    if (maxval == 255 || maxval == 65535) {
+        /* There's no way a sample can be invalid, so we don't need to look at
+           the samples individually.
+        */
+        *errorP = NULL;
+    } else {
+        unsigned int col;
+
+        for (col = 0, *errorP = NULL; col < cols && !*errorP; ++col) {
+            pixval const r = PPM_GETR(pixelrow[col]);
+            pixval const g = PPM_GETG(pixelrow[col]);
+            pixval const b = PPM_GETB(pixelrow[col]);
+
+            if (r > maxval)
+                pm_asprintf(
+                    errorP,
+                    "Red sample value %u is greater than maxval (%u)",
+                    r, maxval);
+            else if (g > maxval)
+                pm_asprintf(
+                    errorP,
+                    "Green sample value %u is greater than maxval (%u)",
+                    g, maxval);
+            else if (b > maxval)
+                pm_asprintf(
+                    errorP,
+                    "Blue sample value %u is greater than maxval (%u)",
+                    b, maxval);
+        }
+    }
+}
+
+
+
+static void
 readRppmRow(FILE *       const fileP, 
             pixel *      const pixelrow, 
             unsigned int const cols, 
@@ -259,7 +308,8 @@ readRppmRow(FILE *       const fileP,
                             "instead of %u", (unsigned)bytesRead, bytesPerRow);
             else {
                 interpRasterRowRaw(rowBuffer, pixelrow, cols, bytesPerSample);
-                error = NULL;
+
+                validateRppmRow(pixelrow, cols, maxval, &error);
             }
         }
         free(rowBuffer);
@@ -319,10 +369,10 @@ readPbmRow(FILE *       const fileP,
     jmp_buf * origJmpbufP;
     bit * bitrow;
 
-    bitrow = pbm_allocrow(cols);
+    bitrow = pbm_allocrow_packed(cols);
 
     if (setjmp(jmpbuf) != 0) {
-        pbm_freerow(bitrow);
+        pbm_freerow_packed(bitrow);
         pm_setjmpbuf(origJmpbufP);
         pm_longjmp();
     } else {
@@ -330,10 +380,12 @@ readPbmRow(FILE *       const fileP,
 
         pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
 
-        pbm_readpbmrow(fileP, bitrow, cols, format);
+        pbm_readpbmrow_packed(fileP, bitrow, cols, format);
 
         for (col = 0; col < cols; ++col) {
-            pixval const g = (bitrow[col] == PBM_WHITE) ? maxval : 0;
+            pixval const g =
+                ((bitrow[col/8] >> (7 - col%8)) & 0x1) == PBM_WHITE ?
+                maxval : 0;
             PPM_ASSIGN(pixelrow[col], g, g, g);
         }
         pm_setjmpbuf(origJmpbufP);
diff --git a/lib/standardppmdfont.c b/lib/standardppmdfont.c
index aa4707e2..bc0c8ff8 100644
--- a/lib/standardppmdfont.c
+++ b/lib/standardppmdfont.c
@@ -1,4 +1,4 @@
-/* THIS FILE WAS GENERATED BY 'ppmdcfont' from a ppmfont file. */
+/* THIS FILE WAS GENERATED BY 'ppmdcfont' from a ppmdfont file. */
 
 #include "ppmdfont.h"