diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-11-07 01:33:26 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-11-07 01:33:26 +0000 |
commit | 42efa67c47521596088768d82f5665b15d03d6bf (patch) | |
tree | 358e75c107ff9ef1a45e3f4a15085d1f3f7a7a42 | |
parent | 109fb3ec30eaca9ce3427d58a2b8fb1c038a7c4f (diff) | |
download | netpbm-mirror-42efa67c47521596088768d82f5665b15d03d6bf.tar.gz netpbm-mirror-42efa67c47521596088768d82f5665b15d03d6bf.tar.xz netpbm-mirror-42efa67c47521596088768d82f5665b15d03d6bf.zip |
fix arithmetic overflows
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@4177 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r-- | converter/other/sunicontopnm.c | 32 | ||||
-rw-r--r-- | converter/pbm/escp2topbm.c | 37 | ||||
-rw-r--r-- | converter/pbm/mgrtopbm.c | 80 | ||||
-rw-r--r-- | converter/pbm/ybmtopbm.c | 37 | ||||
-rw-r--r-- | doc/HISTORY | 4 | ||||
-rw-r--r-- | editor/pamcut.c | 4 | ||||
-rw-r--r-- | editor/pbmpscale.c | 36 | ||||
-rw-r--r-- | editor/pnmcat.c | 5 | ||||
-rw-r--r-- | editor/pnmpad.c | 10 | ||||
-rw-r--r-- | lib/libpbm2.c | 7 |
10 files changed, 165 insertions, 87 deletions
diff --git a/converter/other/sunicontopnm.c b/converter/other/sunicontopnm.c index eff1be58..93ddc0ab 100644 --- a/converter/other/sunicontopnm.c +++ b/converter/other/sunicontopnm.c @@ -12,10 +12,12 @@ /* Most icon images are monochrome: Depth=1 + Depth=8 images are extremely rare. At least some of these are color - images but we can't tell the palette color order. + images but we haven't found information on the palette color order. Output will be in pgm. Convert to ppm with pgmtoppm or pamlookup - if necessary. + if necessary. It is up to the user to provide the color palette in + a form acceptable by the above conversion utilities. */ #include <assert.h> @@ -28,9 +30,9 @@ static void -ReadIconFileHeader(FILE * const file, - int * const widthP, - int * const heightP, +ReadIconFileHeader(FILE * const file, + int * const widthP, + int * const heightP, int * const depthP, int * const bitsPerItemP) { @@ -49,7 +51,7 @@ ReadIconFileHeader(FILE * const file, ch == ' ') ; for (i = 0; - ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && + ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && ch != ' ' && (i < (sizeof(variable) - 1)); ++i) { variable[i] = ch; @@ -82,7 +84,7 @@ ReadIconFileHeader(FILE * const file, } else if (streq(variable, "Valid_bits_per_item")) { if (value != 16 && value !=32) pm_error("invalid Valid_bits_per_item"); - *bitsPerItemP = value; + *bitsPerItemP = value; ++fieldCt; } } @@ -93,12 +95,19 @@ ReadIconFileHeader(FILE * const file, if (*widthP <= 0) pm_error("invalid width (must be positive): %d", *widthP); + else if (*widthP % 8 > 0) + pm_message("warning: width not a multiple of 8: %d", *widthP); + /* We don't know whether widths which are not a multiple of 8 + are allowed. The program must gracefully handle this case + because sun icon files are easy to edit by hand. + */ if (*heightP <= 0) pm_error("invalid height (must be positive): %d", *heightP); } + int main(int argc, const char ** argv) { @@ -125,7 +134,7 @@ main(int argc, const char ** argv) { maxval = 1; pbm_writepbminit(stdout, cols, rows, 0); bitrow = pbm_allocrow_packed(cols); - colChars = cols / 8; + colChars = pbm_packed_bytes(cols); } else { assert(depth == 8); format = PGM_TYPE; @@ -156,7 +165,7 @@ main(int argc, const char ** argv) { else grayrow[colChar] = data; } else - pm_error("error scanning bits item %u" , colChar); + pm_error("error scanning bits item %u", colChar); } /* output row */ @@ -166,6 +175,11 @@ main(int argc, const char ** argv) { pgm_writepgmrow(stdout, grayrow, cols, maxval, 0); } + if (format == PBM_TYPE) + pbm_freerow_packed(bitrow); + else + pgm_freerow(grayrow); + pm_close(ifP); pm_close(stdout); return 0; diff --git a/converter/pbm/escp2topbm.c b/converter/pbm/escp2topbm.c index 632e6345..de3ea931 100644 --- a/converter/pbm/escp2topbm.c +++ b/converter/pbm/escp2topbm.c @@ -47,10 +47,17 @@ #include <stdbool.h> +#include <assert.h> #include "mallocvar.h" #include "pbm.h" +static unsigned int widthMax = 127 * 256 + 255; + /* Limit in official Epson manual */ + +static unsigned int const heightMax = 5120 * 200; + /* 5120 rows is sufficient for US legal at 360 DPI */ + #define ESC 033 @@ -97,7 +104,7 @@ readChar(FILE * const ifP) { -static void +static void readStripeHeader(unsigned int * const widthThisStripeP, unsigned int * const rowsThisStripeP, unsigned int * const compressionP, @@ -113,13 +120,17 @@ readStripeHeader(unsigned int * const widthThisStripeP, compression = stripeHeader[0]; /* verticalResolution = stripeHeader[1]; */ /* horizontalResolution = stripeHeader[2]; */ - rowsThisStripe = stripeHeader[3]; + rowsThisStripe = stripeHeader[3]; widthThisStripe = stripeHeader[5] * 256 + stripeHeader[4]; if (widthThisStripe == 0 || rowsThisStripe == 0) pm_error("Error: Abnormal value in data block header: " "Says stripe has zero width or height"); + if (widthThisStripe > widthMax) + pm_error("Error: Abnormal width value in data block header: %u", + widthThisStripe); + if (compression != 0 && compression != 1) pm_error("Error: Unknown compression mode %u", compression); @@ -132,7 +143,7 @@ readStripeHeader(unsigned int * const widthThisStripeP, /* RLE decoder */ static void -decEpsonRLE(unsigned int const blockSize, +decEpsonRLE(unsigned int const blockSize, unsigned char * const outBuffer, FILE * const ifP) { @@ -163,7 +174,7 @@ decEpsonRLE(unsigned int const blockSize, unsigned int i; for (i = 0; i < runLength; ++i) - outBuffer[dpos + i] = repeatChar; + outBuffer[dpos + i] = repeatChar; dpos += runLength; } } @@ -180,7 +191,7 @@ processStripeRaster(unsigned char ** const bitarray, unsigned int const compression, FILE * const ifP, unsigned int * const rowIdxP) { - + unsigned int const initialRowIdx = *rowIdxP; unsigned int const widthInBytes = pbm_packed_bytes(width); unsigned int const blockSize = rowsThisStripe * widthInBytes; @@ -221,14 +232,12 @@ expandBitarray(unsigned char *** const bitarrayP, unsigned int * const bitarraySizeP) { unsigned int const heightIncrement = 5120; - unsigned int const heightMax = 5120 * 200; - /* 5120 rows is sufficient for US legal at 360 DPI */ *bitarraySizeP += heightIncrement; if (*bitarraySizeP > heightMax) - pm_error("Image too tall"); + pm_error("Error: Image too tall"); else - REALLOCARRAY_NOFAIL(*bitarrayP, *bitarraySizeP); + REALLOCARRAY_NOFAIL(*bitarrayP, *bitarraySizeP); } @@ -244,7 +253,7 @@ writePbmImage(unsigned char ** const bitarray, pm_error("No image"); pbm_writepbminit(stdout, width, height, 0); - + for (row = 0; row < height; ++row) { pbm_cleanrowend_packed(bitarray[row], width); pbm_writepbmrow_packed(stdout, bitarray[row], width, 0); @@ -300,7 +309,7 @@ main(int argc, unsigned int compression; unsigned int rowsThisStripe; unsigned int widthThisStripe; - + readStripeHeader(&widthThisStripe, &rowsThisStripe, &compression, ifP); @@ -311,7 +320,7 @@ main(int argc, /* The official Epson manual says valid values are 1, 8, 24 but we just print a warning message and continue if other values are detected. - */ + */ pm_message("Abnormal data block height value: %u " "(ignoring)", rowsThisStripe); @@ -326,6 +335,10 @@ main(int argc, width, widthThisStripe); } height += rowsThisStripe; + assert(height <= INT_MAX - 10); + /* Becuse image height is tested in expandBitarray() + with a more stringent condition. + */ if (height > bitarraySize) expandBitarray(&bitarray, &bitarraySize); diff --git a/converter/pbm/mgrtopbm.c b/converter/pbm/mgrtopbm.c index 9f7004a1..e0a88883 100644 --- a/converter/pbm/mgrtopbm.c +++ b/converter/pbm/mgrtopbm.c @@ -16,12 +16,54 @@ static void -readMgrHeader(FILE * const ifP, - unsigned int * const colsP, - unsigned int * const rowsP, - unsigned int * const depthP, +interpHdrWidth(struct b_header const head, + unsigned int * const colsP) { + + if (head.h_wide < ' ' || head.l_wide < ' ') + pm_error("Invalid width field in MGR header"); + else { + unsigned int const maxDimension = 4095; + + unsigned int const cols = + (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' '); + + if (cols == 0 || cols > maxDimension) + pm_error("Invalid width value (%u) in MGR header", cols); + else + *colsP = cols; + } +} + + + +static void +interpHdrHeight(struct b_header const head, + unsigned int * const rowsP) { + + if (head.h_high < ' ' || head.l_high < ' ') + pm_error("Invalid height field in MGR header"); + else { + unsigned int const maxDimension = 4095; + + unsigned int const rows = + (((int)head.h_high - ' ') << 6) + ((int)head.l_high - ' '); + + if (rows == 0 || rows > maxDimension) + pm_error("Invalid height value (%u) in MGR header", rows); + else + *rowsP = rows; + } +} + + + +static void +readMgrHeader(FILE * const ifP, + unsigned int * const colsP, + unsigned int * const rowsP, + unsigned int * const depthP, unsigned int * const padrightP ) { - + struct b_header head; unsigned int pad; size_t bytesRead; @@ -31,10 +73,10 @@ readMgrHeader(FILE * const ifP, pm_error("Unable to read 1st byte of file. " "fread() returns errno %d (%s)", errno, strerror(errno)); - if (head.magic[0] == 'y' && head.magic[1] == 'z') { + if (head.magic[0] == 'y' && head.magic[1] == 'z') { /* new style bitmap */ size_t bytesRead; - bytesRead = fread(&head.depth, + bytesRead = fread(&head.depth, sizeof(head) - sizeof(struct old_b_header), 1, ifP); if (bytesRead != 1 ) pm_error("Unable to read header after 1st byte. " @@ -42,11 +84,11 @@ readMgrHeader(FILE * const ifP, errno, strerror(errno)); *depthP = (int) head.depth - ' '; pad = 8; - } else if (head.magic[0] == 'x' && head.magic[1] == 'z') { + } else if (head.magic[0] == 'x' && head.magic[1] == 'z') { /* old style bitmap with 32-bit padding */ *depthP = 1; pad = 32; - } else if (head.magic[0] == 'z' && head.magic[1] == 'z') { + } else if (head.magic[0] == 'z' && head.magic[1] == 'z') { /* old style bitmap with 16-bit padding */ *depthP = 1; pad = 16; @@ -60,14 +102,10 @@ readMgrHeader(FILE * const ifP, pad = 0; /* should never reach here */ } - if (head.h_wide < ' ' || head.l_wide < ' ') - pm_error("Invalid width field in MGR header"); - if (head.h_high < ' ' || head.l_high < ' ') - pm_error("Invalid width field in MGR header"); - - *colsP = (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' '); - *rowsP = (((int)head.h_high - ' ') << 6) + ((int) head.l_high - ' '); - *padrightP = ( ( *colsP + pad - 1 ) / pad ) * pad - *colsP; + interpHdrWidth (head, colsP); + interpHdrHeight(head, rowsP); + + *padrightP = ((*colsP + pad - 1) / pad) * pad - *colsP; } @@ -93,7 +131,7 @@ main(int argc, inputFileName = argv[1]; else inputFileName = "-"; - + ifP = pm_openr(inputFileName); readMgrHeader(ifP, &cols, &rows, &depth, &padright); @@ -103,7 +141,7 @@ main(int argc, pbm_writepbminit(stdout, cols, rows, 0); bitrow = pbm_allocrow_packed(cols + padright); - + itemCount = (cols + padright ) / 8; for (row = 0; row < rows; ++row) { @@ -128,9 +166,9 @@ main(int argc, Changed bitrow from plain to raw, read function from getc() to fread(), write function from pbm_writepbmrow() to pbm_writepbmrow_packed(). Retired bitwise transformation functions. - + NOT tested for old-style format files. Only one zz file in mgrsrc-0.69 . - + */ diff --git a/converter/pbm/ybmtopbm.c b/converter/pbm/ybmtopbm.c index 2a429086..36f2dee7 100644 --- a/converter/pbm/ybmtopbm.c +++ b/converter/pbm/ybmtopbm.c @@ -19,45 +19,48 @@ static short const ybmMagic = ( ( '!' << 8 ) | '!' ); static void -getinit(FILE * const ifP, - short * const colsP, - short * const rowsP, - short * const depthP) { +getinit(FILE * const ifP, + unsigned int * const colsP, + unsigned int * const rowsP, + int * const depthP) { - short magic; + short int magic; + short int cols, rows; int rc; rc = pm_readbigshort(ifP, &magic); if (rc == -1) pm_error("EOF / read error"); - - if (magic != ybmMagic) + else if (magic != ybmMagic) pm_error("bad magic number in YBM file"); - rc = pm_readbigshort(ifP, colsP); + rc = pm_readbigshort(ifP, &cols); if (rc == -1 ) pm_error("EOF / read error"); + else if (cols <= 0) + pm_error("invalid width value in YBM file"); - rc = pm_readbigshort(ifP, rowsP); + rc = pm_readbigshort(ifP, &rows); if (rc == -1) pm_error("EOF / read error"); + else if (rows <= 0) + pm_error("invalid height value in YBM file"); + *colsP = (unsigned int) cols; + *rowsP = (unsigned int) rows; *depthP = 1; } - - - int main(int argc, const char * argv[]) { FILE * ifP; bit * bitrow; - short rows, cols; + unsigned int rows, cols; unsigned int row; - short depth; + int depth; const char * inputFile; pm_proginit(&argc, argv); @@ -76,8 +79,8 @@ main(int argc, const char * argv[]) { getinit(ifP, &cols, &rows, &depth); if (depth != 1) - pm_error("YBM file has depth of %u, must be 1", (unsigned)depth); - + pm_error("YBM file has depth of %u, must be 1", (unsigned int) depth); + pbm_writepbminit(stdout, cols, rows, 0); bitrow = pbm_allocrow_packed(cols + 8); @@ -92,7 +95,7 @@ main(int argc, const char * argv[]) { for (i = 0; i < itemCt; ++i) { short int item; pm_readbigshort(ifP, &item); - itemrow[i] = (uint16_t) item; + itemrow[i] = (uint16_t) item; } for (i = 0; i < pbm_packed_bytes(cols); ++i) diff --git a/doc/HISTORY b/doc/HISTORY index bbd399b7..d9462f87 100644 --- a/doc/HISTORY +++ b/doc/HISTORY @@ -18,6 +18,10 @@ not yet BJH Release 10.97.00 the image than the first. Always broken (Pamrubber was new in Netpbm 10.54 (March 2011)). + sunicontopnm, escp2topbm, mgrtopbm, ybmtopbm, pamcut, pbmpscale, + pnmcat, pnmpad: Fix arithmetic overrun with ridiculously large + image. + pbmclean: Fix overallocation of memory (waste). libnetpbm: When validating computable size of width and height, diff --git a/editor/pamcut.c b/editor/pamcut.c index 1fc9d9b2..7870fd70 100644 --- a/editor/pamcut.c +++ b/editor/pamcut.c @@ -712,7 +712,7 @@ extractRowsPBM(const struct pam * const inpamP, if (leftcol > 0) { totalWidth = MAX(rightcol+1, inpamP->width) + 7; - if (totalWidth > INT_MAX) + if (totalWidth > INT_MAX - 10) /* Prevent overflows in pbm_allocrow_packed() */ pm_error("Specified right edge is too far " "from the right end of input image"); @@ -721,7 +721,7 @@ extractRowsPBM(const struct pam * const inpamP, writeOffset = leftcol; } else { totalWidth = -leftcol + MAX(rightcol+1, inpamP->width); - if (totalWidth > INT_MAX) + if (totalWidth > INT_MAX - 10) pm_error("Specified left/right edge is too far " "from the left/right end of input image"); diff --git a/editor/pbmpscale.c b/editor/pbmpscale.c index 9ab89350..434c7965 100644 --- a/editor/pbmpscale.c +++ b/editor/pbmpscale.c @@ -12,7 +12,7 @@ #define LEFTBITS pm_byteLeftBits #define RIGHTBITS pm_byteRightBits -/* Table for translating bit pattern into "corners" flag element */ +/* Table for translating bit pattern into "corners" flag element */ unsigned char const transTable[512] = { @@ -141,7 +141,7 @@ validateComputableDimensions(unsigned int const width, See validateComputetableSize() in libpam.c and pbm_readpbminitrest() in libpbm2.c -----------------------------------------------------------------------------*/ - unsigned int const maxWidthHeight = INT_MAX - 2; + unsigned int const maxWidthHeight = INT_MAX - 10; unsigned int const maxScaleFactor = maxWidthHeight / MAX(height, width); if (scaleFactor > maxScaleFactor) @@ -154,8 +154,8 @@ validateComputableDimensions(unsigned int const width, static void writeBitSpan(unsigned char * const packedBitrow, - int const cols, - int const offset, + unsigned int const cols, + unsigned int const offset, int const color) { /*---------------------------------------------------------------------------- Write white (color="0") or black (="1") bits into packedBitrow[], @@ -191,8 +191,8 @@ setFlags(const bit * const prevrow, unsigned char * const flags, unsigned int const cols ) { /*---------------------------------------------------------------------------- - Scan one row, examining the row above and row below, and determine - whether there are "corners" for each pixel. Feed a 9 bit sample into + Scan one row, examining the row above and row below, and determine + whether there are "corners" for each pixel. Feed a 9 bit sample into pre-calculated array transTable[512] to calculate all four corner statuses at once. @@ -220,7 +220,7 @@ setFlags(const bit * const prevrow, The high byte of the patterns is a mask, which determines which bits are not ignored. */ - uint16_t const patterns[] + uint16_t const patterns[] = { 0x0000, 0xd555, /* no corner */ 0x0001, 0xffc1, 0xd514, /* normal corner */ 0x0002, 0xd554, 0xd515, 0xbea2, 0xdfc0, 0xfd81, 0xfd80, 0xdf80, @@ -230,7 +230,7 @@ setFlags(const bit * const prevrow, /* For example, the NE corner is examined with the following 8 bit sample: Current : W : NW : N : NE : E : SE : S - (SW is the "square behind") + (SW is the "square behind") */ #endif @@ -257,7 +257,7 @@ setFlags(const bit * const prevrow, sample = ( ( prevrow24 >> ( 8 -offset) ) & 0x01c0 ) | ( ( thisrow24 >> (11 -offset) ) & 0x0038 ) | ( ( nextrow24 >> (14 -offset) ) & 0x0007 ); - + flags[col] = transTable[sample]; } } @@ -275,14 +275,14 @@ expandRow(const bit * const thisrow, int const ucutoff) { /*---------------------------------------------------------------------------- Process one row, using flags array as reference. If pixel has no corners - output a NxN square of the given color, otherwise output with the + output a NxN square of the given color, otherwise output with the specified corner area(s) clipped off. -----------------------------------------------------------------------------*/ unsigned int const outcols = cols * scale; unsigned int i; unsigned int col; - + for (i = 0; i < scale; ++i) { int const zone = (i > ucutoff) - (i < cutoff); int const cut1 = @@ -297,7 +297,7 @@ expandRow(const bit * const thisrow, cut[1] = cut1; cut[2] = cut1 ? cut1 - 1 : 0; cut[3] = (cut1 && cutoff > 1) ? cut1 - 1 : cut1; - + for (col = 0; col < cols; ++col) { unsigned int const col8 = col / 8; unsigned int const offset = col % 8; @@ -309,11 +309,11 @@ expandRow(const bit * const thisrow, if (flag == 0x00) { /* There are no corners, no color change */ outcol += scale; - } else { + } else { switch (zone) { case -1: if (i==0 && flag == 0xff) { - /* No corners, color changed */ + /* No corners, color changed */ cutl = cutr = 0; flags[col] = 0x00; /* Use above skip procedure next cycle */ @@ -330,7 +330,7 @@ expandRow(const bit * const thisrow, cutr = cut[SE(flag)]; break; } - + if (cutl > 0) { writeBitSpan(outrow, cutl, outcol, !pix); outcol += cutl; @@ -384,10 +384,10 @@ main(int argc, const char ** argv) { pbm_readpbminit(ifP, &cols, &rows, &format) ; - validateComputableDimensions(cols, rows, cmdline.scale); + validateComputableDimensions(cols, rows, cmdline.scale); outcols = cols * cmdline.scale; - outrows = rows * cmdline.scale; + outrows = rows * cmdline.scale; /* Initialize input buffers. We add a margin of 8 bits on the right of the three rows. @@ -402,7 +402,7 @@ main(int argc, const char ** argv) { for (i = 0; i < pbm_packed_bytes(cols + 8); ++i) edgerow[i] = 0x00; - /* Add blank bytes at right edges */ + /* Add blank bytes at right edges */ for (i = 0; i < 3; ++i) buffer[i][pbm_packed_bytes(cols + 8) - 1] = 0x00; diff --git a/editor/pnmcat.c b/editor/pnmcat.c index c660698c..01811cb4 100644 --- a/editor/pnmcat.c +++ b/editor/pnmcat.c @@ -115,7 +115,7 @@ parseCommandLine(int argc, const char ** const argv, cmdlineP->backcolor = BACK_AUTO; if (jtop + jbottom + jleft + jright + jcenter > 1) - pm_error("You may specify onlyone of -jtop, -jbottom, " + pm_error("You may specify only one of -jtop, -jbottom, " "-jleft, and -jright"); else { switch (cmdlineP->orientation) { @@ -367,7 +367,8 @@ getPbmImageInfo(ImgInfo const img[], switch (backcolor) { case BACK_AUTO: { bit bgBit; - img2[i].proberow = pbm_allocrow_packed(img[i].cols+7); + img2[i].proberow = + pbm_allocrow_packed((unsigned int)img[i].cols + 7); pbm_readpbmrow_bitoffset( img[i].ifP, img2[i].proberow, img[i].cols, img[i].format, img2[i].offset % 8); diff --git a/editor/pnmpad.c b/editor/pnmpad.c index 55cdcd6c..1e704724 100644 --- a/editor/pnmpad.c +++ b/editor/pnmpad.c @@ -11,7 +11,7 @@ #include "shhopt.h" #include "pnm.h" -#define MAX_WIDTHHEIGHT INT_MAX-10 +#define MAX_WIDTHHEIGHT ((INT_MAX)-10) /* The maximum width or height value we can handle without risking arithmetic overflow */ @@ -268,7 +268,7 @@ validateHorizontalSize(struct cmdlineInfo const cmdline, pm_error("The right padding value you specified is too large."); if ((double) cols + - (double) lpad + + (double) lpad + (double) rpad + (double) mwidthMaxPad > MAX_WIDTHHEIGHT) pm_error("Given padding parameters make output width too large " @@ -378,7 +378,7 @@ computePadSizesOneDim(unsigned int const unpaddedSize, unsigned int const totalPadBeforeMult = begPadBeforeMult + endPadBeforeMult; double const begFrac = - totalPadBeforeMult > 0 ? + totalPadBeforeMult > 0 ? (double)begPadBeforeMult / totalPadBeforeMult : 0.0; unsigned int const addlMsizeBegPad = ROUNDU(morePadNeeded * begFrac); @@ -501,7 +501,7 @@ reportPadSizes(int const inCols, unsigned int const outCols = inCols + lpad + rpad; unsigned int const outRows = inRows + tpad + bpad; - + printf("%u %u %u %u %u %u\n", lpad, rpad, tpad, bpad, outCols, outRows); } @@ -547,7 +547,7 @@ padPbm(FILE * const ifP, /* Write top margin */ for (row = 0; row < tpad; ++row) pbm_writepbmrow_packed(stdout, bgrow, newcols, 0); - + /* Read rows, shift and write with left and right margins added */ for (row = 0; row < rows; ++row) { pbm_readpbmrow_bitoffset(ifP, newrow, cols, format, lpad); diff --git a/lib/libpbm2.c b/lib/libpbm2.c index 1ad93534..2a2e2aac 100644 --- a/lib/libpbm2.c +++ b/lib/libpbm2.c @@ -216,6 +216,9 @@ pbm_readpbmrow_bitoffset(FILE * const ifP, Read it into packedBits[], preserving surrounding image data. Logic not tested for negative offsets. + + Because we are reading in packed mode large cols and offset values are + acceptable; dividing by 8 prevents overflows. -----------------------------------------------------------------------------*/ unsigned int const rsh = offset % 8; unsigned int const lsh = (8 - rsh) % 8; @@ -224,13 +227,15 @@ pbm_readpbmrow_bitoffset(FILE * const ifP, Aligned to nearest byte boundary to the left, so the first few bits might contain original data, not output. */ - unsigned int const last = pbm_packed_bytes(cols+rsh) - 1; + unsigned int const last = pbm_packed_bytes((unsigned int)cols + rsh) - 1; /* Position within window of rightmost byte after shift */ /* The original leftmost and rightmost chars. */ unsigned char const origHead = window[0]; unsigned char const origEnd = window[last]; + assert(cols > 0 && pbm_packed_bytes(cols) > 0); + pbm_readpbmrow_packed(ifP, window, cols, format); if (rsh > 0) { |