CBL-Mariner/SPECS-EXTENDED/netpbm/netpbm-security-code.patch

7037 lines
230 KiB
Diff

diff --git a/analyzer/pgmtexture.c b/analyzer/pgmtexture.c
index c69643e..eae0b42 100644
--- a/analyzer/pgmtexture.c
+++ b/analyzer/pgmtexture.c
@@ -54,6 +54,8 @@ vector(unsigned int const nl,
assert(nh >= nl);
+ overflow_add(nh - nl, 1);
+
MALLOCARRAY(v, (unsigned) (nh - nl + 1));
if (v == NULL)
@@ -85,6 +87,7 @@ matrix (unsigned int const nrl,
assert(nrh >= nrl);
/* allocate pointers to rows */
+ overflow_add(nrh - nrl, 1);
MALLOCARRAY(m, (unsigned) (nrh - nrl + 1));
if (m == NULL)
pm_error("Unable to allocate memory for a matrix.");
@@ -93,6 +96,7 @@ matrix (unsigned int const nrl,
assert (nch >= ncl);
+ overflow_add(nch - ncl, 1);
/* allocate rows and set pointers to them */
for (i = nrl; i <= nrh; ++i) {
MALLOCARRAY(m[i], (unsigned) (nch - ncl + 1));
diff --git a/converter/other/gemtopnm.c b/converter/other/gemtopnm.c
index 6bbfcc0..f7d1dc6 100644
--- a/converter/other/gemtopnm.c
+++ b/converter/other/gemtopnm.c
@@ -36,7 +36,7 @@
* read 4-plane color IMG files. Therefore changed from PBM to PPM.
* Bryan changed it further to use the PNM facilities so it outputs
* both PBM and PPM in the Netpbm tradition. Name changed from
- * gemtopbm to gemtopnm.
+ * gemtopbm to gemtopnm.
*/
#include <assert.h>
@@ -50,106 +50,107 @@
char pattern[8];
static void getinit ARGS ((FILE *file, int *colsP, int *rowsP, int *padrightP,
- int *patlenP, int *planesP));
+ int *patlenP, int *planesP));
int
main(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- int debug = 0;
- FILE *f;
+ int debug = 0;
+ FILE *f;
int row;
- int rows, cols, padright, patlen, planes;
+ int rows, cols, padright, patlen, planes;
/* attributes of input image */
int type; /* The format type (PBM/PPM) of the output image */
- bit *bitrow[4];
+ bit *bitrow[4];
/* One row of input, one or four planes. (If one, only [0] is defined)*/
xel * xelrow; /* One row of output */
- const char * const usage = "[-debug] [gem IMG file]";
- int argn;
+ const char * const usage = "[-debug] [gem IMG file]";
+ int argn;
/* Process multiple planes by maintaining a separate row of bits for each
- * plane. In a single-plane image, all we have to do is write out the
+ * plane. In a single-plane image, all we have to do is write out the
* first plane; in a multiple-plane image, we combine them just before writing
* out the row.
*/
- pnm_init( &argc, argv );
-
+ pnm_init( &argc, argv );
+
argn = 1;
- while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
- {
- if (pm_keymatch(argv[1], "-debug", 2))
- debug = 1;
- else
- pm_usage (usage);
- ++argn;
- }
+ while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
+ {
+ if (pm_keymatch(argv[1], "-debug", 2))
+ debug = 1;
+ else
+ pm_usage (usage);
+ ++argn;
+ }
- if (argc == argn)
- f = stdin;
- else {
- f = pm_openr (argv[argn]);
- ++argn;
- }
+ if (argc == argn)
+ f = stdin;
+ else {
+ f = pm_openr (argv[argn]);
+ ++argn;
+ }
- if (argn != argc)
- pm_usage (usage);
+ if (argn != argc)
+ pm_usage (usage);
- getinit (f, &cols, &rows, &padright, &patlen, &planes);
+ getinit (f, &cols, &rows, &padright, &patlen, &planes);
- if (planes == 1)
+ if (planes == 1)
type = PBM_TYPE;
- else
+ else
type = PPM_TYPE;
- pnm_writepnminit( stdout, cols, rows, MAXVAL, type, 0 );
+ pnm_writepnminit( stdout, cols, rows, MAXVAL, type, 0 );
- {
+ overflow_add(cols, padright);
+ {
/* allocate input row data structure */
int plane;
- for (plane = 0; plane < planes; plane++)
+ for (plane = 0; plane < planes; plane++)
bitrow[plane] = malloc (cols + padright);
}
xelrow = pnm_allocrow(cols+padright); /* Output row */
- for (row = 0; row < rows; ) {
+ for (row = 0; row < rows; ) {
int linerep;
int plane;
- linerep = 1;
- for (plane = 0; plane < planes; plane++) {
+ linerep = 1;
+ for (plane = 0; plane < planes; plane++) {
int col;
- col = 0;
- while (col < cols) {
+ col = 0;
+ while (col < cols) {
int c;
- switch (c = getc(f)) {
- case 0x80: /* Bit String */
+ switch (c = getc(f)) {
+ case 0x80: /* Bit String */
{
int j;
- c = getc(f); /* Byte count */
- if (debug)
+ c = getc(f); /* Byte count */
+ if (debug)
pm_message("bit string of %d bytes", c);
-
- if (col + c * 8 > cols + padright)
- pm_error ("bad byte count");
- for (j = 0; j < c; ++j) {
+
+ if (col + c * 8 > cols + padright)
+ pm_error ("bad byte count");
+ for (j = 0; j < c; ++j) {
int cc, k;
- cc = getc(f);
- for (k = 0x80; k; k >>= 1) {
- bitrow[plane][col] = (k & cc) ? 0 : 1;
- ++col;
- }
- }
+ cc = getc(f);
+ for (k = 0x80; k; k >>= 1) {
+ bitrow[plane][col] = (k & cc) ? 0 : 1;
+ ++col;
+ }
+ }
}
break;
- case 0: /* Pattern run */
+ case 0: /* Pattern run */
{
int j, l;
- c = getc(f); /* Repeat count */
- if (debug)
- pm_message("pattern run of %d repetitions", c);
+ c = getc(f); /* Repeat count */
+ if (debug)
+ pm_message("pattern run of %d repetitions", c);
/* line repeat */
if (c == 0) {
c = getc(f);
@@ -158,25 +159,25 @@ main(argc, argv)
linerep = getc(f);
break;
}
- fread (pattern, 1, patlen, f);
- if (col + c * patlen * 8 > cols + padright)
- pm_error ("bad pattern repeat count");
- for (j = 0; j < c; ++j)
- for (l = 0; l < patlen; ++l) {
+ fread (pattern, 1, patlen, f);
+ if (col + c * patlen * 8 > cols + padright)
+ pm_error ("bad pattern repeat count");
+ for (j = 0; j < c; ++j)
+ for (l = 0; l < patlen; ++l) {
int k;
- for (k = 0x80; k; k >>= 1) {
- bitrow[plane][col] = (k & pattern[l]) ? 0 : 1;
- ++col;
- }
+ for (k = 0x80; k; k >>= 1) {
+ bitrow[plane][col] = (k & pattern[l]) ? 0 : 1;
+ ++col;
+ }
}
}
break;
- default: /* Solid run */
+ default: /* Solid run */
{
int l, j;
- if (debug)
- pm_message("solid run of %d bytes %s", c & 0x7f,
+ if (debug)
+ pm_message("solid run of %d bytes %s", c & 0x7f,
c & 0x80 ? "on" : "off" );
/* each byte had eight bits DSB */
l = (c & 0x80) ? 0: 1;
@@ -185,23 +186,23 @@ main(argc, argv)
pm_error ("bad solid run repeat count");
for (j = 0; j < c; ++j) {
bitrow[plane][col] = l;
- ++col;
+ ++col;
}
}
- break;
+ break;
- case EOF: /* End of file */
- pm_error( "end of file reached" );
+ case EOF: /* End of file */
+ pm_error( "end of file reached" );
- }
- }
+ }
+ }
if ( debug )
pm_message( "EOL plane %d row %d", plane, row );
if (col != cols + padright)
pm_error( "EOL beyond edge" );
- }
+ }
- if (planes == 4) {
+ if (planes == 4) {
/* Construct a pixel from the 4 planes of bits for this row */
int col;
for (col = 0; col < cols; col++) {
@@ -212,21 +213,21 @@ main(argc, argv)
const int b_bit = !bitrow[2][col];
i = bitrow[3][col];
- /* Deal with weird GEM palette - white/black/gray are
- encoded oddly
+ /* Deal with weird GEM palette - white/black/gray are
+ encoded oddly
*/
- if (r_bit == g_bit && g_bit == b_bit) {
+ if (r_bit == g_bit && g_bit == b_bit) {
/* It's black, white, or gray */
- if (r_bit && i) r = LIGHT;
- else if (r_bit) r = BLACK;
- else if (i) r = MAXVAL;
- else r = DARK;
- g = b = r;
- } else {
+ if (r_bit && i) r = LIGHT;
+ else if (r_bit) r = BLACK;
+ else if (i) r = MAXVAL;
+ else r = DARK;
+ g = b = r;
+ } else {
/* It's one of the twelve colored colors */
if (!i) {
/* Low intensity */
- r = r_bit * LIGHT;
+ r = r_bit * LIGHT;
g = g_bit * LIGHT;
b = b_bit * LIGHT;
} else {
@@ -237,21 +238,21 @@ main(argc, argv)
}
}
PPM_ASSIGN(xelrow[col], r, g, b);
- }
- } else {
+ }
+ } else {
int col;
- for (col = 0; col < cols; col++)
+ for (col = 0; col < cols; col++)
PNM_ASSIGN1(xelrow[col], bitrow[0][col]);
}
- while (linerep--) {
- pnm_writepnmrow( stdout, xelrow, cols, MAXVAL, type, 0 );
- ++row;
- }
- }
+ while (linerep--) {
+ pnm_writepnmrow( stdout, xelrow, cols, MAXVAL, type, 0 );
+ ++row;
+ }
+ }
pnm_freerow(xelrow);
- pm_close( f );
- pm_close( stdout );
- exit(0);
+ pm_close( f );
+ pm_close( stdout );
+ exit(0);
}
@@ -303,5 +304,3 @@ getinit (file, colsP, rowsP, padrightP, patlenP, planesP)
}
}
-
-
diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c
index 98552c0..311298c 100644
--- a/converter/other/jpegtopnm.c
+++ b/converter/other/jpegtopnm.c
@@ -862,6 +862,8 @@ convertImage(FILE * const ofP,
/* Calculate output image dimensions so we can allocate space */
jpeg_calc_output_dimensions(cinfoP);
+ overflow2(cinfoP->output_width, cinfoP->output_components);
+
/* Start decompressor */
jpeg_start_decompress(cinfoP);
diff --git a/converter/other/pbmtopgm.c b/converter/other/pbmtopgm.c
index 817fb5b..8baaa57 100644
--- a/converter/other/pbmtopgm.c
+++ b/converter/other/pbmtopgm.c
@@ -60,6 +60,7 @@ main(int argc, char *argv[]) {
outrow = pgm_allocrow(cols) ;
+ overflow2(width, height);
maxval = MIN(PGM_OVERALLMAXVAL, width*height);
pgm_writepgminit(stdout, cols, rows, maxval, 0) ;
diff --git a/converter/other/pnmtoddif.c b/converter/other/pnmtoddif.c
index b7b942b..52be0e4 100644
--- a/converter/other/pnmtoddif.c
+++ b/converter/other/pnmtoddif.c
@@ -629,6 +629,7 @@ main(int argc, char *argv[]) {
switch (PNM_FORMAT_TYPE(format)) {
case PBM_TYPE:
ip.bits_per_pixel = 1;
+ overflow_add(cols, 7);
ip.bytes_per_line = (cols + 7) / 8;
ip.spectral = 2;
ip.components = 1;
@@ -644,6 +645,7 @@ main(int argc, char *argv[]) {
ip.polarity = 2;
break;
case PPM_TYPE:
+ overflow2(cols, 3);
ip.bytes_per_line = 3 * cols;
ip.bits_per_pixel = 24;
ip.spectral = 5;
diff --git a/converter/other/pnmtojpeg.c b/converter/other/pnmtojpeg.c
index e345831..757d08d 100644
--- a/converter/other/pnmtojpeg.c
+++ b/converter/other/pnmtojpeg.c
@@ -9,7 +9,7 @@
This program is by Bryan Henderson on 2000.03.06, but is derived
with permission from the program cjpeg, which is in the Independent
Jpeg Group's JPEG library package. Under the terms of that permission,
- redistribution of this software is restricted as described in the
+ redistribution of this software is restricted as described in the
file README.JPEG.
Copyright (C) 1991-1998, Thomas G. Lane.
@@ -84,12 +84,12 @@ struct cmdlineInfo {
struct density density;
};
-static void
-interpret_maxmemory (const char * const maxmemory,
- long int * const max_memory_to_use_p) {
+static void
+interpret_maxmemory (const char * const maxmemory,
+ long int * const max_memory_to_use_p) {
long int lval;
char ch;
-
+
if (maxmemory == NULL) {
*max_memory_to_use_p = -1; /* unspecified */
} else if (sscanf(maxmemory, "%ld%c", &lval, &ch) < 1) {
@@ -119,9 +119,9 @@ interpret_restart(const char * const restart,
long lval;
char ch;
unsigned int matches;
-
+
matches= sscanf(restart, "%ld%c", &lval, &ch);
- if (matches == 0)
+ if (matches == 0)
pm_error("Invalid value for the --restart option : '%s'.",
restart);
else {
@@ -160,7 +160,7 @@ interpret_density(const char * const densityString,
int horiz, vert;
unitName = malloc(strlen(densityString)+1);
-
+
matched = sscanf(densityString, "%dx%d%s", &horiz, &vert, unitName);
if (matched < 2)
@@ -178,7 +178,7 @@ interpret_density(const char * const densityString,
densityP->horiz = horiz;
densityP->vert = vert;
- if (matched < 3)
+ if (matched < 3)
densityP->unit = DEN_UNSPECIFIED;
else {
if (streq(unitName, "dpi") || streq(unitName, "DPI"))
@@ -235,7 +235,7 @@ parseCommandLine(const int argc, char ** argv,
option_def_index = 0; /* incremented by OPTENTRY */
OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
- OPTENT3(0, "quality", OPT_UINT, &cmdlineP->quality,
+ OPTENT3(0, "quality", OPT_UINT, &cmdlineP->quality,
&qualitySpec, 0);
OPTENT3(0, "baseline", OPT_FLAG, NULL, &cmdlineP->force_baseline, 0);
OPTENT3(0, "progressive", OPT_FLAG, NULL, &cmdlineP->progressive, 0);
@@ -250,14 +250,14 @@ parseCommandLine(const int argc, char ** argv,
OPTENT3(0, "qtables", OPT_STRING, &cmdlineP->qtablefile, NULL, 0);
OPTENT3(0, "sample", OPT_STRING, &cmdlineP->sample, NULL, 0);
OPTENT3(0, "scans", OPT_STRING, &cmdlineP->scans, NULL, 0);
- OPTENT3(0, "smooth", OPT_UINT, &cmdlineP->smoothing_factor,
+ OPTENT3(0, "smooth", OPT_UINT, &cmdlineP->smoothing_factor,
&smoothSpec, 0);
OPTENT3(0, "optimize", OPT_FLAG, NULL, &cmdlineP->optimize, 0);
OPTENT3(0, "optimise", OPT_FLAG, NULL, &cmdlineP->optimize, 0);
OPTENT3(0, "restart", OPT_STRING, &restart, NULL, 0);
OPTENT3(0, "comment", OPT_STRING, &cmdlineP->comment, NULL, 0);
OPTENT3(0, "exif", OPT_STRING, &cmdlineP->exif_filespec, NULL, 0);
- OPTENT3(0, "density", OPT_STRING, &density,
+ OPTENT3(0, "density", OPT_STRING, &density,
&cmdlineP->density_spec, 0);
/* Set the defaults */
@@ -295,7 +295,7 @@ parseCommandLine(const int argc, char ** argv,
cmdlineP->input_filespec = strdup("-"); /* he wants stdin */
else if (argc_parse - 1 == 1)
cmdlineP->input_filespec = strdup(argv_parse[1]);
- else
+ else
pm_error("Too many arguments. The only argument accepted "
"is the input file specification.");
if (dctval == NULL)
@@ -314,15 +314,15 @@ parseCommandLine(const int argc, char ** argv,
interpret_maxmemory(maxmemory, &cmdlineP->max_memory_to_use);
interpret_restart(restart, &cmdlineP->restart_value,
&cmdlineP->restart_unit);
- if (cmdlineP->density_spec)
+ if (cmdlineP->density_spec)
interpret_density(density, &cmdlineP->density);
-
+
if (cmdlineP->smoothing_factor > 100)
pm_error("Smoothing factor %d is greater than 100 (%%).",
cmdlineP->smoothing_factor);
if (streq(cmdlineP->input_filespec, "=") &&
- cmdlineP->exif_filespec &&
+ cmdlineP->exif_filespec &&
streq(cmdlineP->exif_filespec, "-"))
pm_error("Cannot have both input image and exif header be from "
@@ -336,7 +336,7 @@ parseCommandLine(const int argc, char ** argv,
static void
report_compressor(const struct jpeg_compress_struct cinfo) {
-
+
if (cinfo.scan_info == NULL)
pm_message("No scan script is being used");
else {
@@ -346,7 +346,7 @@ report_compressor(const struct jpeg_compress_struct cinfo) {
for (i = 0; i < cinfo.num_scans; i++) {
int j;
pm_message(" Scan %2d: Ss=%2d Se=%2d Ah=%2d Al=%2d "
- "%d components",
+ "%d components",
i,
cinfo.scan_info[i].Ss,
cinfo.scan_info[i].Se,
@@ -364,11 +364,11 @@ report_compressor(const struct jpeg_compress_struct cinfo) {
static void
-setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
- int const width, int const height,
+setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
+ int const width, int const height,
int const format) {
/*----------------------------------------------------------------------------
- Set up in the compressor descriptor *cinfoP the description of the
+ Set up in the compressor descriptor *cinfoP the description of the
source image as required by the compressor.
-----------------------------------------------------------------------------*/
@@ -379,7 +379,7 @@ setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
cinfoP->input_components = 1;
break;
case PPM_TYPE:
- cinfoP->in_color_space = JCS_RGB;
+ cinfoP->in_color_space = JCS_RGB;
cinfoP->input_components = 3;
break;
default:
@@ -391,7 +391,7 @@ setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
static void
-setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
+setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
struct density const density) {
/*----------------------------------------------------------------------------
Set up in the compressor descriptor *cinfoP the density information
@@ -402,7 +402,7 @@ setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
case DEN_DOTS_PER_INCH: cinfoP->density_unit = 1; break;
case DEN_DOTS_PER_CM: cinfoP->density_unit = 2; break;
}
-
+
cinfoP->X_density = density.horiz;
cinfoP->Y_density = density.vert;
}
@@ -411,7 +411,7 @@ setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
/*----------------------------------------------------------------------------
The functions below here are essentially the file rdswitch.c from
- the JPEG library. They perform the functions specified by the following
+ the JPEG library. They perform the functions specifed by the following
pnmtojpeg options:
-qtables file Read quantization tables from text file
@@ -426,7 +426,7 @@ text_getc (FILE * file)
/* A comment/newline sequence is returned as a newline */
{
register int ch;
-
+
ch = getc(file);
if (ch == '#') {
do {
@@ -454,12 +454,12 @@ readTextInteger(FILE * const fileP,
-----------------------------------------------------------------------------*/
int ch;
boolean retval;
-
+
/* Skip any leading whitespace, detect EOF */
do {
ch = text_getc(fileP);
} while (isspace(ch));
-
+
if (!isdigit(ch))
retval = FALSE;
else {
@@ -554,7 +554,7 @@ read_scan_script(j_compress_ptr const cinfo,
ncomps = 1;
while (termchar == ' ') {
if (ncomps >= MAX_COMPS_IN_SCAN) {
- pm_message("Too many components in one scan in file %s",
+ pm_message("Too many components in one scan in file %s",
filename);
fclose(fp);
return FALSE;
@@ -603,10 +603,14 @@ read_scan_script(j_compress_ptr const cinfo,
/* Stash completed scan list in cinfo structure. NOTE: in
this program, JPOOL_IMAGE is the right lifetime for this
data, but if you want to compress multiple images you'd
- want JPOOL_PERMANENT.
+ want JPOOL_PERMANENT.
*/
const unsigned int scan_info_size = nscans * sizeof(jpeg_scan_info);
- jpeg_scan_info * const scan_info =
+ const jpeg_scan_info * scan_info;
+
+ overflow2(nscans, sizeof(jpeg_scan_info));
+
+ scan_info =
(jpeg_scan_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
scan_info_size);
@@ -656,7 +660,7 @@ read_quant_tables (j_compress_ptr cinfo, char * filename,
if (tblno >= NUM_QUANT_TBLS) {
pm_message("Too many tables in file %s", filename);
error = TRUE;
- } else {
+ } else {
unsigned int table[DCTSIZE2];
unsigned int i;
@@ -686,7 +690,7 @@ read_quant_tables (j_compress_ptr cinfo, char * filename,
fclose(fp);
retval = !error;
}
-
+
return retval;
}
@@ -717,7 +721,7 @@ set_quant_slots (j_compress_ptr cinfo, char *arg)
return FALSE;
}
cinfo->comp_info[ci].quant_tbl_no = val;
- while (*arg && *arg++ != ',')
+ while (*arg && *arg++ != ',')
/* advance to next segment of arg string */
;
} else {
@@ -747,7 +751,7 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
return FALSE;
if (val1 <= 0 || val1 > 4) {
- pm_message("Invalid sampling factor: %d. "
+ pm_message("Invalid sampling factor: %d. "
"JPEG sampling factors must be 1..4", val1);
return FALSE;
}
@@ -758,11 +762,11 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
}
cinfo->comp_info[ci].h_samp_factor = val1;
cinfo->comp_info[ci].v_samp_factor = val2;
- while (*arg && *arg++ != ',')
+ while (*arg && *arg++ != ',')
/* advance to next segment of arg string */
;
} else {
- /* reached end of parameter, set remaining components
+ /* reached end of parameter, set remaining components
to 1x1 sampling */
cinfo->comp_info[ci].h_samp_factor = 1;
cinfo->comp_info[ci].v_samp_factor = 1;
@@ -776,13 +780,13 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
static void
setup_jpeg(struct jpeg_compress_struct * const cinfoP,
struct jpeg_error_mgr * const jerrP,
- struct cmdlineInfo const cmdline,
+ struct cmdlineInfo const cmdline,
int const width,
int const height,
pixval const maxval,
int const input_fmt,
FILE * const output_file) {
-
+
int quality;
int q_scale_factor;
@@ -794,14 +798,14 @@ setup_jpeg(struct jpeg_compress_struct * const cinfoP,
jpeg_set_defaults(cinfoP);
- cinfoP->data_precision = BITS_IN_JSAMPLE;
+ cinfoP->data_precision = BITS_IN_JSAMPLE;
/* we always rescale data to this */
cinfoP->image_width = (unsigned int) width;
cinfoP->image_height = (unsigned int) height;
cinfoP->arith_code = cmdline.arith_code;
cinfoP->dct_method = cmdline.dct_method;
- if (cmdline.trace_level == 0 && cmdline.verbose)
+ if (cmdline.trace_level == 0 && cmdline.verbose)
cinfoP->err->trace_level = 1;
else cinfoP->err->trace_level = cmdline.trace_level;
if (cmdline.grayscale)
@@ -822,26 +826,26 @@ setup_jpeg(struct jpeg_compress_struct * const cinfoP,
quality = cmdline.quality;
q_scale_factor = jpeg_quality_scaling(cmdline.quality);
}
- if (cmdline.smoothing_factor != -1)
+ if (cmdline.smoothing_factor != -1)
cinfoP->smoothing_factor = cmdline.smoothing_factor;
/* Set quantization tables for selected quality. */
/* Some or all may be overridden if user specified --qtables. */
jpeg_set_quality(cinfoP, quality, cmdline.force_baseline);
-
+
if (cmdline.qtablefile != NULL) {
if (! read_quant_tables(cinfoP, cmdline.qtablefile,
- q_scale_factor, cmdline.force_baseline))
+ q_scale_factor, cmdline.force_baseline))
pm_error("Can't use quantization table file '%s'.",
cmdline.qtablefile);
}
-
+
if (cmdline.qslots != NULL) {
if (! set_quant_slots(cinfoP, cmdline.qslots))
- pm_error("Bad quantization-table-selectors parameter string '%s'.",
+ pm_error("Bad quantization-table-selectors parameter string '%s'.",
cmdline.qslots);
}
-
+
if (cmdline.sample != NULL) {
if (! set_sample_factors(cinfoP, cmdline.sample))
pm_error("Bad sample-factors parameters string '%s'.",
@@ -878,7 +882,7 @@ write_exif_header(struct jpeg_compress_struct * const cinfoP,
/*----------------------------------------------------------------------------
Generate an APP1 marker in the JFIF output that is an Exif header.
- The contents of the Exif header are in the file with filespec
+ The contents of the Exif header are in the file with filespec
'exif_filespec' (file spec and contents are not validated).
exif_filespec = "-" means Standard Input.
@@ -888,7 +892,7 @@ write_exif_header(struct jpeg_compress_struct * const cinfoP,
-----------------------------------------------------------------------------*/
FILE * exif_file;
unsigned short length;
-
+
exif_file = pm_openr(exif_filespec);
pm_readbigshort(exif_file, (short*)&length);
@@ -900,7 +904,7 @@ write_exif_header(struct jpeg_compress_struct * const cinfoP,
else {
unsigned char * exif_data;
size_t rc;
- size_t const data_length = length - 2;
+ size_t const data_length = length - 2;
/* Subtract 2 byte length field*/
assert(data_length > 0);
@@ -917,16 +921,16 @@ write_exif_header(struct jpeg_compress_struct * const cinfoP,
"%u bytes of data, read only %u",
(unsigned)data_length, (unsigned)rc);
- jpeg_write_marker(cinfoP, JPEG_APP0+1,
+ jpeg_write_marker(cinfoP, JPEG_APP0+1,
(const JOCTET *) exif_data, data_length);
free(exif_data);
}
-
+
pm_close(exif_file);
}
-
+
static void
compute_rescaling_array(JSAMPLE ** const rescale_p, const pixval maxval,
@@ -938,9 +942,11 @@ compute_rescaling_array(JSAMPLE ** const rescale_p, const pixval maxval,
const long half_maxval = maxval / 2;
long val;
+ overflow_add(maxval, 1);
+ overflow2(maxval+1, sizeof(JSAMPLE));
*rescale_p = (JSAMPLE *)
(cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_IMAGE,
- (size_t) (((long) maxval + 1L) *
+ (size_t) (((long) maxval + 1L) *
sizeof(JSAMPLE)));
for (val = 0; val <= maxval; val++) {
/* The multiplication here must be done in 32 bits to avoid overflow */
@@ -951,9 +957,9 @@ compute_rescaling_array(JSAMPLE ** const rescale_p, const pixval maxval,
static void
-translate_row(const pixel pnm_buffer[],
- JSAMPLE jpeg_buffer[],
- int const width,
+translate_row(const pixel pnm_buffer[],
+ JSAMPLE jpeg_buffer[],
+ int const width,
int const input_components,
const JSAMPLE translate[]) {
/*----------------------------------------------------------------------------
@@ -971,16 +977,16 @@ translate_row(const pixel pnm_buffer[],
switch (input_components) {
case 1:
- for (column = 0; column < width; column++)
+ for (column = 0; column < width; column++)
jpeg_buffer[column] = translate[(int)PNM_GET1(pnm_buffer[column])];
break;
case 3:
for (column = 0; column < width; column++) {
- jpeg_buffer[column*3+0] =
+ jpeg_buffer[column*3+0] =
translate[(int)PPM_GETR(pnm_buffer[column])];
- jpeg_buffer[column*3+1] =
+ jpeg_buffer[column*3+1] =
translate[(int)PPM_GETG(pnm_buffer[column])];
- jpeg_buffer[column*3+2] =
+ jpeg_buffer[column*3+2] =
translate[(int)PPM_GETB(pnm_buffer[column])];
}
break;
@@ -1000,44 +1006,45 @@ convert_scanlines(struct jpeg_compress_struct * const cinfo_p,
int const input_fmt,
JSAMPLE xlate_table[]){
/*----------------------------------------------------------------------------
- Read scan lines from the input file, which is already opened in the
- netpbm library sense and ready for reading, and write them to the
+ Read scan lines from the input file, which is already opened in the
+ netpbm library sense and ready for reading, and write them to the
output JPEG object. Translate the pnm sample values to JPEG sample
values through the thable xlate_table[].
-----------------------------------------------------------------------------*/
- xel * pnm_buffer;
+ xel * pnm_buffer;
/* contains the row of the input image currently being processed,
in pnm_readpnmrow format
*/
JSAMPARRAY buffer;
- /* Row 0 of this array contains the row of the output image currently
+ /* Row 0 of this array contains the row of the output image currently
being processed, in JPEG compressor input format. The array only
has that one row.
*/
/* Allocate the libpnm output and compressor input buffers */
+ overflow2(cinfo_p->image_width, cinfo_p->input_components);
buffer = (*cinfo_p->mem->alloc_sarray)
((j_common_ptr) cinfo_p, JPOOL_IMAGE,
- (unsigned int) cinfo_p->image_width * cinfo_p->input_components,
+ (unsigned int) cinfo_p->image_width * cinfo_p->input_components,
(unsigned int) 1);
-
+
pnm_buffer = pnm_allocrow(cinfo_p->image_width);
while (cinfo_p->next_scanline < cinfo_p->image_height) {
- if (cinfo_p->err->trace_level > 1)
+ if (cinfo_p->err->trace_level > 1)
pm_message("Converting Row %d...", cinfo_p->next_scanline);
- pnm_readpnmrow(input_file, pnm_buffer, cinfo_p->image_width,
+ pnm_readpnmrow(input_file, pnm_buffer, cinfo_p->image_width,
maxval, input_fmt);
- translate_row(pnm_buffer, buffer[0],
+ translate_row(pnm_buffer, buffer[0],
cinfo_p->image_width, cinfo_p->input_components,
xlate_table);
jpeg_write_scanlines(cinfo_p, buffer, 1);
- if (cinfo_p->err->trace_level > 1)
+ if (cinfo_p->err->trace_level > 1)
pm_message("Done.");
}
pnm_freerow(pnm_buffer);
- /* Don't worry about the compressor input buffer; it gets freed
+ /* Don't worry about the compressor input buffer; it gets freed
automatically
*/
}
@@ -1053,11 +1060,11 @@ main(int argc,
struct jpeg_error_mgr jerr;
FILE * input_file;
FILE * output_file;
- int height;
+ int height;
/* height of the input image in rows, as specified by its header */
- int width;
+ int width;
/* width of the input image in columns, as specified by its header */
- pixval maxval;
+ pixval maxval;
/* maximum value of an input pixel component, as specified by header */
int input_fmt;
/* The input format, as determined by its header. */
@@ -1081,7 +1088,7 @@ main(int argc,
if (cmdline.verbose) {
pm_message("Input file has format %c%c.\n"
"It has %d rows of %d columns of pixels "
- "with max sample value of %d.",
+ "with max sample value of %d.",
(char) (input_fmt/256), (char) (input_fmt % 256),
height, width, maxval);
}
@@ -1091,13 +1098,13 @@ main(int argc,
compute_rescaling_array(&rescale, maxval, cinfo);
- if (cmdline.comment)
- jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET *) cmdline.comment,
+ if (cmdline.comment)
+ jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET *) cmdline.comment,
strlen(cmdline.comment));
if (cmdline.exif_filespec)
write_exif_header(&cinfo, cmdline.exif_filespec);
-
+
/* Translate and copy over the actual scanlines */
convert_scanlines(&cinfo, input_file, maxval, input_fmt, rescale);
@@ -1110,10 +1117,7 @@ main(int argc,
pm_close(input_file);
/* Program may have exited with non-zero completion code via
- various function calls above.
+ various function calls above.
*/
return jerr.num_warnings > 0 ? EXIT_WARNING : EXIT_SUCCESS;
}
-
-
-
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c
index 45d856d..09c28d5 100644
--- a/converter/other/pnmtops.c
+++ b/converter/other/pnmtops.c
@@ -125,8 +125,8 @@ static bool verbose;
static void
-parseDpi(const char * const dpiOpt,
- unsigned int * const dpiXP,
+parseDpi(const char * const dpiOpt,
+ unsigned int * const dpiXP,
unsigned int * const dpiYP) {
char *dpistr2;
@@ -253,9 +253,9 @@ parseCommandLine(int argc, const char ** argv,
OPTENT3(0, "showpage", OPT_FLAG, NULL, &showpage, 0);
OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
OPTENT3(0, "debug", OPT_FLAG, NULL, &cmdlineP->debug, 0);
- OPTENT3(0, "level", OPT_UINT, &cmdlineP->level,
+ OPTENT3(0, "level", OPT_UINT, &cmdlineP->level,
&cmdlineP->levelSpec, 0);
-
+
opt.opt_table = option_def;
opt.short_allowed = FALSE;
opt.allowNegNum = FALSE;
@@ -293,18 +293,22 @@ parseCommandLine(int argc, const char ** argv,
validateCompDimension(width, 72, "-width value");
validateCompDimension(height, 72, "-height value");
-
+
+ overflow2(width, 72);
cmdlineP->width = width * 72;
+ overflow2(height, 72);
cmdlineP->height = height * 72;
if (imagewidthSpec) {
validateCompDimension(imagewidth, 72, "-imagewidth value");
+ overflow2(imagewidth, 72);
cmdlineP->imagewidth = imagewidth * 72;
}
else
cmdlineP->imagewidth = 0;
if (imageheightSpec) {
- validateCompDimension(imagewidth, 72, "-imageheight value");
+ validateCompDimension(imageheight, 72, "-imageheight value");
+ overflow2(imageheight, 72);
cmdlineP->imageheight = imageheight * 72;
}
else
@@ -318,7 +322,7 @@ parseCommandLine(int argc, const char ** argv,
if (cmdlineP->bitspersampleSpec)
validateBps_1_2_4_8_12(cmdlineP->bitspersample);
- if (argc-1 == 0)
+ if (argc-1 == 0)
cmdlineP->inputFileName = "-";
else if (argc-1 != 1)
pm_error("Program takes zero or one argument (filename). You "
@@ -326,7 +330,7 @@ parseCommandLine(int argc, const char ** argv,
else
cmdlineP->inputFileName = argv[1];
- free(option_def);
+ free(option_def);
}
@@ -432,7 +436,7 @@ addToPidList(pid_t * const pidList,
/*===========================================================================
The output encoder
===========================================================================*/
-
+
enum OutputType {AsciiHex, Ascii85};
typedef struct {
@@ -453,7 +457,7 @@ bytesPerRow (unsigned int const cols,
-----------------------------------------------------------------------------*/
unsigned int retval;
- assert(bitsPerSample==1 || bitsPerSample==2 || bitsPerSample==4 ||
+ assert(bitsPerSample==1 || bitsPerSample==2 || bitsPerSample==4 ||
bitsPerSample==8 || bitsPerSample==12);
switch (bitsPerSample) {
@@ -519,7 +523,7 @@ typedef void FilterFn(FILE * const ifP,
/* This is a function that can be run in a separate process to do
arbitrary modifications of the raster data stream.
*/
-
+
#ifndef NOFLATE
@@ -545,7 +549,7 @@ initZlib(z_stream * const strmP) {
static FilterFn flateFilter;
-static void
+static void
flateFilter(FILE * const ifP,
FILE * const ofP,
OutputEncoder * const oeP) {
@@ -600,12 +604,12 @@ flateFilter(FILE * const ifP,
} while (flush != Z_FINISH);
free(in);
- free(out);
+ free(out);
deflateEnd(&strm);
fclose(ifP);
fclose(ofP);
#else
- assert(false); /* filter is never used */
+ assert(false); /* filter is never used */
#endif
}
@@ -687,7 +691,7 @@ asciiHexFilter(FILE * const ifP,
unsigned int i;
for (i = 0; i < readCt; ++i) {
- int const item = inbuff[i];
+ int const item = inbuff[i];
outbuff[i*2] = hexits[item >> 4];
outbuff[i*2+1] = hexits[item & 15];
}
@@ -736,7 +740,7 @@ ascii85Filter(FILE * const ifP,
++outcount;
count = 0;
} else if (count == 4) {
- outbuff[4] = value % 85 + 33; value/=85;
+ outbuff[4] = value % 85 + 33; value/=85;
outbuff[3] = value % 85 + 33; value/=85;
outbuff[2] = value % 85 + 33; value/=85;
outbuff[1] = value % 85 + 33;
@@ -745,7 +749,7 @@ ascii85Filter(FILE * const ifP,
writeFileChar(outbuff, count + 1, "ASCII 85 filter", ofP);
count = value = 0;
- outcount += 5;
+ outcount += 5;
}
if (outcount > 75) {
@@ -794,9 +798,9 @@ closeAllBut(int const saveFd0,
'saveFd1', and 'saveFd2'.
This is helpful because even if this process doesn't touch other file
- descriptors, its very existence will keep the files open.
+ desriptors, its very existence will keep the files open.
-----------------------------------------------------------------------------*/
-
+
/* Unix provides no good way to do this; we just assume file descriptors
above 9 are not used in this program; Caller must ensure that is true.
*/
@@ -829,15 +833,15 @@ spawnFilter(FILE * const ofP,
pid_t rc;
makePipe(pipeFd);
-
+
rc = fork();
if (rc == (pid_t)-1)
- pm_error("fork() of filter process failed. errno=%d (%s)",
+ pm_error("fork() of filter process failed. errno=%d (%s)",
errno, strerror(errno));
else if (rc == 0) {
/* This is the child process */
-
+
FILE * ifP;
ifP = fdopen(pipeFd[0], "r");
@@ -892,11 +896,11 @@ addFilter(const char * const description,
pid_t pid;
spawnFilter(oldFeedFileP, filter, oeP, &newFeedFileP, &pid);
-
+
if (verbose)
pm_message("%s filter spawned: pid %u",
description, (unsigned)pid);
-
+
if (debug) {
int const outFd = fileno(oldFeedFileP);
int const supplyFd = fileno(newFeedFileP);
@@ -971,7 +975,7 @@ waitForChildren(const pid_t * const pidList) {
signal is the default), the process' children do not become
zombies. Consequently, waitpid() always fails with ECHILD - but
nonetheless waits for the child to exit.
-
+
We expect the process not to have the action for SIGCHLD set that
way.
*/
@@ -1004,9 +1008,9 @@ waitForChildren(const pid_t * const pidList) {
static void
-validateComputableBoundingBox(float const scols,
+validateComputableBoundingBox(float const scols,
float const srows,
- float const llx,
+ float const llx,
float const lly) {
float const bbWidth = llx + scols + 0.5;
@@ -1036,22 +1040,22 @@ warnUserRescaling(float const scale) {
static void
-computeImagePosition(int const dpiX,
- int const dpiY,
- int const icols,
+computeImagePosition(int const dpiX,
+ int const dpiY,
+ int const icols,
int const irows,
bool const mustturn,
bool const canturn,
bool const center,
- int const pagewid,
- int const pagehgt,
+ int const pagewid,
+ int const pagehgt,
float const requestedScale,
float const imagewidth,
float const imageheight,
bool const equalpixels,
float * const scolsP,
float * const srowsP,
- float * const llxP,
+ float * const llxP,
float * const llyP,
bool * const turnedP ) {
/*----------------------------------------------------------------------------
@@ -1091,7 +1095,7 @@ computeImagePosition(int const dpiX,
rotated if applicable
*/
bool shouldturn; /* The image fits the page better if we turn it */
-
+
if (icols > irows && pagehgt > pagewid)
shouldturn = TRUE;
else if (irows > icols && pagewid > pagehgt)
@@ -1120,27 +1124,27 @@ computeImagePosition(int const dpiX,
scale = (float) imagewidth/cols;
else
scale = MIN((float)imagewidth/cols, (float)imageheight/rows);
-
+
*scolsP = cols*scale;
*srowsP = rows*scale;
} else {
/* He didn't give us a bounding box for the image so figure
out output image size from other inputs.
*/
- const int devpixX = dpiX / 72.0 + 0.5;
- const int devpixY = dpiY / 72.0 + 0.5;
+ const int devpixX = dpiX / 72.0 + 0.5;
+ const int devpixY = dpiY / 72.0 + 0.5;
/* How many device pixels make up 1/72 inch, rounded to
nearest integer */
const float pixfacX = 72.0 / dpiX * devpixX; /* 1, approx. */
const float pixfacY = 72.0 / dpiY * devpixY; /* 1, approx. */
float scale;
- scale = MIN(requestedScale,
+ scale = MIN(requestedScale,
MIN((float)pagewid/cols, (float)pagehgt/rows));
*scolsP = scale * cols * pixfacX;
*srowsP = scale * rows * pixfacY;
-
+
if (scale != requestedScale)
warnUserRescaling(scale);
@@ -1236,7 +1240,7 @@ defineReadstring(bool const rle) {
static void
setupReadstringNative(bool const rle,
bool const color,
- unsigned int const icols,
+ unsigned int const icols,
unsigned int const bitsPerSample) {
/*----------------------------------------------------------------------------
Write to Standard Output statements to define /readstring and also
@@ -1247,7 +1251,7 @@ setupReadstringNative(bool const rle,
/* Size of row buffer, padded up to byte boundary. */
defineReadstring(rle);
-
+
if (color) {
printf("/rpicstr %d string def\n", bytesPerRow);
printf("/gpicstr %d string def\n", bytesPerRow);
@@ -1266,18 +1270,18 @@ putFilters(unsigned int const postscriptLevel,
bool const color) {
assert(postscriptLevel > 1);
-
+
/* We say to decode flate, then rle, so Caller must ensure it encodes
rel, then flate.
*/
if (ascii85)
printf("/ASCII85Decode filter ");
- else
+ else
printf("/ASCIIHexDecode filter ");
if (flate)
printf("/FlateDecode filter ");
- if (rle)
+ if (rle)
printf("/RunLengthDecode filter ");
}
@@ -1311,7 +1315,7 @@ putSetup(unsigned int const dictSize,
if (dictSize > 0)
/* inputf {r,g,b,}pictsr readstring readrlestring rlestring */
printf("%u dict begin\n", dictSize);
-
+
if (!psFilter)
setupReadstringNative(rle, color, icols, bitsPerSample);
@@ -1353,7 +1357,7 @@ putInitPsFilter(unsigned int const postscriptLevel,
putFilters(postscriptLevel, rle, flate, ascii85, color);
putImage(filterTrue, color);
-
+
printf(" } exec");
}
@@ -1365,7 +1369,7 @@ putInitReadstringNative(bool const color) {
bool const filterFalse = FALSE;
putReadstringNative(color);
-
+
putImage(filterFalse, color);
}
@@ -1373,18 +1377,18 @@ putInitReadstringNative(bool const color) {
static void
putInit(unsigned int const postscriptLevel,
- char const name[],
- int const icols,
- int const irows,
- float const scols,
+ char const name[],
+ int const icols,
+ int const irows,
+ float const scols,
float const srows,
- float const llx,
+ float const llx,
float const lly,
int const bitsPerSample,
- int const pagewid,
+ int const pagewid,
int const pagehgt,
- bool const color,
- bool const turned,
+ bool const color,
+ bool const turned,
bool const rle,
bool const flate,
bool const ascii85,
@@ -1438,7 +1442,7 @@ putInit(unsigned int const postscriptLevel,
static void
-putEnd(bool const showpage,
+putEnd(bool const showpage,
bool const psFilter,
bool const ascii85,
unsigned int const dictSize,
@@ -1486,7 +1490,7 @@ validateBpsRequest(unsigned int const bitsPerSampleReq,
"-psfilter, the maximum is 8", bitsPerSampleReq);
}
-
+
static unsigned int
bpsFromInput(unsigned int const bitsRequiredByMaxval,
@@ -1553,7 +1557,7 @@ warnUserAboutReducedDepth(unsigned int const bitsGot,
static void
computeDepth(xelval const inputMaxval,
- unsigned int const postscriptLevel,
+ unsigned int const postscriptLevel,
bool const psFilter,
unsigned int const bitsPerSampleReq,
unsigned int * const bitsPerSampleP) {
@@ -1584,7 +1588,7 @@ computeDepth(xelval const inputMaxval,
"%u bits per sample, so maxval = %u",
inputMaxval, *bitsPerSampleP, psMaxval);
}
-}
+}
@@ -1643,7 +1647,7 @@ ba_add(BitAccumulator * const baP,
/*----------------------------------------------------------------------------
Combine bit sequences that do not fit into a byte.
- Used when bitsPerSample =1, 2, 4.
+ Used when bitsPerSample =1, 2, 4.
Logic also works for bitsPerSample = 8, 16.
The accumulator, baP->value is unsigned int (usually 32 bits), but
@@ -1725,7 +1729,7 @@ flushOutput(BitAccumulator * const baP,
convertRowNative and convertRowPsFilter are the general converters.
They are quite similar, the differences being:
- (1) Native output separates the color planes:
+ (1) Native output separates the color planes:
(RRR...RRR GGG...GGG BBB...BBB),
whereas psFilter does not:
(RGB RGB RGB RGB ......... RGB).
@@ -1765,10 +1769,10 @@ convertRowPbm(struct pam * const pamP,
static void
-convertRowNative(struct pam * const pamP,
- tuple * tuplerow,
+convertRowNative(struct pam * const pamP,
+ tuple * tuplerow,
unsigned int const bitsPerSample,
- FILE * const fP) {
+ FILE * const fP) {
unsigned int const psMaxval = pm_bitstomaxval(bitsPerSample);
@@ -1795,7 +1799,7 @@ static void
convertRowPsFilter(struct pam * const pamP,
tuple * tuplerow,
unsigned int const bitsPerSample,
- FILE * const fP) {
+ FILE * const fP) {
unsigned int const psMaxval = pm_bitstomaxval(bitsPerSample);
@@ -1828,7 +1832,7 @@ selectPostscriptLevel(bool const levelIsGiven,
bool const psFilter,
unsigned int * const postscriptLevelP) {
- unsigned int const maxPermittedLevel =
+ unsigned int const maxPermittedLevel =
levelIsGiven ? levelGiven : UINT_MAX;
unsigned int minPossibleLevel;
@@ -1877,7 +1881,7 @@ convertRaster(struct pam * const inpamP,
Read the raster described by *inpamP, and write a bit stream of samples
to *fP. This stream has to be compressed and converted to text before it
can be part of a Postscript program.
-
+
'psFilter' means to do the conversion using built in Postscript filters, as
opposed to our own filters via /readstring.
@@ -1897,7 +1901,7 @@ convertRaster(struct pam * const inpamP,
} else {
tuple *tuplerow;
unsigned int row;
-
+
tuplerow = pnm_allocpamrow(inpamP);
for (row = 0; row < inpamP->height; ++row) {
@@ -1920,31 +1924,31 @@ convertRaster(struct pam * const inpamP,
pipe but this program's output, then we don't want it closed when the
filter terminates because we'll need it to be open for the next image
the program converts (with a whole new chain of filters).
-
- To prevent the program output file from getting closed, we pass a
+
+ To prevent the progam output file from getting closed, we pass a
duplicate of it to spawnFilters() and keep the original open.
*/
static void
-convertPage(FILE * const ifP,
- int const turnflag,
- int const turnokflag,
+convertPage(FILE * const ifP,
+ int const turnflag,
+ int const turnokflag,
bool const psFilter,
- bool const rle,
+ bool const rle,
bool const flate,
bool const ascii85,
bool const setpage,
bool const showpage,
- bool const center,
+ bool const center,
float const scale,
- int const dpiX,
- int const dpiY,
- int const pagewid,
+ int const dpiX,
+ int const dpiY,
+ int const pagewid,
int const pagehgt,
- int const imagewidth,
- int const imageheight,
+ int const imagewidth,
+ int const imageheight,
bool const equalpixels,
unsigned int const bitsPerSampleReq,
char const name[],
@@ -1952,7 +1956,7 @@ convertPage(FILE * const ifP,
bool const vmreclaim,
bool const levelIsGiven,
unsigned int const levelGiven) {
-
+
struct pam inpam;
float scols, srows;
float llx, lly;
@@ -1960,7 +1964,7 @@ convertPage(FILE * const ifP,
bool color;
unsigned int postscriptLevel;
unsigned int bitsPerSample;
- unsigned int dictSize;
+ unsigned int dictSize;
/* Size of Postscript dictionary we should define */
OutputEncoder oe;
pid_t filterPidList[MAX_FILTER_CT + 1];
@@ -1974,19 +1978,19 @@ convertPage(FILE * const ifP,
pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
validateCompDimension(inpam.width, 16, "Input image width");
-
+
if (!STRSEQ(inpam.tuple_type, PAM_PBM_TUPLETYPE) &&
!STRSEQ(inpam.tuple_type, PAM_PGM_TUPLETYPE) &&
!STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE))
pm_error("Unrecognized tuple type %s. This program accepts only "
- "PBM, PGM, PPM, and equivalent PAM input images",
+ "PBM, PGM, PPM, and equivalent PAM input images",
inpam.tuple_type);
color = STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE);
-
- selectPostscriptLevel(levelIsGiven, levelGiven, color,
+
+ selectPostscriptLevel(levelIsGiven, levelGiven, color,
dict, flate, ascii85, psFilter, &postscriptLevel);
-
+
if (color)
pm_message("generating color Postscript program.");
@@ -1996,16 +2000,16 @@ convertPage(FILE * const ifP,
/* In positioning/scaling the image, we treat the input image as if
it has a density of 72 pixels per inch.
*/
- computeImagePosition(dpiX, dpiY, inpam.width, inpam.height,
+ computeImagePosition(dpiX, dpiY, inpam.width, inpam.height,
turnflag, turnokflag, center,
pagewid, pagehgt, scale, imagewidth, imageheight,
equalpixels,
&scols, &srows, &llx, &lly, &turned);
determineDictionaryRequirement(dict, psFilter, &dictSize);
-
- putInit(postscriptLevel, name, inpam.width, inpam.height,
- scols, srows, llx, lly, bitsPerSample,
+
+ putInit(postscriptLevel, name, inpam.width, inpam.height,
+ scols, srows, llx, lly, bitsPerSample,
pagewid, pagehgt, color,
turned, rle, flate, ascii85, setpage, psFilter, dictSize);
@@ -2017,7 +2021,7 @@ convertPage(FILE * const ifP,
/* spawnFilters() closes this. See FILE MANAGEMENT above */
spawnFilters(filterChainOfP, &oe, &feedFileP, filterPidList);
-
+
convertRaster(&inpam, bitsPerSample, psFilter, feedFileP);
fflush(feedFileP);
@@ -2081,17 +2085,17 @@ main(int argc, const char * argv[]) {
eof = FALSE; /* There is always at least one image */
for (imageSeq = 0; !eof; ++imageSeq) {
- convertPage(ifP, cmdline.mustturn, cmdline.canturn,
+ convertPage(ifP, cmdline.mustturn, cmdline.canturn,
cmdline.psfilter,
- cmdline.rle, cmdline.flate, cmdline.ascii85,
+ cmdline.rle, cmdline.flate, cmdline.ascii85,
cmdline.setpage, cmdline.showpage,
cmdline.center, cmdline.scale,
cmdline.dpiX, cmdline.dpiY,
- cmdline.width, cmdline.height,
- cmdline.imagewidth, cmdline.imageheight,
+ cmdline.width, cmdline.height,
+ cmdline.imagewidth, cmdline.imageheight,
cmdline.equalpixels,
cmdline.bitspersampleSpec ? cmdline.bitspersample : 0,
- name,
+ name,
cmdline.dict, cmdline.vmreclaim,
cmdline.levelSpec, cmdline.level);
pnm_nextimage(ifP, &eof);
@@ -2121,7 +2125,7 @@ main(int argc, const char * argv[]) {
** wrzl@gup.uni-linz.ac.at.
**
** July 2011 afu
-** row converters rewritten, fast PBM-only row converter added,
+** row convertors rewritten, fast PBM-only row convertor added,
** rle compression slightly modified, flate compression added
** ascii85 output end added.
**
diff --git a/converter/other/rletopnm.c b/converter/other/rletopnm.c
index 97f271d..72b63d3 100644
--- a/converter/other/rletopnm.c
+++ b/converter/other/rletopnm.c
@@ -19,6 +19,8 @@
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
+ *
+ * 2002-12-19: Fix maths wrapping bugs. Alan Cox <alan@redhat.com>
*/
/*
* rletopnm - A conversion program to convert from Utah's "rle" image format
diff --git a/converter/other/sirtopnm.c b/converter/other/sirtopnm.c
index fafcc91..9fe49d0 100644
--- a/converter/other/sirtopnm.c
+++ b/converter/other/sirtopnm.c
@@ -69,6 +69,7 @@ char* argv[];
}
break;
case PPM_TYPE:
+ overflow3(cols, rows, 3);
picsize = cols * rows * 3;
planesize = cols * rows;
if ( !( sirarray = (unsigned char*) malloc( picsize ) ) )
diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c
index 05493e7..26a5d7f 100644
--- a/converter/other/tifftopnm.c
+++ b/converter/other/tifftopnm.c
@@ -1372,7 +1372,9 @@ convertRasterByRows(pnmOut * const pnmOutP,
if (scanbuf == NULL)
pm_error("can't allocate memory for scanline buffer");
- MALLOCARRAY(samplebuf, cols * spp);
+ /* samplebuf is unsigned int * !!! */
+ samplebuf = (unsigned int *) malloc3(cols , sizeof(unsigned int) , spp);
+
if (samplebuf == NULL)
pm_error("can't allocate memory for row buffer");
diff --git a/converter/other/xwdtopnm.c b/converter/other/xwdtopnm.c
index a74da34..4d26a31 100644
--- a/converter/other/xwdtopnm.c
+++ b/converter/other/xwdtopnm.c
@@ -210,6 +210,10 @@ processX10Header(X10WDFileHeader * const h10P,
*colorsP = pnm_allocrow(2);
PNM_ASSIGN1((*colorsP)[0], 0);
PNM_ASSIGN1((*colorsP)[1], *maxvalP);
+ overflow_add(h10P->pixmap_width, 15);
+ if(h10P->pixmap_width < 0)
+ pm_error("assert: negative width");
+ overflow2((((h10P->pixmap_width + 15) / 16) * 16 - h10P->pixmap_width), 8);
*padrightP =
(((h10P->pixmap_width + 15) / 16) * 16 - h10P->pixmap_width) * 8;
*bits_per_itemP = 16;
@@ -635,6 +639,7 @@ processX11Header(X11WDFileHeader * const h11P,
*colsP = h11FixedP->pixmap_width;
*rowsP = h11FixedP->pixmap_height;
+ overflow2(h11FixedP->bytes_per_line, 8);
*padrightP =
h11FixedP->bytes_per_line * 8 -
h11FixedP->pixmap_width * h11FixedP->bits_per_pixel;
diff --git a/converter/pbm/mdatopbm.c b/converter/pbm/mdatopbm.c
index 461b3f8..c8bab6c 100644
--- a/converter/pbm/mdatopbm.c
+++ b/converter/pbm/mdatopbm.c
@@ -245,10 +245,13 @@ main(int argc, char **argv) {
pm_readlittleshort(infile, &yy); nInCols = yy;
}
+ overflow2(nOutCols, 8);
nOutCols = 8 * nInCols;
nOutRows = nInRows;
- if (bScale)
+ if (bScale) {
+ overflow2(nOutRows, 2);
nOutRows *= 2;
+ }
data = pbm_allocarray(nOutCols, nOutRows);
diff --git a/converter/pbm/mgrtopbm.c b/converter/pbm/mgrtopbm.c
index 9f7004a..60e8477 100644
--- a/converter/pbm/mgrtopbm.c
+++ b/converter/pbm/mgrtopbm.c
@@ -65,6 +65,8 @@ readMgrHeader(FILE * const ifP,
if (head.h_high < ' ' || head.l_high < ' ')
pm_error("Invalid width field in MGR header");
+ overflow_add(*colsP, pad);
+
*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;
diff --git a/converter/pbm/pbmto4425.c b/converter/pbm/pbmto4425.c
index 1d97ac6..c4c8cbb 100644
--- a/converter/pbm/pbmto4425.c
+++ b/converter/pbm/pbmto4425.c
@@ -2,6 +2,7 @@
#include "nstring.h"
#include "pbm.h"
+#include <string.h>
static char bit_table[2][3] = {
{1, 4, 0x10},
@@ -160,7 +161,7 @@ main(int argc, char * argv[]) {
xres = vmap_width * 2;
yres = vmap_height * 3;
- vmap = malloc(vmap_width * vmap_height * sizeof(char));
+ vmap = malloc3(vmap_width, vmap_height, sizeof(char));
if(vmap == NULL)
{
pm_error( "Cannot allocate memory" );
diff --git a/converter/pbm/pbmtogem.c b/converter/pbm/pbmtogem.c
index 4fd30e9..c82757d 100644
--- a/converter/pbm/pbmtogem.c
+++ b/converter/pbm/pbmtogem.c
@@ -79,6 +79,7 @@ putinit (int const rows, int const cols)
bitsperitem = 0;
bitshift = 7;
outcol = 0;
+ overflow_add(cols, 7);
outmax = (cols + 7) / 8;
outrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
lastrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
diff --git a/converter/pbm/pbmtogo.c b/converter/pbm/pbmtogo.c
index 4f84f39..943dc84 100644
--- a/converter/pbm/pbmtogo.c
+++ b/converter/pbm/pbmtogo.c
@@ -158,6 +158,7 @@ main(int argc,
bitrow = pbm_allocrow(cols);
/* Round cols up to the nearest multiple of 8. */
+ overflow_add(cols, 7);
rucols = ( cols + 7 ) / 8;
bytesperrow = rucols; /* GraphOn uses bytes */
rucols = rucols * 8;
diff --git a/converter/pbm/pbmtolj.c b/converter/pbm/pbmtolj.c
index 3cd7670..0b51932 100644
--- a/converter/pbm/pbmtolj.c
+++ b/converter/pbm/pbmtolj.c
@@ -120,7 +120,11 @@ parseCommandLine(int argc, char ** argv,
static void
allocateBuffers(unsigned int const cols) {
+ overflow_add(cols, 8);
rowBufferSize = (cols + 7) / 8;
+ overflow_add(rowBufferSize, 128);
+ overflow_add(rowBufferSize, rowBufferSize+128);
+ overflow_add(rowBufferSize+10, rowBufferSize/8);
packBufferSize = rowBufferSize + (rowBufferSize + 127) / 128 + 1;
deltaBufferSize = rowBufferSize + rowBufferSize / 8 + 10;
diff --git a/converter/pbm/pbmtomda.c b/converter/pbm/pbmtomda.c
index 3ad5149..9efe5cf 100644
--- a/converter/pbm/pbmtomda.c
+++ b/converter/pbm/pbmtomda.c
@@ -179,6 +179,7 @@ int main(int argc, char **argv)
nOutRowsUnrounded = bScale ? nInRows/2 : nInRows;
+ overflow_add(nOutRowsUnrounded, 3);
nOutRows = ((nOutRowsUnrounded + 3) / 4) * 4;
/* MDA wants rows a multiple of 4 */
nOutCols = nInCols / 8;
diff --git a/converter/pbm/pbmtoppa/pbm.c b/converter/pbm/pbmtoppa/pbm.c
index ae36e0d..1c8d236 100644
--- a/converter/pbm/pbmtoppa/pbm.c
+++ b/converter/pbm/pbmtoppa/pbm.c
@@ -11,185 +11,128 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
-#include "pm.h"
-#include "nstring.h"
#include "ppapbm.h"
-int
-make_pbm_stat(pbm_stat * const pbmStatP,
- FILE * const ifP) {
-
- char line[1024];
- char * rc;
- int retval;
-
- pbmStatP->fptr = ifP;
- pbmStatP->version = none;
- pbmStatP->current_line = 0;
- pbmStatP->unread = 0;
-
- rc = fgets(line, 1024, ifP);
- if (rc == NULL)
- retval = 0;
- else {
- line[strlen(line)-1] = 0;
-
- if (streq(line,"P1"))
- pbmStatP->version=P1;
- if (streq(line,"P4"))
- pbmStatP->version=P4;
-
- if (pbmStatP->version == none) {
- pm_message("unknown PBM magic '%s'", line);
- retval = 0;
- } else {
- do {
- char * rc;
- rc = fgets(line, 1024, ifP);
- if (rc == NULL)
- return 0;
- } while (line[0] == '#');
- {
- int rc;
- rc = sscanf(line, "%d %d",
- &pbmStatP->width, &pbmStatP->height);
- if (rc != 2)
- retval = 0;
- else {
- if (pbmStatP->width < 0) {
- pm_message("Image has negative width");
- retval = 0;
- } else if (pbmStatP->width > INT_MAX/2) {
- pm_message("Uncomputeably large width: %d",
- pbmStatP->width);
- retval = 0;
- } else if (pbmStatP->height < 0) {
- pm_message("Image has negative height");
- retval = 0;
- } else if (pbmStatP->height > INT_MAX/2) {
- pm_message("Uncomputeably large height: %d",
- pbmStatP->height);
- retval = 0;
- } else
- retval = 1;
- }
- }
- }
- }
- return retval;
-}
+int make_pbm_stat(pbm_stat* pbm,FILE* fptr)
+{
+ char line[1024];
+ pbm->fptr=fptr;
+ pbm->version=none;
+ pbm->current_line=0;
+ pbm->unread = 0;
+ if (fgets (line, 1024, fptr) == NULL)
+ return 0;
+ line[strlen(line)-1] = 0;
-static int
-getbytes(FILE * const ifP,
- unsigned int const width,
- unsigned char * const data) {
-
- unsigned char mask;
- unsigned char acc;
- unsigned char * place;
- unsigned int num;
- int retval;
-
- if (width == 0)
- retval = 0;
- else {
- for (mask = 0x80, acc = 0, num = 0, place = data; num < width; ) {
- switch (getc(ifP)) {
- case EOF:
- return 0;
- case '1':
- acc |= mask;
- /* fall through */
- case '0':
- mask >>= 1;
- ++num;
- if (mask == 0x00) { /* if (num % 8 == 0) */
- *place++ = acc;
- acc = 0;
- mask = 0x80;
- }
- }
- }
- if (width % 8 != 0)
- *place = acc;
-
- retval = 1;
- }
- return retval;
-}
+ if(!strcmp(line,"P1")) pbm->version=P1;
+ if(!strcmp(line,"P4")) pbm->version=P4;
+ if(pbm->version == none)
+ {
+ fprintf(stderr,"pbm_readheader(): unknown PBM magic '%s'\n",line);
+ return 0;
+ }
+ do
+ if (fgets (line, 1024, fptr) == NULL)
+ return 0;
+ while (line[0] == '#');
+ if (2 != sscanf (line, "%d %d", &pbm->width, &pbm->height))
+ return 0;
-int
-pbm_readline(pbm_stat * const pbmStatP,
- unsigned char * const data) {
-/*----------------------------------------------------------------------------
- Read a single line into data which must be at least (pbmStatP->width+7)/8
- bytes of storage.
------------------------------------------------------------------------------*/
- int retval;
-
- if (pbmStatP->current_line >= pbmStatP->height)
- retval = 0;
- else {
- if (pbmStatP->unread) {
- memcpy(data, pbmStatP->revdata, (pbmStatP->width+7)/8);
- ++pbmStatP->current_line;
- pbmStatP->unread = 0;
- free(pbmStatP->revdata);
- pbmStatP->revdata = NULL;
- retval = 1;
- } else {
- switch (pbmStatP->version) {
- case P1:
- if (getbytes(pbmStatP->fptr, pbmStatP->width, data)) {
- pbmStatP->current_line++;
- retval = 1;
- } else
- retval = 0;
- break;
- case P4: {
- int tmp, tmp2;
- tmp = (pbmStatP->width+7)/8;
- tmp2 = fread(data,1,tmp,pbmStatP->fptr);
- if (tmp2 == tmp) {
- ++pbmStatP->current_line;
- retval = 1;
- } else {
- pm_message("error reading line data (%d)", tmp2);
- retval = 0;
- }
- } break;
-
- default:
- pm_message("unknown PBM version");
- retval = 0;
- }
- }
- }
- return retval;
+ return 1;
}
+static int getbytes(FILE *fptr,int width,unsigned char* data)
+{
+ unsigned char mask,acc,*place;
+ int num;
+
+ if(!width) return 0;
+ for(mask=0x80, acc=0, num=0, place=data; num<width; )
+ {
+ switch(getc(fptr))
+ {
+ case EOF:
+ return 0;
+ case '1':
+ acc|=mask;
+ /* fall through */
+ case '0':
+ mask>>=1;
+ num++;
+ if(!mask) /* if(num%8 == 0) */
+ {
+ *place++ = acc;
+ acc=0;
+ mask=0x80;
+ }
+ }
+ }
+ if(width%8)
+ *place=acc;
+ return 1;
+}
+/* Reads a single line into data which must be at least (pbm->width+7)/8
+ bytes of storage */
+int pbm_readline(pbm_stat* pbm,unsigned char* data)
+{
+ int tmp,tmp2;
+
+ if(pbm->current_line >= pbm->height) return 0;
+
+ if (pbm->unread)
+ {
+ memcpy (data, pbm->revdata, (pbm->width+7)/8);
+ pbm->current_line++;
+ pbm->unread = 0;
+ free (pbm->revdata);
+ pbm->revdata = NULL;
+ return 1;
+ }
-void
-pbm_unreadline(pbm_stat * const pbmStatP,
- void * const data) {
-/*----------------------------------------------------------------------------
- Push a line back into the buffer; we read too much!
------------------------------------------------------------------------------*/
- /* can store only one line in the unread buffer */
-
- if (!pbmStatP->unread) {
- pbmStatP->unread = 1;
- pbmStatP->revdata = malloc ((pbmStatP->width+7)/8);
- memcpy(pbmStatP->revdata, data, (pbmStatP->width+7)/8);
- --pbmStatP->current_line;
+ switch(pbm->version)
+ {
+ case P1:
+ if(getbytes(pbm->fptr,pbm->width,data))
+ {
+ pbm->current_line++;
+ return 1;
}
-}
+ return 0;
+
+ case P4:
+ overflow_add(pbm->width, 7);
+ tmp=(pbm->width+7)/8;
+ tmp2=fread(data,1,tmp,pbm->fptr);
+ if(tmp2 == tmp)
+ {
+ pbm->current_line++;
+ return 1;
+ }
+ fprintf(stderr,"pbm_readline(): error reading line data (%d)\n",tmp2);
+ return 0;
+ default:
+ fprintf(stderr,"pbm_readline(): unknown PBM version\n");
+ return 0;
+ }
+}
+/* push a line back into the buffer; we read too much! */
+void pbm_unreadline (pbm_stat *pbm, void *data)
+{
+ /* can only store one line in the unread buffer */
+ if (pbm->unread)
+ return;
+
+ pbm->unread = 1;
+ overflow_add(pbm->width, 7);
+ pbm->revdata = malloc ((pbm->width+7)/8);
+ memcpy (pbm->revdata, data, (pbm->width+7)/8);
+ pbm->current_line--;
+}
diff --git a/converter/pbm/pbmtoppa/pbmtoppa.c b/converter/pbm/pbmtoppa/pbmtoppa.c
index ff4a599..aa510ec 100644
--- a/converter/pbm/pbmtoppa/pbmtoppa.c
+++ b/converter/pbm/pbmtoppa/pbmtoppa.c
@@ -453,6 +453,7 @@ main(int argc, char *argv[]) {
pm_error("main(): unrecognized parameter '%s'", argv[argn]);
}
+ overflow_add(Width, 7);
Pwidth=(Width+7)/8;
printer.fptr=out;
diff --git a/converter/pbm/pbmtoxbm.c b/converter/pbm/pbmtoxbm.c
index ecb72b3..fc0eb9c 100644
--- a/converter/pbm/pbmtoxbm.c
+++ b/converter/pbm/pbmtoxbm.c
@@ -352,6 +352,8 @@ convertRaster(FILE * const ifP,
unsigned char * bitrow;
unsigned int row;
+
+ overflow_add(cols, padright);
putinit(xbmVersion);
diff --git a/converter/pbm/pktopbm.c b/converter/pbm/pktopbm.c
index 712f339..b6fcb02 100644
--- a/converter/pbm/pktopbm.c
+++ b/converter/pbm/pktopbm.c
@@ -280,6 +280,7 @@ main(int argc, char *argv[]) {
if (flagbyte == 7) { /* long form preamble */
integer packetlength = get32() ; /* character packet length */
car = get32() ; /* character number */
+ overflow_add(packetlength, pktopbm_pkloc);
endofpacket = packetlength + pktopbm_pkloc;
/* calculate end of packet */
if ((car >= MAXPKCHAR) || !filename[car]) {
diff --git a/converter/pbm/thinkjettopbm.l b/converter/pbm/thinkjettopbm.l
index 5de4f2b..7f31de5 100644
--- a/converter/pbm/thinkjettopbm.l
+++ b/converter/pbm/thinkjettopbm.l
@@ -114,7 +114,9 @@ DIG [0-9]
<RASTERMODE>\033\*b{DIG}+W {
int l;
if (rowCount >= rowCapacity) {
- rowCapacity += 100;
+ overflow_add(rowCapacity, 100);
+ rowCapacity += 100;
+ overflow2(rowCapacity, sizeof *rows);
rows = realloc (rows, rowCapacity * sizeof *rows);
if (rows == NULL)
pm_error ("Out of memory.");
@@ -226,6 +228,8 @@ yywrap (void)
/*
* Quite simple since ThinkJet bit arrangement matches PBM
*/
+
+ overflow2(maxRowLength, 8);
pbm_writepbminit(stdout, maxRowLength*8, rowCount, 0);
packed_bitrow = malloc(maxRowLength);
diff --git a/converter/pbm/ybmtopbm.c b/converter/pbm/ybmtopbm.c
index 2a42908..cf1ff03 100644
--- a/converter/pbm/ybmtopbm.c
+++ b/converter/pbm/ybmtopbm.c
@@ -43,6 +43,7 @@ getinit(FILE * const ifP,
pm_error("EOF / read error");
*depthP = 1;
+ overflow_add(*colsP, 15);
}
diff --git a/converter/pgm/lispmtopgm.c b/converter/pgm/lispmtopgm.c
index 40dd3fb..b5469f7 100644
--- a/converter/pgm/lispmtopgm.c
+++ b/converter/pgm/lispmtopgm.c
@@ -58,6 +58,7 @@ main( argc, argv )
pm_error( "depth (%d bits) is too large", depth);
pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 );
+ overflow_add(cols, 7);
grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 );
for ( row = 0; row < rows; ++row )
@@ -102,6 +103,8 @@ getinit( file, colsP, rowsP, depthP, padrightP )
if ( *depthP == 0 )
*depthP = 1; /* very old file */
+
+ overflow_add((int)colsP, 31);
*padrightP = ( ( *colsP + 31 ) / 32 ) * 32 - *colsP;
diff --git a/converter/pgm/psidtopgm.c b/converter/pgm/psidtopgm.c
index 07417d1..25bb311 100644
--- a/converter/pgm/psidtopgm.c
+++ b/converter/pgm/psidtopgm.c
@@ -78,6 +78,7 @@ main(int argc,
pm_error("bits/sample (%d) is too large.", bitspersample);
pgm_writepgminit(stdout, cols, rows, maxval, 0);
+ overflow_add(cols, 7);
grayrow = pgm_allocrow((cols + 7) / 8 * 8);
for (row = 0; row < rows; ++row) {
unsigned int col;
diff --git a/converter/ppm/Makefile b/converter/ppm/Makefile
index 003ef8d..b97349d 100644
--- a/converter/ppm/Makefile
+++ b/converter/ppm/Makefile
@@ -11,7 +11,7 @@ SUBDIRS = hpcdtoppm ppmtompeg
PORTBINARIES = 411toppm eyuvtoppm gouldtoppm ilbmtoppm imgtoppm \
leaftoppm mtvtoppm neotoppm \
- pcxtoppm pc1toppm pi1toppm picttoppm pjtoppm \
+ pcxtoppm pc1toppm pi1toppm pjtoppm \
ppmtoacad ppmtoapplevol ppmtoarbtxt ppmtoascii \
ppmtobmp ppmtoeyuv ppmtogif ppmtoicr ppmtoilbm \
ppmtoleaf ppmtolj ppmtomitsu ppmtoneo \
diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c
index b9b8986..f4fe331 100644
--- a/converter/ppm/ilbmtoppm.c
+++ b/converter/ppm/ilbmtoppm.c
@@ -608,6 +608,7 @@ decode_row(FILE * const ifP,
rawtype *chp;
cols = bmhdP->w;
+ overflow_add(cols, 15);
bytes = RowBytes(cols);
for( plane = 0; plane < nPlanes; plane++ ) {
int mask;
@@ -695,6 +696,23 @@ decode_mask(FILE * const ifP,
Multipalette handling
****************************************************************************/
+static void *
+xmalloc2(x, y)
+ int x;
+ int y;
+{
+ void *mem;
+
+ overflow2(x,y);
+ if( x * y == 0 )
+ return NULL;
+
+ mem = malloc2(x,y);
+ if( mem == NULL )
+ pm_error("out of memory allocating %d bytes", x * y);
+ return mem;
+}
+
static void
multi_adjust(ColorMap * const cmapP,
@@ -1363,6 +1381,9 @@ dcol_to_ppm(FILE * const ifP,
if( redmaxval != maxval || greenmaxval != maxval || bluemaxval != maxval )
pm_message("scaling colors to %d bits", pm_maxvaltobits(maxval));
+ overflow_add(redmaxval, 1);
+ overflow_add(greenmaxval, 1);
+ overflow_add(bluemaxval, 1);
MALLOCARRAY_NOFAIL(redtable, redmaxval +1);
MALLOCARRAY_NOFAIL(greentable, greenmaxval +1);
MALLOCARRAY_NOFAIL(bluetable, bluemaxval +1);
@@ -1802,7 +1823,9 @@ PCHG_ConvertSmall(PCHGHeader * const pchgP,
ChangeCount32 = *data++;
remDataSize -= 2;
+ overflow_add(ChangeCount16, ChangeCount32);
changes = ChangeCount16 + ChangeCount32;
+ overflow_add(changes, 1);
for (i = 0; i < changes; ++i) {
if (totalchanges >= pchgP->TotalChanges) goto fail;
if (remDataSize < 2) goto fail;
@@ -2067,6 +2090,9 @@ read_pchg(FILE * const ifP,
cmap->mp_change[i] = NULL;
if( PCHG.StartLine < 0 ) {
int nch;
+ if(PCHG.MaxReg < PCHG.MinReg)
+ pm_error("assert: MinReg > MaxReg");
+ overflow_add(PCHG.MaxReg-PCHG.MinReg, 2);
nch = PCHG.MaxReg - PCHG.MinReg +1;
MALLOCARRAY_NOFAIL(cmap->mp_init, nch + 1);
for( i = 0; i < nch; i++ )
@@ -2143,6 +2169,7 @@ process_body( FILE * const ifP,
if (typeid == ID_ILBM) {
int isdeep;
+ overflow_add(bmhdP->w, 15);
MALLOCARRAY_NOFAIL(ilbmrow, RowBytes(bmhdP->w));
*viewportmodesP |= fakeviewport; /* -isham/-isehb */
diff --git a/converter/ppm/ilbmtoppm.c.rej b/converter/ppm/ilbmtoppm.c.rej
new file mode 100644
index 0000000..972cad0
--- /dev/null
+++ b/converter/ppm/ilbmtoppm.c.rej
@@ -0,0 +1,46 @@
+--- converter/ppm/ilbmtoppm.c
++++ converter/ppm/ilbmtoppm.c
+@@ -694,6 +695,23 @@ decode_mask(FILE * const ifP,
+ Multipalette handling
+ ****************************************************************************/
+
++static void *
++xmalloc2(x, y)
++ int x;
++ int y;
++{
++ void *mem;
++
++ overflow2(x,y);
++ if( x * y == 0 )
++ return NULL;
++
++ mem = malloc2(x,y);
++ if( mem == NULL )
++ pm_error("out of memory allocating %d bytes", x * y);
++ return mem;
++}
++
+
+ static void
+ multi_adjust(cmap, row, palchange)
+@@ -1356,6 +1374,9 @@ dcol_to_ppm(FILE * const ifP,
+ if( redmaxval != maxval || greenmaxval != maxval || bluemaxval != maxval )
+ pm_message("scaling colors to %d bits", pm_maxvaltobits(maxval));
+
++ overflow_add(redmaxval, 1);
++ overflow_add(greenmaxval, 1);
++ overflow_add(bluemaxval, 1);
+ MALLOCARRAY_NOFAIL(redtable, redmaxval +1);
+ MALLOCARRAY_NOFAIL(greentable, greenmaxval +1);
+ MALLOCARRAY_NOFAIL(bluetable, bluemaxval +1);
+@@ -1785,7 +1806,9 @@ PCHG_ConvertSmall(PCHG, cmap, mask, datasize)
+ ChangeCount32 = *data++;
+ datasize -= 2;
+
++ overflow_add(ChangeCount16, ChangeCount32);
+ changes = ChangeCount16 + ChangeCount32;
++ overflow_add(changes, 1);
+ for( i = 0; i < changes; i++ ) {
+ if( totalchanges >= PCHG->TotalChanges ) goto fail;
+ if( datasize < 2 ) goto fail;
diff --git a/converter/ppm/imgtoppm.c b/converter/ppm/imgtoppm.c
index 7078b88..eb8509e 100644
--- a/converter/ppm/imgtoppm.c
+++ b/converter/ppm/imgtoppm.c
@@ -84,6 +84,7 @@ main(int argc, char ** argv) {
len = atoi((char*) buf );
if ( fread( buf, len, 1, ifp ) != 1 )
pm_error( "bad colormap buf" );
+ overflow2(cmaplen, 3);
if ( cmaplen * 3 != len )
{
pm_message(
@@ -105,6 +106,7 @@ main(int argc, char ** argv) {
pm_error( "bad pixel data header" );
buf[8] = '\0';
len = atoi((char*) buf );
+ overflow2(cols, rows);
if ( len != cols * rows )
pm_message(
"pixel data length (%d) does not match image size (%d)",
diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c
index e252ba2..270ae3b 100644
--- a/converter/ppm/pcxtoppm.c
+++ b/converter/ppm/pcxtoppm.c
@@ -409,6 +409,7 @@ pcx_planes_to_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
/*
* clear the pixel buffer
*/
+ overflow2(bytesperline, 8);
npixels = (bytesperline * 8) / bitsperpixel;
p = pixels;
while (--npixels >= 0)
@@ -470,6 +471,7 @@ pcx_16col_to_ppm(FILE * const ifP,
}
/* BytesPerLine should be >= BitsPerPixel * cols / 8 */
+ overflow2(BytesPerLine, 8);
rawcols = BytesPerLine * 8 / BitsPerPixel;
if (headerCols > rawcols) {
pm_message("warning - BytesPerLine = %d, "
diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c
index 9cf570e..6020f67 100644
--- a/converter/ppm/picttoppm.c
+++ b/converter/ppm/picttoppm.c
@@ -1,3 +1,4 @@
+#error "Unfixable. Don't ship me"
/*
* picttoppm.c -- convert a MacIntosh PICT file to PPM format.
*
diff --git a/converter/ppm/pjtoppm.c b/converter/ppm/pjtoppm.c
index ffb01d0..e7f9392 100644
--- a/converter/ppm/pjtoppm.c
+++ b/converter/ppm/pjtoppm.c
@@ -11,87 +11,65 @@
*/
#include "ppm.h"
-#include "pm_c_util.h"
#include "mallocvar.h"
static char usage[] = "[paintjetfile]";
-
-
-static unsigned int
-uintProduct(unsigned int const multiplicand,
- unsigned int const multiplier) {
-
- if (UINT_MAX / multiplier < multiplicand)
- pm_error("Airthmetic overflow");
-
- return multiplicand * multiplier;
-}
-
-
-
+static int egetc ARGS((FILE *fp));
static int
-egetc(FILE * const ifP) {
+egetc(fp)
+ FILE *fp;
+{
int c;
-
- c = fgetc(ifP);
-
- if (c == -1)
+ if ((c = fgetc(fp)) == -1)
pm_error("unexpected end of file");
-
- return c;
+ return(c);
}
-
-
int
-main(int argc, const char ** argv) {
-
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
int cmd, val;
char buffer[BUFSIZ];
int planes = 3, rows = -1, cols = -1;
+ int r = 0, c = 0, p = 0, i;
unsigned char **image = NULL;
int *imlen;
- FILE * ifP;
+ FILE *fp = stdin;
int mode;
int argn;
unsigned char bf[3];
- pixel * pixrow;
- int c;
- int row;
- int plane;
+ pixel *pixrow;
- pm_proginit(&argc, argv);
+ ppm_init(&argc, argv);
argn = 1;
if (argn != argc)
- ifP = pm_openr(argv[argn++]);
+ fp = pm_openr(argv[argn++]);
else
- ifP = stdin;
+ fp = stdin;
if (argn != argc)
pm_usage(usage);
- row = 0; /* initial value */
- plane = 0; /* initial value */
-
- while ((c = fgetc(ifP)) != -1) {
+ while ((c = fgetc(fp)) != -1) {
if (c != '\033')
continue;
- switch (c = egetc(ifP)) {
+ switch (c = egetc(fp)) {
case 'E': /* reset */
break;
- case '*': {
- unsigned int i;
- cmd = egetc(ifP);
+ case '*':
+ cmd = egetc(fp);
for (i = 0; i < BUFSIZ; i++) {
- if (!isdigit(c = egetc(ifP)) && c != '+' && c != '-')
+ if (!isdigit(c = egetc(fp)) && c != '+' && c != '-')
break;
buffer[i] = c;
}
if (i != 0) {
buffer[i] = '\0';
- if (sscanf(buffer, "%d", &val) != 1)
+ if (sscanf(buffer, "%d", &val) != 1)
pm_error("bad value `%s' at <ESC>*%c%c", buffer, cmd, c);
}
else
@@ -122,7 +100,7 @@ main(int argc, const char ** argv) {
break;
case 'U': /* planes */
planes = val;
- if (planes != 3)
+ if (planes != 3)
pm_error("can handle only 3 plane files");
break;
case 'A': /* begin raster */
@@ -148,33 +126,40 @@ main(int argc, const char ** argv) {
break;
case 'V': /* send plane */
case 'W': /* send last plane */
- if (rows == -1 || row >= rows || image == NULL) {
- if (rows == -1 || row >= rows)
+ if (rows == -1 || r >= rows || image == NULL) {
+ if (rows == -1 || r >= rows) {
+ overflow_add(rows, 100);
rows += 100;
+ }
+
if (image == NULL) {
- MALLOCARRAY(image, uintProduct(rows, planes));
- MALLOCARRAY(imlen, uintProduct(rows, planes));
- } else {
- REALLOCARRAY(image, uintProduct(rows, planes));
- REALLOCARRAY(imlen, uintProduct(rows, planes));
+ image = (unsigned char **)
+ malloc3(rows , planes , sizeof(unsigned char *));
+ imlen = (int *) malloc3(rows , planes, sizeof(int));
}
+ else {
+ overflow2(rows,planes);
+ image = (unsigned char **)
+ realloc2(image, rows * planes,
+ sizeof(unsigned char *));
+ imlen = (int *) realloc2(imlen, rows * planes, sizeof(int)); }
}
if (image == NULL || imlen == NULL)
pm_error("out of memory");
- if (plane >= planes)
+ if (p == planes)
pm_error("too many planes");
- cols = MAX(cols, val);
- imlen[row * planes + plane] = val;
- MALLOCARRAY(image[row * planes + plane], val);
- if (image[row * planes + plane] == NULL)
+ cols = cols > val ? cols : val;
+ imlen[r * planes + p] = val;
+ MALLOCARRAY(image[r * planes + p], val);
+ if (image[r * planes + p] == NULL)
pm_error("out of memory");
- if (fread(image[row * planes + plane], 1, val, ifP) != val)
+ if (fread(image[r * planes + p], 1, val, fp) != val)
pm_error("short data");
if (c == 'V')
- ++plane;
+ p++;
else {
- plane = 0;
- ++row;
+ p = 0;
+ r++;
}
break;
default:
@@ -183,7 +168,7 @@ main(int argc, const char ** argv) {
}
break;
case 'p': /* Position */
- if (plane != 0)
+ if (p != 0)
pm_error("changed position in the middle of "
"transferring planes");
switch (c) {
@@ -192,15 +177,15 @@ main(int argc, const char ** argv) {
break;
case 'Y':
if (buffer[0] == '+')
- val = row + val;
+ val = r + val;
if (buffer[0] == '-')
- val = row - val;
- for (; val > row; ++row)
- for (plane = 0; plane < 3; ++plane) {
- imlen[row * planes + plane] = 0;
- image[row * planes + plane] = NULL;
+ val = r - val;
+ for (; val > r; r++)
+ for (p = 0; p < 3; p++) {
+ imlen[r * planes + p] = 0;
+ image[r * planes + p] = NULL;
}
- row = val;
+ r = val;
break;
default:
pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
@@ -209,80 +194,65 @@ main(int argc, const char ** argv) {
default:
pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
break;
- }
- } /* case */
- } /* switch */
+ }
+ }
}
- pm_close(ifP);
- rows = row;
+ pm_close(fp);
+ rows = r;
if (mode == 1) {
- int const newcols = 10240; /* It could not be larger that that! */
- unsigned char * buf;
- unsigned int row;
-
- for (row = 0, cols = 0; row < rows; ++row) {
- unsigned int plane;
- if (image[row * planes] == NULL)
+ unsigned char *buf;
+ int newcols = 0;
+ newcols = 10240; /* It could not be larger that that! */
+ cols = 0;
+ for (r = 0; r < rows; r++) {
+ if (image[r * planes] == NULL)
continue;
- for (plane = 0; plane < planes; ++plane) {
- unsigned int i;
- unsigned int col;
+ for (p = 0; p < planes; p++) {
MALLOCARRAY(buf, newcols);
- if (buf == NULL)
+ if (buf == NULL)
pm_error("out of memory");
- for (i = 0, col = 0;
- col < imlen[plane + row * planes];
- col += 2)
- for (cmd = image[plane + row * planes][col],
- val = image[plane + row * planes][col+1];
- cmd >= 0 && i < newcols; cmd--, i++)
+ for (i = 0, c = 0; c < imlen[p + r * planes]; c += 2)
+ for (cmd = image[p + r * planes][c],
+ val = image[p + r * planes][c+1];
+ cmd >= 0 && i < newcols; cmd--, i++) {
buf[i] = val;
- cols = MAX(cols, i);
- free(image[plane + row * planes]);
- /*
- * This is less than what we have so it realloc should
+ overflow_add(i, 1);
+ }
+ cols = cols > i ? cols : i;
+ free(image[p + r * planes]);
+ /*
+ * This is less than what we have so it realloc should
* not return null. Even if it does, tough! We will
* lose a line, and probably die on the next line anyway
*/
- image[plane + row * planes] = realloc(buf, i);
+ image[p + r * planes] = (unsigned char *) realloc(buf, i);
}
}
+ overflow2(cols, 8);
cols *= 8;
}
-
+
+
ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
pixrow = ppm_allocrow(cols);
-
- for (row = 0; row < rows; ++row) {
- if (image[row * planes] == NULL) {
- unsigned int col;
- for (col = 0; col < cols; ++col)
- PPM_ASSIGN(pixrow[col], 0, 0, 0);
+ for (r = 0; r < rows; r++) {
+ if (image[r * planes] == NULL) {
+ for (c = 0; c < cols; c++)
+ PPM_ASSIGN(pixrow[c], 0, 0, 0);
continue;
}
- {
- unsigned int col;
- unsigned int cmd;
- for (cmd = 0, col = 0; col < cols; col += 8, ++cmd) {
- unsigned int i;
- for (i = 0; i < 8 && col + i < cols; ++i) {
- unsigned int plane;
- for (plane = 0; plane < planes; ++plane)
- if (mode == 0 && cmd >= imlen[row * planes + plane])
- bf[plane] = 0;
- else
- bf[plane] = (image[row * planes + plane][cmd] &
- (1 << (7 - i))) ? 255 : 0;
- PPM_ASSIGN(pixrow[col + i], bf[0], bf[1], bf[2]);
- }
+ for (cmd = 0, c = 0; c < cols; c += 8, cmd++)
+ for (i = 0; i < 8 && c + i < cols; i++) {
+ for (p = 0; p < planes; p++)
+ if (mode == 0 && cmd >= imlen[r * planes + p])
+ bf[p] = 0;
+ else
+ bf[p] = (image[r * planes + p][cmd] &
+ (1 << (7 - i))) ? 255 : 0;
+ PPM_ASSIGN(pixrow[c + i], bf[0], bf[1], bf[2]);
}
- }
- ppm_writeppmrow(stdout, pixrow, cols, 255, 0);
+ ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0);
}
pm_close(stdout);
-
- return 0;
+ exit(0);
}
-
-
-
diff --git a/converter/ppm/ppmtoeyuv.c b/converter/ppm/ppmtoeyuv.c
index f5ce115..6f072be 100644
--- a/converter/ppm/ppmtoeyuv.c
+++ b/converter/ppm/ppmtoeyuv.c
@@ -114,6 +114,7 @@ create_multiplication_tables(const pixval maxval) {
int index;
+ overflow_add(maxval, 1);
MALLOCARRAY_NOFAIL(mult299 , maxval+1);
MALLOCARRAY_NOFAIL(mult587 , maxval+1);
MALLOCARRAY_NOFAIL(mult114 , maxval+1);
diff --git a/converter/ppm/ppmtolj.c b/converter/ppm/ppmtolj.c
index 7ed814e..b4e7db1 100644
--- a/converter/ppm/ppmtolj.c
+++ b/converter/ppm/ppmtolj.c
@@ -182,6 +182,7 @@ int main(int argc, char *argv[]) {
ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
pixelrow = ppm_allocrow( cols );
+ overflow2(cols, 6);
obuf = (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
cbuf = (unsigned char *) pm_allocrow(cols * 6, sizeof(unsigned char));
if (mode == C_TRANS_MODE_DELTA)
diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c
index 50b790d..63d3182 100644
--- a/converter/ppm/ppmtomitsu.c
+++ b/converter/ppm/ppmtomitsu.c
@@ -685,6 +685,8 @@ main(int argc, char * argv[]) {
medias = MSize_User;
if (dpi300) {
+ overflow2(medias.maxcols, 2);
+ overflow2(medias.maxrows, 2);
medias.maxcols *= 2;
medias.maxrows *= 2;
}
diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c
index 76f0629..e7b06ff 100644
--- a/converter/ppm/ppmtopcx.c
+++ b/converter/ppm/ppmtopcx.c
@@ -422,6 +422,8 @@ ppmTo16ColorPcx(pixel ** const pixels,
else Planes = 1;
}
}
+ overflow2(BitsPerPixel, cols);
+ overflow_add(BitsPerPixel * cols, 7);
BytesPerLine = ((cols * BitsPerPixel) + 7) / 8;
MALLOCARRAY_NOFAIL(indexRow, cols);
MALLOCARRAY_NOFAIL(planesrow, BytesPerLine);
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
index 36464b6..c91ccf2 100644
--- a/converter/ppm/ppmtopict.c
+++ b/converter/ppm/ppmtopict.c
@@ -450,6 +450,8 @@ main(int argc, const char ** argv) {
putShort(stdout, 0); /* mode */
/* Finally, write out the data. */
+ overflow_add(cols/MAX_COUNT, 1);
+ overflow_add(cols, cols/MAX_COUNT+1);
outBuf = malloc((unsigned)(cols+cols/MAX_COUNT+1));
for (row = 0, oc = 0; row < rows; ++row) {
unsigned int rowSize;
diff --git a/converter/ppm/ppmtopj.c b/converter/ppm/ppmtopj.c
index d116773..fc84cac 100644
--- a/converter/ppm/ppmtopj.c
+++ b/converter/ppm/ppmtopj.c
@@ -179,6 +179,7 @@ char *argv[];
pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
pm_close( ifp );
+ overflow2(cols,2);
obuf = (unsigned char *) pm_allocrow(cols, sizeof(unsigned char));
cbuf = (unsigned char *) pm_allocrow(cols * 2, sizeof(unsigned char));
diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c
index 90bcef0..72d0027 100644
--- a/converter/ppm/ppmtopjxl.c
+++ b/converter/ppm/ppmtopjxl.c
@@ -267,6 +267,9 @@ main(int argc, const char * argv[]) {
if (maxval > PCL_MAXVAL)
pm_error("color range too large; reduce with ppmcscale");
+ if (cols < 0 || rows < 0)
+ pm_error("negative size is not possible");
+
/* Figure out the colormap. */
pm_message("Computing colormap...");
chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
@@ -286,6 +289,8 @@ main(int argc, const char * argv[]) {
case 0: /* direct mode (no palette) */
bpp = bitsperpixel(maxval); /* bits per pixel */
bpg = bpp; bpb = bpp;
+ overflow2(bpp, 3);
+ overflow_add(bpp*3, 7);
bpp = (bpp*3+7)>>3; /* bytes per pixel now */
bpr = (bpp<<3)-bpg-bpb;
bpp *= cols; /* bytes per row now */
@@ -295,9 +300,13 @@ main(int argc, const char * argv[]) {
case 3: case 7: pclindex++;
default:
bpp = 8/pclindex;
+ overflow_add(cols, bpp);
+ if(bpp == 0)
+ pm_error("assert: no bpp");
bpp = (cols+bpp-1)/bpp; /* bytes per row */
}
}
+ overflow2(bpp,2);
inrow = (char *)malloc((unsigned)bpp);
outrow = (char *)malloc((unsigned)bpp*2);
runcnt = (signed char *)malloc((unsigned)bpp);
diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c
index c673798..af2b445 100644
--- a/converter/ppm/ppmtowinicon.c
+++ b/converter/ppm/ppmtowinicon.c
@@ -12,6 +12,7 @@
#include <math.h>
#include <string.h>
+#include <stdlib.h>
#include "pm_c_util.h"
#include "winico.h"
@@ -214,6 +215,7 @@ createAndBitmap (gray ** const ba, int const cols, int const rows,
MALLOCARRAY_NOFAIL(rowData, rows);
icBitmap->xBytes = xBytes;
icBitmap->data = rowData;
+ overflow2(xBytes, rows);
icBitmap->size = xBytes * rows;
for (y=0;y<rows;y++) {
u1 * row;
@@ -342,6 +344,7 @@ create4Bitmap (pixel ** const pa, int const cols, int const rows,
MALLOCARRAY_NOFAIL(rowData, rows);
icBitmap->xBytes = xBytes;
icBitmap->data = rowData;
+ overflow2(xBytes, rows);
icBitmap->size = xBytes * rows;
for (y=0;y<rows;y++) {
@@ -402,6 +405,7 @@ create8Bitmap (pixel ** const pa, int const cols, int const rows,
MALLOCARRAY_NOFAIL(rowData, rows);
icBitmap->xBytes = xBytes;
icBitmap->data = rowData;
+ overflow2(xBytes, rows);
icBitmap->size = xBytes * rows;
for (y=0;y<rows;y++) {
@@ -709,7 +713,11 @@ addEntryToIcon(MS_Ico const MSIconData,
entry->bitcount = bpp;
entry->ih = createInfoHeader(entry, xorBitmap, andBitmap);
entry->colors = palette->colors;
- entry->size_in_bytes =
+ overflow2(4, entry->color_count);
+ overflow_add(xorBitmap->size, andBitmap->size);
+ overflow_add(xorBitmap->size + andBitmap->size, 40);
+ overflow_add(xorBitmap->size + andBitmap->size + 40, 4 * entry->color_count);
+ entry->size_in_bytes =
xorBitmap->size + andBitmap->size + 40 + (4 * entry->color_count);
if (verbose)
pm_message("entry->size_in_bytes = %d + %d + %d = %d",
diff --git a/converter/ppm/ppmtoxpm.c b/converter/ppm/ppmtoxpm.c
index 0e31692..1b3923f 100644
--- a/converter/ppm/ppmtoxpm.c
+++ b/converter/ppm/ppmtoxpm.c
@@ -198,6 +198,7 @@ genNumstr(unsigned int const input, int const digits) {
unsigned int i;
/* Allocate memory for printed number. Abort if error. */
+ overflow_add(digits, 1);
if (!(str = (char *) malloc(digits + 1)))
pm_error("out of memory");
@@ -315,6 +316,7 @@ genCmap(colorhist_vector const chv,
unsigned int charsPerPixel;
unsigned int xpmMaxval;
+ if (includeTransparent) overflow_add(ncolors, 1);
MALLOCARRAY(cmap, cmapSize);
if (cmapP == NULL)
pm_error("Out of memory allocating %u bytes for a color map.",
diff --git a/converter/ppm/qrttoppm.c b/converter/ppm/qrttoppm.c
index 935463e..653084c 100644
--- a/converter/ppm/qrttoppm.c
+++ b/converter/ppm/qrttoppm.c
@@ -46,7 +46,7 @@ main( argc, argv )
ppm_writeppminit( stdout, cols, rows, maxval, 0 );
pixelrow = ppm_allocrow( cols );
- buf = (unsigned char *) malloc( 3 * cols );
+ buf = (unsigned char *) malloc2( 3 , cols );
if ( buf == (unsigned char *) 0 )
pm_error( "out of memory" );
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index 2fef023..1f30cbd 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -154,127 +154,85 @@ vscale(int * const px,
-static void
-upcase(const char * const sname,
- char * const uname) {
-
- unsigned int i;
- const char * ip;
-
- for (i = 0, ip = sname; i < 31; ++i) {
- char const ch = *ip++;
-
- if (ch != EOS)
- uname[i] = islower(ch) ? toupper(ch) : ch;
- }
- uname[i] = EOS;
-}
-
-
-
-static void
-skipBytes(FILE * const fileP,
- unsigned int const count) {
-
- unsigned int i;
-
- for (i = 0; i < count; ++i)
- getc(fileP);
-}
-
-
-
-static void
-scanDirectory(FILE * const slFileP,
- long const dirPos,
- bool const dirOnly,
- const char * const uname,
- bool * const foundP) {
-/*----------------------------------------------------------------------------
- Scan the directory at the current position in *slFileP, either listing
- the directory ('dirOnly' true) or searching for a slide named
- 'uname' ('dirOnly' false).
-
- 'dirPos' is the offset in the file of the directory, i.e. the current
- position of *slFileP.
-
- In the latter case, return as *foundP whether the slide name is there.
------------------------------------------------------------------------------*/
- bool found;
- bool eof;
- long pos;
- unsigned char libent[36];
-
- for (found = false, eof = false, pos = dirPos; !found && !eof; ) {
- size_t readCt;
- readCt = fread(libent, 36, 1, slFileP);
- if (readCt != 1)
- eof = true;
- else {
- /* The directory entry is 32 bytes of NUL-terminated slide name
- followed by 4 bytes of offset of the next directory entry.
- */
- const char * const slideName = (const char *)(&libent[0]);
- if (pm_strnlen(slideName, 32) == 32)
- pm_error("Invalid input: slide name field is not "
- "nul-terminated");
- else {
- if (strlen(slideName) == 0)
- eof = true;
- else {
- pos += 36;
- if (dirOnly) {
- pm_message(" %s", slideName);
- } else if (streq(slideName, uname)) {
- long const dpos =
- (((((libent[35] << 8) | libent[34]) << 8) |
- libent[33]) << 8) | libent[32];
-
- if ((slFileP == stdin) ||
- (fseek(slFileP, dpos, 0) == -1)) {
-
- skipBytes(slFileP, dpos - pos);
- }
- found = true;
- }
- }
- }
- }
- }
- *foundP = found;
-}
-
/* SLIDEFIND -- Find a slide in a library or, if DIRONLY is
nonzero, print a directory listing of the library.
If UCASEN is nonzero, the requested slide name is
converted to upper case. */
static void
-slidefind(const char * const slideName,
- bool const dirOnly,
+slidefind(const char * const sname,
+ bool const dironly,
bool const ucasen) {
- char uname[32]; /* upper case translation of 'slideName' */
- char header[32]; /* (supposed) header read from file */
+ char uname[32];
+ unsigned char libent[36];
+ long pos;
bool found;
+ bool eof;
- if (dirOnly)
+ if (dironly)
pm_message("Slides in library:");
else {
- upcase(slideName, uname);
+ unsigned int i;
+ const char * ip;
+
+ ip = sname; /* initial value */
+
+ for (i = 0; i < 31; ++i) {
+ char const ch = *ip++;
+ if (ch == EOS)
+ break;
+
+ {
+ char const upperCh =
+ ucasen && islower(ch) ? toupper(ch) : ch;
+
+ uname[i] = upperCh;
+ }
+ }
+ uname[i] = EOS;
}
/* Read slide library header and verify. */
-
- if ((fread(header, 32, 1, slfile) != 1) ||
- (!STRSEQ(header, "AutoCAD Slide Library 1.0\r\n\32"))) {
+
+ if ((fread(libent, 32, 1, slfile) != 1) ||
+ (!streq((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
pm_error("not an AutoCAD slide library file.");
}
+ pos = 32;
+
+ /* Search for a slide with the requested name or list the directory */
+
+ for (found = false, eof = false; !found && !eof; ) {
+ size_t readCt;
+ readCt = fread(libent, 36, 1, slfile);
+ if (readCt != 1)
+ eof = true;
+ else if (strlen((char *)libent) == 0)
+ eof = true;
+ }
+ if (!eof) {
+ pos += 36;
+ if (dironly) {
+ pm_message(" %s", libent);
+ } else if (streq((char *)libent, uname)) {
+ long dpos;
+
+ dpos = (((((libent[35] << 8) | libent[34]) << 8) |
+ libent[33]) << 8) | libent[32];
+
+ if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
+ dpos -= pos;
+
+ while (dpos-- > 0)
+ getc(slfile);
+ }
+ found = true;
+ }
+ }
- scanDirectory(slfile, 32, dirOnly, ucasen ? uname : slideName, &found);
-
- if (!found && !dirOnly)
- pm_error("slide '%s' not in library.", slideName);
+ if (!found && !dironly)
+ pm_error("slide '%s' not in library.", sname);
}
@@ -392,7 +350,7 @@ slider(slvecfn slvec,
/* Verify that slide format is compatible with this program. */
- if (!STRSEQ(slfrof.slh, slhi.slh))
+ if (streq(slfrof.slh, slhi.slh))
pm_error("this is not an AutoCAD slide file.");
/* Verify that the number format and file level in the header are
@@ -506,6 +464,8 @@ slider(slvecfn slvec,
/* Allocate image buffer and clear it to black. */
+ overflow_add(ixdots, 1);
+ overflow_add(iydots, 1);
pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
PPM_ASSIGN(rgbcolor, 0, 0, 0);
ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c
index 9620942..e9083f3 100644
--- a/converter/ppm/ximtoppm.c
+++ b/converter/ppm/ximtoppm.c
@@ -118,6 +118,7 @@ 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)) {
+ overflow_add(strlen(a_head.author),1);
if (!(header->author = calloc((unsigned int)strlen(a_head.author)+1,
1))) {
pm_message("ReadXimHeader: can't calloc author string" );
@@ -127,6 +128,7 @@ ReadXimHeader(FILE * const in_fp,
strncpy(header->author, a_head.author, strlen(a_head.author));
}
if (strlen(a_head.date)) {
+ overflow_add(strlen(a_head.date),1);
if (!(header->date =calloc((unsigned int)strlen(a_head.date)+1,1))){
pm_message("ReadXimHeader: can't calloc date string" );
return(0);
@@ -135,6 +137,7 @@ ReadXimHeader(FILE * const in_fp,
strncpy(header->date, a_head.date, strlen(a_head.date));
}
if (strlen(a_head.program)) {
+ overflow_add(strlen(a_head.program),1);
if (!(header->program = calloc(
(unsigned int)strlen(a_head.program) + 1, 1))) {
pm_message("ReadXimHeader: can't calloc program string" );
@@ -161,6 +164,7 @@ ReadXimHeader(FILE * const in_fp,
if (header->nchannels == 3 && header->bits_channel == 8)
header->ncolors = 0;
else if (header->nchannels == 1 && header->bits_channel == 8) {
+ overflow2(header->ncolors, sizeof(Color));
header->colors = (Color *)calloc((unsigned int)header->ncolors,
sizeof(Color));
if (header->colors == NULL) {
diff --git a/editor/pamcut.c b/editor/pamcut.c
index 1fc9d9b..ad0e030 100644
--- a/editor/pamcut.c
+++ b/editor/pamcut.c
@@ -799,6 +799,8 @@ cutOneImage(FILE * const ifP,
outpam = inpam; /* Initial value -- most fields should be same */
outpam.file = ofP;
+ overflow_add(rightcol, 1);
+ overflow_add(bottomrow, 1);
outpam.width = rightcol - leftcol + 1;
outpam.height = bottomrow - toprow + 1;
diff --git a/editor/pnmgamma.c b/editor/pnmgamma.c
index 1fdf20e..98b7e90 100644
--- a/editor/pnmgamma.c
+++ b/editor/pnmgamma.c
@@ -596,6 +596,7 @@ createGammaTables(enum transferFunction const transferFunction,
xelval ** const btableP) {
/* Allocate space for the tables. */
+ overflow_add(maxval, 1);
MALLOCARRAY(*rtableP, maxval+1);
MALLOCARRAY(*gtableP, maxval+1);
MALLOCARRAY(*btableP, maxval+1);
diff --git a/editor/pnmhisteq.c b/editor/pnmhisteq.c
index a339f73..c2c85a3 100644
--- a/editor/pnmhisteq.c
+++ b/editor/pnmhisteq.c
@@ -107,6 +107,7 @@ computeLuminosityHistogram(xel * const * const xels,
unsigned int pixelCount;
unsigned int * lumahist;
+ overflow_add(maxval, 1);
MALLOCARRAY(lumahist, maxval + 1);
if (lumahist == NULL)
pm_error("Out of storage allocating array for %u histogram elements",
diff --git a/editor/pnmindex.csh b/editor/pnmindex.csh
index c6f1e84..c513a84 100755
--- a/editor/pnmindex.csh
+++ b/editor/pnmindex.csh
@@ -1,5 +1,7 @@
#!/bin/csh -f
#
+echo "Unsafe code, needs debugging, do not ship"
+exit 1
# pnmindex - build a visual index of a bunch of anymaps
#
# Copyright (C) 1991 by Jef Poskanzer.
diff --git a/editor/pnmpad.c b/editor/pnmpad.c
index 55cdcd6..10da3af 100644
--- a/editor/pnmpad.c
+++ b/editor/pnmpad.c
@@ -654,6 +654,8 @@ main(int argc, const char ** argv) {
computePadSizes(cmdline, cols, rows, &lpad, &rpad, &tpad, &bpad);
+ overflow_add(cols, lpad);
+ overflow_add(cols + lpad, rpad);
newcols = cols + lpad + rpad;
if (cmdline.reportonly)
diff --git a/editor/pnmremap.c b/editor/pnmremap.c
index 0c0096b..8b86cb7 100644
--- a/editor/pnmremap.c
+++ b/editor/pnmremap.c
@@ -468,6 +468,7 @@ fserr_init(struct pam * const pamP,
unsigned int const fserrSize = pamP->width + 2;
+ overflow_add(pamP->width, 2);
fserrP->width = pamP->width;
MALLOCARRAY(fserrP->thiserr, pamP->depth);
@@ -506,6 +507,7 @@ floydInitRow(struct pam * const pamP,
unsigned int col;
+ overflow_add(pamP->width, 2);
for (col = 0; col < pamP->width + 2; ++col) {
unsigned int plane;
for (plane = 0; plane < pamP->depth; ++plane)
diff --git a/editor/pnmremap.c.rej b/editor/pnmremap.c.rej
new file mode 100644
index 0000000..c627c20
--- /dev/null
+++ b/editor/pnmremap.c.rej
@@ -0,0 +1,10 @@
+--- editor/pnmremap.c
++++ editor/pnmremap.c
+@@ -506,6 +507,7 @@ floydInitRow(struct pam * const pamP, struct Fserr * const fserrP) {
+
+ int col;
+
++ overflow_add(pamP->width, 2);
+ for (col = 0; col < pamP->width + 2; ++col) {
+ unsigned int plane;
+ for (plane = 0; plane < pamP->depth; ++plane)
diff --git a/editor/pnmscalefixed.c b/editor/pnmscalefixed.c
index 884ca31..747cd8f 100644
--- a/editor/pnmscalefixed.c
+++ b/editor/pnmscalefixed.c
@@ -214,6 +214,7 @@ compute_output_dimensions(const struct cmdline_info cmdline,
const int rows, const int cols,
int * newrowsP, int * newcolsP) {
+ overflow2(rows, cols);
if (cmdline.pixels) {
if (rows * cols <= cmdline.pixels) {
*newrowsP = rows;
@@ -265,6 +266,8 @@ compute_output_dimensions(const struct cmdline_info cmdline,
if (*newcolsP < 1) *newcolsP = 1;
if (*newrowsP < 1) *newrowsP = 1;
+
+ overflow2(*newcolsP, *newrowsP);
}
@@ -446,6 +449,9 @@ main(int argc, char **argv ) {
unfilled. We can address that by stretching, whereas the other
case would require throwing away some of the input.
*/
+
+ overflow2(newcols, SCALE);
+ overflow2(newrows, SCALE);
sxscale = SCALE * newcols / cols;
syscale = SCALE * newrows / rows;
diff --git a/editor/ppmdither.c b/editor/ppmdither.c
index ec1b977..e701e09 100644
--- a/editor/ppmdither.c
+++ b/editor/ppmdither.c
@@ -356,6 +356,11 @@ dithMatrix(unsigned int const dithPower) {
(dithDim * sizeof(*dithMat)) + /* pointers */
(dithDim * dithDim * sizeof(**dithMat)); /* data */
+
+ overflow2(dithDim, sizeof(*dithMat));
+ overflow3(dithDim, dithDim, sizeof(**dithMat));
+ overflow_add(dithDim * sizeof(*dithMat), dithDim * dithDim * sizeof(**dithMat));
+
dithMat = malloc(dithMatSize);
if (dithMat == NULL)
diff --git a/editor/specialty/pamoil.c b/editor/specialty/pamoil.c
index 6cb8d3a..6f4bde9 100644
--- a/editor/specialty/pamoil.c
+++ b/editor/specialty/pamoil.c
@@ -112,6 +112,7 @@ main(int argc, char *argv[] ) {
tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type));
pm_close(ifp);
+ overflow_add(inpam.maxval, 1);
MALLOCARRAY(hist, inpam.maxval + 1);
if (hist == NULL)
pm_error("Unable to allocate memory for histogram.");
diff --git a/lib/libpam.c b/lib/libpam.c
index a8f140b..e6986f1 100644
--- a/lib/libpam.c
+++ b/lib/libpam.c
@@ -225,7 +225,8 @@ allocPamRow(const struct pam * const pamP) {
unsigned int const bytesPerTuple = allocationDepth(pamP) * sizeof(sample);
tuple * tuplerow;
- tuplerow = malloc(pamP->width * (sizeof(tuple *) + bytesPerTuple));
+ overflow_add(sizeof(tuple *), bytesPerTuple);
+ tuplerow = malloc2(pamP->width, (sizeof(tuple *) + bytesPerTuple));
if (tuplerow != NULL) {
/* Now we initialize the pointers to the individual tuples
diff --git a/lib/libpammap.c b/lib/libpammap.c
index 569156f..ba27a4c 100644
--- a/lib/libpammap.c
+++ b/lib/libpammap.c
@@ -64,7 +64,7 @@ pnm_createtuplehash(void) {
pm_error("Out of memory allocating tuple hash of size %u",
HASH_SIZE);
- for (i = 0; i < HASH_SIZE; ++i)
+ for (i = 0; i < HASH_SIZE; ++i)
retval[i] = NULL;
return retval;
@@ -82,13 +82,13 @@ pnm_destroytuplehash(tuplehash const tuplehash) {
for (i = 0; i < HASH_SIZE; ++i) {
struct tupleint_list_item * p;
struct tupleint_list_item * next;
-
+
/* Walk this chain, freeing each element */
for (p = tuplehash[i]; p; p = next) {
next = p->next;
free(p);
- }
+ }
}
/* Free the table of chains */
@@ -98,18 +98,20 @@ pnm_destroytuplehash(tuplehash const tuplehash) {
-static struct tupleint_list_item *
+static struct tupleint_list_item *
allocTupleIntListItem(struct pam * const pamP) {
- /* This is complicated by the fact that the last element of a
+ /* This is complicated by the fact that the last element of a
tupleint_list_item is of variable length, because the last element
- of _it_ is of variable length
+ of _it_ is of variable length
*/
struct tupleint_list_item * retval;
+ overflow2(pamP->depth, sizeof(sample));
+ overflow_add(sizeof(*retval)-sizeof(retval->tupleint.tuple), pamP->depth*sizeof(sample));
unsigned int const size =
- sizeof(*retval) - sizeof(retval->tupleint.tuple)
+ sizeof(*retval) - sizeof(retval->tupleint.tuple)
+ pamP->depth * sizeof(sample);
retval = (struct tupleint_list_item *) malloc(size);
@@ -121,7 +123,7 @@ allocTupleIntListItem(struct pam * const pamP) {
void
pnm_addtotuplehash(struct pam * const pamP,
- tuplehash const tuplehash,
+ tuplehash const tuplehash,
tuple const tupletoadd,
int const value,
int * const fitsP) {
@@ -138,7 +140,7 @@ pnm_addtotuplehash(struct pam * const pamP,
*fitsP = FALSE;
else {
unsigned int const hashvalue = pnm_hashtuple(pamP, tupletoadd);
-
+
*fitsP = TRUE;
pnm_assigntuple(pamP, listItemP->tupleint.tuple, tupletoadd);
@@ -151,10 +153,10 @@ pnm_addtotuplehash(struct pam * const pamP,
void
-pnm_lookuptuple(struct pam * const pamP,
- const tuplehash tuplehash,
- const tuple searchval,
- int * const foundP,
+pnm_lookuptuple(struct pam * const pamP,
+ const tuplehash tuplehash,
+ const tuple searchval,
+ int * const foundP,
int * const retvalP) {
/*----------------------------------------------------------------------------
Return as *revtvalP the index of the tuple value 'searchval' in the
@@ -183,18 +185,18 @@ pnm_lookuptuple(struct pam * const pamP,
static void
-addColorOccurrenceToHash(tuple const color,
+addColorOccurrenceToHash(tuple const color,
tuplehash const tuplefreqhash,
struct pam * const pamP,
unsigned int const maxsize,
unsigned int * const sizeP,
bool * const fullP) {
-
+
unsigned int const hashvalue = pnm_hashtuple(pamP, color);
-
+
struct tupleint_list_item *p;
- for (p = tuplefreqhash[hashvalue];
+ for (p = tuplefreqhash[hashvalue];
p && !pnm_tupleequal(pamP, p->tupleint.tuple, color);
p = p->next);
@@ -205,7 +207,7 @@ addColorOccurrenceToHash(tuple const color,
} else {
/* It's not in the hash yet, so add it (if allowed) */
++(*sizeP);
- if (maxsize > 0 && *sizeP > maxsize)
+ if (maxsize > 0 && *sizeP > maxsize)
*fullP = TRUE;
else {
*fullP = FALSE;
@@ -228,7 +230,7 @@ pnm_addtuplefreqoccurrence(struct pam * const pamP,
tuplehash const tuplefreqhash,
int * const firstOccurrenceP) {
/*----------------------------------------------------------------------------
- Tally one more occurrence of the tuple value 'value' to the tuple frequency
+ Tally one more occurence of the tuple value 'value' to the tuple frequencey
hash 'tuplefreqhash', adding the tuple to the hash if it isn't there
already.
@@ -238,10 +240,10 @@ pnm_addtuplefreqoccurrence(struct pam * const pamP,
program.
-----------------------------------------------------------------------------*/
unsigned int const hashvalue = pnm_hashtuple(pamP, value);
-
+
struct tupleint_list_item * p;
- for (p = tuplefreqhash[hashvalue];
+ for (p = tuplefreqhash[hashvalue];
p && !pnm_tupleequal(pamP, p->tupleint.tuple, value);
p = p->next);
@@ -270,8 +272,8 @@ pnm_addtuplefreqoccurrence(struct pam * const pamP,
static void
computehashrecoverable(struct pam * const pamP,
- tuple ** const tupleArray,
- unsigned int const maxsize,
+ tuple ** const tupleArray,
+ unsigned int const maxsize,
unsigned int const newDepth,
sample const newMaxval,
unsigned int * const sizeP,
@@ -295,20 +297,20 @@ computehashrecoverable(struct pam * const pamP,
*tuplefreqhashP = pnm_createtuplehash();
*sizeP = 0; /* initial value */
-
+
*rowbufferP = pnm_allocpamrow(pamP);
-
+
*colorP = pnm_allocpamtuple(pamP);
-
+
full = FALSE; /* initial value */
-
+
/* Go through the entire raster, building a hash table of
- tuple values.
+ tuple values.
*/
for (row = 0; row < pamP->height && !full; ++row) {
unsigned int col;
const tuple * tuplerow; /* The row of tuples we are processing */
-
+
if (tupleArray)
tuplerow = tupleArray[row];
else {
@@ -335,8 +337,8 @@ computehashrecoverable(struct pam * const pamP,
static tuplehash
computetuplefreqhash(struct pam * const pamP,
- tuple ** const tupleArray,
- unsigned int const maxsize,
+ tuple ** const tupleArray,
+ unsigned int const maxsize,
unsigned int const newDepth,
sample const newMaxval,
unsigned int * const sizeP) {
@@ -350,18 +352,18 @@ computetuplefreqhash(struct pam * const pamP,
2) an open PAM file, positioned to the raster. In this case,
'tupleArray' is NULL. *pamP contains the file descriptor.
-
- We return with the file still open and its position undefined.
+
+ We return with the file still open and its position undefined.
In either case, *pamP contains parameters of the tuple array.
Return the number of unique tuple values found as *sizeP.
- However, if the number of unique tuple values is greater than 'maxsize',
+ However, if the number of unique tuple values is greater than 'maxsize',
return a null return value and *sizeP undefined.
The tuple values that index the hash have depth 'newDepth'. We look at
- only the first 'newDepth' planes of the input. Caller must ensure that
+ only the first 'newDepth' planes of the input. Caler must ensure that
the input has at least that many planes.
The tuple values that index the hash are scaled to a new maxval of
@@ -374,18 +376,18 @@ computetuplefreqhash(struct pam * const pamP,
/* Buffer for a row read from the input file; undefined (but still
allocated) if input is not from a file.
*/
- tuple color;
+ tuple color;
/* The color currently being added, scaled to the new maxval */
jmp_buf jmpbuf;
jmp_buf * origJmpbufP;
-
+
/* Initialize to "none" for purposes of error recovery */
tuplefreqhash = NULL;
rowbuffer = NULL;
color = NULL;
if (setjmp(jmpbuf) != 0) {
- if (color)
+ if (color)
pnm_freepamtuple(color);
if (rowbuffer)
pnm_freepamrow(rowbuffer);
@@ -413,24 +415,24 @@ pnm_computetuplefreqhash(struct pam * const pamP,
Compute the tuple frequency hash for the tuple array tupleArray[][].
-----------------------------------------------------------------------------*/
return computetuplefreqhash(pamP, tupleArray, maxsize,
- pamP->depth, pamP->maxval,
+ pamP->depth, pamP->maxval,
sizeP);
}
static void
-alloctupletable(const struct pam * const pamP,
+alloctupletable(const struct pam * const pamP,
unsigned int const size,
tupletable * const tupletableP,
const char ** const errorP) {
-
+
if (UINT_MAX / sizeof(struct tupleint) < size)
pm_asprintf(errorP, "size %u is too big for arithmetic", size);
else {
unsigned int const mainTableSize = size * sizeof(struct tupleint *);
- unsigned int const tupleIntSize =
- sizeof(struct tupleint) - sizeof(sample)
+ unsigned int const tupleIntSize =
+ sizeof(struct tupleint) - sizeof(sample)
+ pamP->depth * sizeof(sample);
/* To save the enormous amount of time it could take to allocate
@@ -442,7 +444,7 @@ alloctupletable(const struct pam * const pamP,
else {
unsigned int const allocSize = mainTableSize + size * tupleIntSize;
void * pool;
-
+
pool = malloc(allocSize);
if (!pool)
@@ -469,7 +471,7 @@ alloctupletable(const struct pam * const pamP,
tupletable
-pnm_alloctupletable(const struct pam * const pamP,
+pnm_alloctupletable(const struct pam * const pamP,
unsigned int const size) {
tupletable retval;
@@ -491,8 +493,8 @@ void
pnm_freetupletable(const struct pam * const pamP,
tupletable const tupletable) {
- /* Note that the address 'tupletable' is, to the operating system,
- the address of a larger block of memory that contains not only
+ /* Note that the address 'tupletable' is, to the operating system,
+ the address of a larger block of memory that contains not only
tupletable, but all the samples to which it points (e.g.
tupletable[0].tuple[0])
*/
@@ -574,7 +576,7 @@ pnm_tuplehashtotable(const struct pam * const pamP,
tuplehash
-pnm_computetupletablehash(struct pam * const pamP,
+pnm_computetupletablehash(struct pam * const pamP,
tupletable const tupletable,
unsigned int const tupletableSize) {
/*----------------------------------------------------------------------------
@@ -591,12 +593,12 @@ pnm_computetupletablehash(struct pam * const pamP,
tuplehash tupletablehash;
unsigned int i;
int fits;
-
+
tupletablehash = pnm_createtuplehash();
fits = TRUE; /* initial assumption */
for (i = 0; i < tupletableSize && fits; ++i) {
- pnm_addtotuplehash(pamP, tupletablehash,
+ pnm_addtotuplehash(pamP, tupletablehash,
tupletable[i]->tuple, i, &fits);
}
if (!fits) {
@@ -658,7 +660,7 @@ pnm_computetuplefreqtable3(struct pam * const pamP,
"argument (%u) greater than input depth (%u)",
newDepth, pamP->depth);
- tuplefreqhash = computetuplefreqhash(pamP, tupleArray, maxsize,
+ tuplefreqhash = computetuplefreqhash(pamP, tupleArray, maxsize,
newDepth, newMaxval, &uniqueCount);
if (tuplefreqhash == NULL)
tuplefreqtable = NULL;
@@ -704,8 +706,8 @@ pnm_computetuplefreqtable(struct pam * const pamP,
char*
-pam_colorname(struct pam * const pamP,
- tuple const color,
+pam_colorname(struct pam * const pamP,
+ tuple const color,
enum colornameFormat const format) {
unsigned int r, g, b;
@@ -726,9 +728,9 @@ pam_colorname(struct pam * const pamP,
while (!done) {
struct colorfile_entry const ce = pm_colorget(f);
if (ce.colorname) {
- unsigned int const this_diff =
- abs((int)r - (int)ce.r) +
- abs((int)g - (int)ce.g) +
+ unsigned int const this_diff =
+ abs((int)r - (int)ce.r) +
+ abs((int)g - (int)ce.g) +
abs((int)b - (int)ce.b);
if (this_diff < best_diff) {
@@ -739,7 +741,7 @@ pam_colorname(struct pam * const pamP,
done = TRUE;
}
fclose(f);
- if (best_diff != 32767 &&
+ if (best_diff != 32767 &&
(best_diff == 0 || format == PAM_COLORNAME_ENGLISH))
return colorname;
}
diff --git a/lib/libpm.c b/lib/libpm.c
index 47a2f49..a263598 100644
--- a/lib/libpm.c
+++ b/lib/libpm.c
@@ -888,5 +888,53 @@ pm_parse_height(const char * const arg) {
return height;
}
+/*
+ * Maths wrapping
+ */
+void __overflow2(int a, int b)
+{
+ if(a < 0 || b < 0)
+ pm_error("object too large");
+ if(b == 0)
+ return;
+ if(a > INT_MAX / b)
+ pm_error("object too large");
+}
+
+void overflow3(int a, int b, int c)
+{
+ overflow2(a,b);
+ overflow2(a*b, c);
+}
+
+void overflow_add(int a, int b)
+{
+ if( a > INT_MAX - b)
+ pm_error("object too large");
+}
+
+void *malloc2(int a, int b)
+{
+ overflow2(a, b);
+ if(a*b == 0)
+ pm_error("Zero byte allocation");
+ return malloc(a*b);
+}
+
+void *malloc3(int a, int b, int c)
+{
+ overflow3(a, b, c);
+ if(a*b*c == 0)
+ pm_error("Zero byte allocation");
+ return malloc(a*b*c);
+}
+
+void *realloc2(void * a, int b, int c)
+{
+ overflow2(b, c);
+ if(b*c == 0)
+ pm_error("Zero byte allocation");
+ return realloc(a, b*c);
+}
diff --git a/lib/pm.h b/lib/pm.h
index 3fc92fb..1e30ce9 100644
--- a/lib/pm.h
+++ b/lib/pm.h
@@ -441,5 +441,12 @@ pm_parse_height(const char * const arg);
}
#endif
+void *malloc2(int, int);
+void *malloc3(int, int, int);
+#define overflow2(a,b) __overflow2(a,b)
+void __overflow2(int, int);
+void overflow3(int, int, int);
+void overflow_add(int, int);
+
#endif
diff --git a/lib/pm.h.orig b/lib/pm.h.orig
new file mode 100644
index 0000000..471f445
--- /dev/null
+++ b/lib/pm.h.orig
@@ -0,0 +1,446 @@
+/* pm.h - interface to format-independent part of libpbm.
+**
+** Copyright (C) 1988, 1989, 1991 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#ifndef PM_H_INCLUDED
+#define PM_H_INCLUDED
+
+#include <netpbm/pm_config.h>
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+} /* to fake out automatic code indenters */
+#endif
+
+
+/* Definitions to make Netpbm programs work with either ANSI C or C
+ Classic.
+
+ This is obsolete, as all compilers recognize the ANSI syntax now.
+
+ We are slowly removing all the ARGS invocations from the programs
+ (and replacing them with explicit ANSI syntax), but we have a lot
+ of programs where we have removed ARGS from the definition but not
+ the prototype, and we have discovered that the Sun compiler
+ considers the resulting mismatch between definition and prototype
+ to be an error. So we make ARGS create the ANSI syntax
+ unconditionally to avoid having to fix all those mismatches. */
+
+#if 0
+#if __STDC__
+#define ARGS(alist) alist
+#else /*__STDC__*/
+#define ARGS(alist) ()
+#define const
+#endif /*__STDC__*/
+#endif
+#define ARGS(alist) alist
+
+
+/* PM_GNU_PRINTF_ATTR lets the GNU compiler check pm_message() and pm_error()
+ calls to be sure the arguments match the format string, thus preventing
+ runtime segmentation faults and incorrect messages.
+*/
+#ifdef __GNUC__
+#define PM_GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define PM_GNU_PRINTF_ATTR(a,b)
+#endif
+
+
+/* PURE_FN_ATTR is the attribute you add to a function declaration
+ that indicates it's a true function -- has no side effects and return
+ value is not influenced by anything except its arguments.
+*/
+#ifdef __GNUC__
+#define PURE_FN_ATTR __attribute__ ((const))
+#else
+#define PURE_FN_ATTR
+#endif
+
+
+/* S_IRUSR is POSIX, defined in <sys/stat.h> Some old BSD systems and Windows
+ systems have S_IREAD instead. Most Unix today (2011) has both. In 2011,
+ Android has S_IRUSR and not S_IREAD.
+
+ Some Windows has _S_IREAD.
+
+ We're ignoring S_IREAD now to see if anyone misses it. If there are still
+ users that need it, we can handle it here.
+*/
+#if MSVCRT
+ #define PM_S_IWUSR _S_IWRITE
+ #define PM_S_IRUSR _S_IREAD
+#else
+ #define PM_S_IWUSR S_IWUSR
+ #define PM_S_IRUSR S_IRUSR
+#endif
+
+
+
+typedef struct {
+ /* Coordinates of a pixel within an image. Row 0 is the top row.
+ Column 0 is the left column.
+ */
+ unsigned int row;
+ unsigned int col;
+} pm_pixelcoord;
+
+extern int pm_plain_output;
+ /* Output functions are to produce plain (as opposed to raw) format
+ regardless of their 'plainformat' arguments.
+ */
+extern const char * pm_progname;
+
+void
+pm_init(const char * const progname, unsigned int const flags);
+
+void
+pm_proginit(int * const argcP, const char * argv[]);
+
+void
+pm_setMessage(int const newState, int * const oldStateP);
+
+int
+pm_getMessage(void);
+
+FILE *
+pm_tmpfile(void);
+
+int
+pm_tmpfile_fd(void);
+
+void
+pm_make_tmpfile(FILE ** const filePP,
+ const char ** const filenameP);
+
+void
+pm_make_tmpfile_fd(int * const fdP,
+ const char ** const filenameP);
+
+void
+pm_nextimage(FILE * const file, int * const eofP);
+
+/* Variable-sized arrays definitions. */
+
+char**
+pm_allocarray (int const cols, int const rows, int const size );
+
+void *
+pm_allocrow(unsigned int const cols,
+ unsigned int const size);
+
+void
+pm_freearray (char** const its, int const rows);
+
+void
+pm_freerow(void * const row);
+
+
+/* Obsolete -- use shhopt instead */
+int
+pm_keymatch(const char * const str,
+ const char * const keyword,
+ int const minchars);
+
+
+int PURE_FN_ATTR
+pm_maxvaltobits(int const maxval);
+
+int PURE_FN_ATTR
+pm_bitstomaxval(int const bits);
+
+unsigned int PURE_FN_ATTR
+pm_lcm (unsigned int const x,
+ unsigned int const y,
+ unsigned int const z,
+ unsigned int const limit);
+
+void
+pm_setjmpbuf(jmp_buf * const jmpbufP);
+
+void
+pm_setjmpbufsave(jmp_buf * const jmpbufP,
+ jmp_buf ** const oldJmpbufPP);
+
+void
+pm_longjmp(void);
+
+void
+pm_fork(int * const iAmParentP,
+ pid_t * const childPidP,
+ const char ** const errorP);
+
+void
+pm_waitpid(pid_t const pid,
+ int * const statusP,
+ int const options,
+ pid_t * const exitedPidP,
+ const char ** const errorP);
+
+
+void
+pm_waitpidSimple(pid_t const pid);
+
+typedef void pm_usermessagefn(const char * msg);
+
+void
+pm_setusermessagefn(pm_usermessagefn * fn);
+
+typedef void pm_usererrormsgfn(const char * msg);
+
+void
+pm_setusererrormsgfn(pm_usererrormsgfn * fn);
+
+void PM_GNU_PRINTF_ATTR(1,2)
+pm_message (const char format[], ...);
+
+void PM_GNU_PRINTF_ATTR(1,2)
+pm_errormsg(const char format[], ...);
+
+void PM_GNU_PRINTF_ATTR(1,2)
+pm_error (const char reason[], ...);
+
+int
+pm_have_float_format(void);
+
+/* Obsolete - use shhopt and user's manual instead */
+void
+pm_usage (const char usage[]);
+
+FILE*
+pm_openr (const char* const name);
+
+FILE*
+pm_openw (const char* const name);
+
+FILE *
+pm_openr_seekable(const char name[]);
+
+void
+pm_close (FILE* const f);
+
+void
+pm_closer (FILE* const f);
+
+void
+pm_closew (FILE* const f);
+
+
+
+void
+pm_readchar(FILE * const ifP,
+ char * const cP);
+
+static __inline__ void
+pm_readcharu(FILE * const ifP,
+ unsigned char * const cP) {
+ pm_readchar(ifP, (char *) cP);
+}
+
+void
+pm_writechar(FILE * const ofP,
+ char const c);
+
+static __inline__ void
+pm_writecharu(FILE * const ofP,
+ unsigned char const c) {
+ pm_writechar(ofP, (char) c);
+}
+
+int
+pm_readbigshort(FILE * const ifP,
+ short * const sP);
+
+static __inline__ int
+pm_readbigshortu(FILE* const ifP,
+ unsigned short * const sP) {
+ return pm_readbigshort(ifP, (short *) sP);
+}
+
+int
+pm_writebigshort(FILE * const ofP,
+ short const s);
+
+static __inline__ int
+pm_writebigshortu(FILE * const ofP,
+ unsigned short const s) {
+ return pm_writebigshort(ofP, (short) s);
+}
+
+int
+pm_readbiglong(FILE * const ifP,
+ long * const lP);
+
+static __inline__ int
+pm_readbiglongu(FILE * const ifP,
+ unsigned long * const lP) {
+ return pm_readbiglong(ifP, (long *) lP);
+}
+
+int
+pm_readbiglong2(FILE * const ifP,
+ int32_t * const lP);
+
+static __inline__ int
+pm_readbiglongu2(FILE * const ifP,
+ uint32_t * const lP) {
+ return pm_readbiglong2(ifP, (int32_t *) lP);
+}
+
+int
+pm_writebiglong(FILE * const ofP,
+ long const l);
+
+static __inline__ int
+pm_writebiglongu(FILE * const ofP,
+ unsigned long const l) {
+ return pm_writebiglong(ofP, (long) l);
+}
+
+int
+pm_readlittleshort(FILE * const ifP,
+ short * const sP);
+
+static __inline__ int
+pm_readlittleshortu(FILE * const ifP,
+ unsigned short * const sP) {
+ return pm_readlittleshort(ifP, (short *) sP);
+}
+
+int
+pm_writelittleshort(FILE * const ofP,
+ short const s);
+
+static __inline__ int
+pm_writelittleshortu(FILE * const ofP,
+ unsigned short const s) {
+ return pm_writelittleshort(ofP, (short) s);
+}
+
+int
+pm_readlittlelong(FILE * const ifP,
+ long * const lP);
+
+static __inline__ int
+pm_readlittlelongu(FILE * const ifP,
+ unsigned long * const lP) {
+ return pm_readlittlelong(ifP, (long *) lP);
+}
+
+int
+pm_readlittlelong2(FILE * const ifP,
+ int32_t * const lP);
+
+static __inline__ int
+pm_readlittlelong2u(FILE * const ifP,
+ uint32_t * const lP) {
+ return pm_readlittlelong2(ifP, (int32_t *) lP);
+}
+
+int
+pm_writelittlelong(FILE * const ofP,
+ long const l);
+
+static __inline__ int
+pm_writelittlelongu(FILE * const ofP,
+ unsigned long const l) {
+ return pm_writelittlelong(ofP, (long) l);
+}
+
+int
+pm_readmagicnumber(FILE * const ifP);
+
+char*
+pm_read_unknown_size(FILE * const ifP,
+ long * const buf);
+
+void
+pm_getline(FILE * const ifP,
+ char ** const bufferP,
+ size_t * const bufferSzP,
+ int * const eofP,
+ size_t * const lineLenP);
+
+short
+pm_bs_short(short const s);
+
+long
+pm_bs_long(long const l);
+
+unsigned int
+pm_tell(FILE * const fileP);
+
+void
+pm_tell2(FILE * const fileP,
+ void * const fileposP,
+ unsigned int const fileposSize);
+
+void
+pm_seek2(FILE * const fileP,
+ const pm_filepos * const fileposP,
+ unsigned int const fileposSize);
+
+void
+pm_seek(FILE * const fileP, unsigned long filepos);
+
+enum pm_check_code {
+ PM_CHECK_OK,
+ PM_CHECK_UNKNOWN_TYPE,
+ PM_CHECK_TOO_LONG,
+ PM_CHECK_UNCHECKABLE,
+ PM_CHECK_TOO_SHORT
+};
+
+enum pm_check_type {
+ PM_CHECK_BASIC
+};
+
+void
+pm_check(FILE * const file,
+ enum pm_check_type const check_type,
+ pm_filepos const need_raster_size,
+ enum pm_check_code * const retval_p);
+
+void
+pm_drain(FILE * const fileP,
+ unsigned int const limit,
+ unsigned int * const bytesReadP);
+
+char *
+pm_arg0toprogname(const char arg0[]);
+
+unsigned int
+pm_randseed(void);
+
+unsigned int
+pm_parse_width(const char * const arg);
+
+unsigned int
+pm_parse_height(const char * const arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/other/pnmcolormap.c b/other/pnmcolormap.c
index 7da3122..dafa390 100644
--- a/other/pnmcolormap.c
+++ b/other/pnmcolormap.c
@@ -1002,6 +1002,7 @@ colormapToSquare(struct pam * const pamP,
pamP->width = intsqrt;
else
pamP->width = intsqrt + 1;
+ overflow_add(intsqrt, 1);
}
{
unsigned int const intQuotient = colormap.size / pamP->width;
diff --git a/other/pnmcolormap.c.orig b/other/pnmcolormap.c.orig
new file mode 100644
index 0000000..7da3122
--- /dev/null
+++ b/other/pnmcolormap.c.orig
@@ -0,0 +1,1143 @@
+/******************************************************************************
+ pnmcolormap.c
+*******************************************************************************
+
+ Create a colormap file (a PPM image containing one pixel of each of a set
+ of colors). Base the set of colors on an input image.
+
+ For PGM input, do the equivalent for grayscale and produce a PGM graymap.
+
+ By Bryan Henderson, San Jose, CA 2001.12.17
+
+ Derived from ppmquant, originally by Jef Poskanzer.
+
+ Copyright (C) 1989, 1991 by Jef Poskanzer.
+ Copyright (C) 2001 by Bryan Henderson.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation. This software is provided "as is" without express or
+ implied warranty.
+
+******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "pm_config.h"
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "nstring.h"
+#include "shhopt.h"
+#include "pam.h"
+#include "pammap.h"
+
+enum MethodForLargest {LARGE_NORM, LARGE_LUM};
+
+enum MethodForRep {REP_CENTER_BOX, REP_AVERAGE_COLORS, REP_AVERAGE_PIXELS};
+
+enum MethodForSplit {SPLIT_MAX_PIXELS, SPLIT_MAX_COLORS, SPLIT_MAX_SPREAD};
+
+struct Box {
+ unsigned int index;
+ unsigned int colorCt;
+ unsigned int sum;
+ unsigned int maxdim;
+ /* which dimension has the largest spread. RGB plane number. */
+ sample spread;
+ /* spread in dimension 'maxdim' */
+};
+
+struct BoxVector {
+ struct Box * box; /* malloc'ed array */
+ unsigned int boxCt;
+ unsigned int capacity;
+};
+
+struct CmdlineInfo {
+ /* All the information the user supplied in the command line,
+ in a form easy for the program to use.
+ */
+ const char * inputFileNm; /* Name of input file */
+ unsigned int allcolors; /* boolean: select all colors from the input */
+ unsigned int newcolors;
+ /* Number of colors argument; meaningless if allcolors true */
+ enum MethodForLargest methodForLargest;
+ /* -spreadintensity/-spreadluminosity options */
+ enum MethodForRep methodForRep;
+ /* -center/-meancolor/-meanpixel options */
+ enum MethodForSplit methodForSplit;
+ /* -splitpixelct/-splitcolorct/-splitspread options */
+ unsigned int sort;
+ unsigned int square;
+ unsigned int verbose;
+};
+
+
+
+static void
+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.
+
+ If command line is internally inconsistent (invalid options, etc.),
+ issue error message to stderr and abort program.
+
+ Note that the strings we return are stored in the storage that
+ was passed to us as the argv array. We also trash *argv.
+-----------------------------------------------------------------------------*/
+ optEntry *option_def;
+ /* Instructions to pm_optParseOptions3 on how to parse our options.
+ */
+ optStruct3 opt;
+
+ unsigned int option_def_index;
+
+ unsigned int spreadbrightness, spreadluminosity;
+ unsigned int center, meancolor, meanpixel;
+ unsigned int splitpixelct, splitcolorct, splitspread;
+
+ MALLOCARRAY_NOFAIL(option_def, 100);
+
+ option_def_index = 0; /* incremented by OPTENT3 */
+ OPTENT3(0, "spreadbrightness", OPT_FLAG,
+ NULL, &spreadbrightness, 0);
+ OPTENT3(0, "spreadluminosity", OPT_FLAG,
+ NULL, &spreadluminosity, 0);
+ OPTENT3(0, "center", OPT_FLAG,
+ NULL, &center, 0);
+ OPTENT3(0, "meancolor", OPT_FLAG,
+ NULL, &meancolor, 0);
+ OPTENT3(0, "meanpixel", OPT_FLAG,
+ NULL, &meanpixel, 0);
+ OPTENT3(0, "splitpixelct", OPT_FLAG,
+ NULL, &splitpixelct, 0);
+ OPTENT3(0, "splitcolorct", OPT_FLAG,
+ NULL, &splitcolorct, 0);
+ OPTENT3(0, "splitspread", OPT_FLAG,
+ NULL, &splitspread, 0);
+ OPTENT3(0, "sort", OPT_FLAG, NULL,
+ &cmdlineP->sort, 0 );
+ OPTENT3(0, "square", OPT_FLAG, NULL,
+ &cmdlineP->square, 0 );
+ OPTENT3(0, "verbose", OPT_FLAG, NULL,
+ &cmdlineP->verbose, 0 );
+
+ opt.opt_table = option_def;
+ opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
+ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
+
+ pm_optParseOptions3( &argc, (char **)argv, opt, sizeof(opt), 0 );
+ /* Uses and sets argc, argv, and some of *cmdline_p and others. */
+
+
+ if (spreadbrightness && spreadluminosity)
+ pm_error("You cannot specify both -spreadbrightness and "
+ "spreadluminosity.");
+ if (spreadluminosity)
+ cmdlineP->methodForLargest = LARGE_LUM;
+ else
+ cmdlineP->methodForLargest = LARGE_NORM;
+
+ if (center + meancolor + meanpixel > 1)
+ pm_error("You can specify only one of -center, -meancolor, and "
+ "-meanpixel.");
+ if (meancolor)
+ cmdlineP->methodForRep = REP_AVERAGE_COLORS;
+ else if (meanpixel)
+ cmdlineP->methodForRep = REP_AVERAGE_PIXELS;
+ else
+ cmdlineP->methodForRep = REP_CENTER_BOX;
+
+ if (splitpixelct)
+ cmdlineP->methodForSplit = SPLIT_MAX_PIXELS;
+ else if (splitcolorct)
+ cmdlineP->methodForSplit = SPLIT_MAX_COLORS;
+ else if (splitspread)
+ cmdlineP->methodForSplit = SPLIT_MAX_SPREAD;
+ else
+ cmdlineP->methodForSplit = SPLIT_MAX_PIXELS;
+
+ if (argc-1 > 2)
+ pm_error("Program takes at most two arguments: number of colors "
+ "and input file specification. "
+ "You specified %d arguments.", argc-1);
+ else {
+ if (argc-1 < 2)
+ cmdlineP->inputFileNm = "-";
+ else
+ cmdlineP->inputFileNm = argv[2];
+
+ if (argc-1 < 1)
+ pm_error("You must specify the number of colors in the "
+ "output as an argument.");
+ else {
+ if (strcmp(argv[1], "all") == 0)
+ cmdlineP->allcolors = TRUE;
+ else {
+ char * tail;
+ long int const newcolors = strtol(argv[1], &tail, 10);
+ if (*tail != '\0')
+ pm_error("The number of colors argument '%s' is not "
+ "a number or 'all'", argv[1]);
+ else if (newcolors < 1)
+ pm_error("The number of colors must be positive");
+ else if (newcolors == 1)
+ pm_error("The number of colors must be greater than 1.");
+ else {
+ cmdlineP->newcolors = newcolors;
+ cmdlineP->allcolors = FALSE;
+ }
+ }
+ }
+ }
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn compareplane;
+#endif
+
+static unsigned int compareplanePlane;
+ /* This is a parameter to compareplane(). We use this global variable
+ so that compareplane() can be called by qsort(), to compare two
+ tuples. qsort() doesn't pass any arguments except the two tuples.
+ */
+static int
+compareplane(const void * const arg1,
+ const void * const arg2) {
+
+ const struct tupleint * const * const comparandPP = arg1;
+ const struct tupleint * const * const comparatorPP = arg2;
+
+ sample const comparandSample = (*comparandPP) ->tuple[compareplanePlane];
+ sample const comparatorSample = (*comparatorPP)->tuple[compareplanePlane];
+
+ return
+ comparandSample < comparatorSample ? -1 :
+ comparandSample > comparatorSample ? 1 :
+ 0;
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn sumcompare;
+#endif
+
+static int
+sumcompare(const void * const arg1,
+ const void * const arg2) {
+
+ struct Box * const comparandP = (struct Box *)arg1;
+ struct Box * const comparatorP = (struct Box *)arg2;
+
+ return
+ comparatorP->sum < comparandP->sum ? -1 :
+ comparatorP->sum > comparandP->sum ? 1 :
+ 0;
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn colcompare;
+#endif
+
+static int
+colcompare(const void * const arg1,
+ const void * const arg2) {
+
+ struct Box * const comparandP = (struct Box *)arg1;
+ struct Box * const comparatorP = (struct Box *)arg2;
+
+ return
+ comparatorP->colorCt < comparandP->colorCt ? -1 :
+ comparatorP->colorCt > comparandP->colorCt ? 1 :
+ 0;
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn spreadcompare;
+#endif
+
+static int
+spreadcompare(const void * const arg1,
+ const void * const arg2) {
+
+ struct Box * const comparandP = (struct Box *)arg1;
+ struct Box * const comparatorP = (struct Box *)arg2;
+
+ return
+ comparatorP->spread < comparandP->spread ? -1 :
+ comparatorP->spread > comparandP->spread ? 1 :
+ 0;
+}
+
+
+
+static void
+sortBoxes(struct BoxVector * const boxVectorP,
+ enum MethodForSplit const methodForSplit) {
+
+ qsort_comparison_fn * comparisonFn;
+
+ switch (methodForSplit){
+ case SPLIT_MAX_PIXELS: comparisonFn = &sumcompare; break;
+ case SPLIT_MAX_COLORS: comparisonFn = &colcompare; break;
+ case SPLIT_MAX_SPREAD: comparisonFn = &spreadcompare; break;
+ }
+
+ qsort((char*) &boxVectorP->box[0], boxVectorP->boxCt, sizeof(struct Box),
+ comparisonFn);
+}
+
+
+
+/*
+** Here is the fun part, the median-cut colormap generator. This is based
+** on Paul Heckbert's paper "Color Image Quantization for Frame Buffer
+** Display", SIGGRAPH '82 Proceedings, page 297.
+*/
+
+static void
+findBoxBoundaries(tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ unsigned int const boxStart,
+ unsigned int const boxSize,
+ sample minval[],
+ sample maxval[]) {
+/*----------------------------------------------------------------------------
+ Go through the box finding the minimum and maximum of each component - the
+ boundaries of the box.
+-----------------------------------------------------------------------------*/
+ unsigned int plane;
+ unsigned int i;
+
+ for (plane = 0; plane < depth; ++plane) {
+ minval[plane] = colorfreqtable.table[boxStart]->tuple[plane];
+ maxval[plane] = minval[plane];
+ }
+
+ for (i = 1; i < boxSize; ++i) {
+ unsigned int plane;
+ for (plane = 0; plane < depth; ++plane) {
+ sample const v = colorfreqtable.table[boxStart + i]->tuple[plane];
+ if (v < minval[plane]) minval[plane] = v;
+ if (v > maxval[plane]) maxval[plane] = v;
+ }
+ }
+}
+
+
+
+static void
+findPlaneWithLargestSpreadByNorm(sample const minval[],
+ sample const maxval[],
+ unsigned int const depth,
+ unsigned int * const planeP,
+ sample * const spreadP) {
+
+ unsigned int planeWithLargest;
+ sample largestSpreadSoFar;
+ unsigned int plane;
+
+ for (plane = 0, largestSpreadSoFar = 0; plane < depth; ++plane) {
+
+ sample const spread = maxval[plane]-minval[plane];
+ if (spread > largestSpreadSoFar) {
+ largestSpreadSoFar = spread;
+ planeWithLargest = plane;
+ }
+ }
+ *planeP = planeWithLargest;
+ *spreadP = largestSpreadSoFar;
+}
+
+
+
+static void
+findPlaneWithLargestSpreadByLuminosity(sample const minval[],
+ sample const maxval[],
+ unsigned int const depth,
+ unsigned int * const planeP,
+ sample * const spreadP) {
+/*----------------------------------------------------------------------------
+ This subroutine presumes that the tuple type is either
+ BLACKANDWHITE, GRAYSCALE, or RGB (which implies pamP->depth is 1 or 3).
+ To save time, we don't actually check it.
+-----------------------------------------------------------------------------*/
+ if (depth == 1){
+ *planeP = 0;
+ *spreadP = 0;
+ } else {
+ /* An RGB tuple */
+ unsigned int planeWithLargest;
+ sample largestSpreadSoFar;
+ unsigned int plane;
+
+ assert(depth >= 3);
+
+ for (plane = 0, largestSpreadSoFar = 0; plane < 3; ++plane) {
+ double const spread =
+ pnm_lumin_factor[plane] * (maxval[plane]-minval[plane]);
+ if (spread > largestSpreadSoFar) {
+ largestSpreadSoFar = spread;
+ planeWithLargest = plane;
+ }
+ }
+ *planeP = planeWithLargest;
+ *spreadP = largestSpreadSoFar;
+ }
+}
+
+
+
+static void
+computeBoxSpread(const struct Box * const boxP,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ enum MethodForLargest const methodForLargest,
+ unsigned int * const planeWithLargestP,
+ sample * const spreadP
+ ) {
+/*----------------------------------------------------------------------------
+ Find the spread in the dimension in which it is greatest.
+
+ Return as *planeWithLargestP the number of that plane and as *spreadP the
+ spread in that plane.
+-----------------------------------------------------------------------------*/
+ sample * minval; /* malloc'ed array */
+ sample * maxval; /* malloc'ed array */
+
+ MALLOCARRAY_NOFAIL(minval, depth);
+ MALLOCARRAY_NOFAIL(maxval, depth);
+
+ findBoxBoundaries(colorfreqtable, depth, boxP->index, boxP->colorCt,
+ minval, maxval);
+
+ switch (methodForLargest) {
+ case LARGE_NORM:
+ findPlaneWithLargestSpreadByNorm(minval, maxval, depth,
+ planeWithLargestP, spreadP);
+ break;
+ case LARGE_LUM:
+ findPlaneWithLargestSpreadByLuminosity(minval, maxval, depth,
+ planeWithLargestP, spreadP);
+ break;
+ }
+ free(minval); free(maxval);
+}
+
+
+
+static unsigned int
+freqTotal(tupletable2 const freqtable) {
+
+ unsigned int i;
+ unsigned int sum;
+
+ for (i = 0, sum = 0; i < freqtable.size; ++i)
+ sum += freqtable.table[i]->value;
+
+ return sum;
+}
+
+
+
+static struct BoxVector
+newBoxVector(tupletable2 const colorfreqtable,
+ unsigned int const capacity,
+ unsigned int const depth,
+ enum MethodForLargest const methodForLargest) {
+
+ unsigned int const colorCt = colorfreqtable.size;
+ unsigned int const sum = freqTotal(colorfreqtable);
+
+ struct BoxVector boxVector;
+
+ MALLOCARRAY(boxVector.box, capacity);
+
+ if (!boxVector.box)
+ pm_error("out of memory allocating box vector table");
+
+ /* Set up the initial box. */
+ boxVector.box[0].index = 0;
+ boxVector.box[0].colorCt = colorCt;
+ boxVector.box[0].sum = sum;
+
+ computeBoxSpread(&boxVector.box[0], colorfreqtable, depth,
+ methodForLargest,
+ &boxVector.box[0].maxdim,
+ &boxVector.box[0].spread);
+
+ boxVector.boxCt = 1;
+ boxVector.capacity = capacity;
+
+ return boxVector;
+}
+
+
+
+static void
+destroyBoxVector(struct BoxVector const boxVector) {
+
+ free(boxVector.box);
+}
+
+
+
+static void
+centerBox(int const boxStart,
+ int const boxSize,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ tuple const newTuple) {
+
+ unsigned int plane;
+
+ for (plane = 0; plane < depth; ++plane) {
+ int minval, maxval;
+ unsigned int i;
+
+ minval = maxval = colorfreqtable.table[boxStart]->tuple[plane];
+
+ for (i = 1; i < boxSize; ++i) {
+ int const v = colorfreqtable.table[boxStart + i]->tuple[plane];
+ minval = MIN( minval, v);
+ maxval = MAX( maxval, v);
+ }
+ newTuple[plane] = (minval + maxval) / 2;
+ }
+}
+
+
+
+static tupletable2
+newColorMap(unsigned int const colorCt,
+ unsigned int const depth) {
+
+ tupletable2 colormap;
+ unsigned int i;
+ struct pam pam;
+
+ pam.depth = depth;
+
+ colormap.table = pnm_alloctupletable(&pam, colorCt);
+
+ for (i = 0; i < colorCt; ++i) {
+ unsigned int plane;
+ for (plane = 0; plane < depth; ++plane)
+ colormap.table[i]->tuple[plane] = 0;
+ }
+ colormap.size = colorCt;
+
+ return colormap;
+}
+
+
+
+static void
+averageColors(int const boxStart,
+ int const boxSize,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ tuple const newTuple) {
+
+ unsigned int plane;
+
+ for (plane = 0; plane < depth; ++plane) {
+ sample sum;
+ int i;
+
+ sum = 0;
+
+ for (i = 0; i < boxSize; ++i)
+ sum += colorfreqtable.table[boxStart+i]->tuple[plane];
+
+ newTuple[plane] = ROUNDDIV(sum, boxSize);
+ }
+}
+
+
+
+static void
+averagePixels(int const boxStart,
+ int const boxSize,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ tuple const newTuple) {
+
+ unsigned int n;
+ /* Number of tuples represented by the box */
+ unsigned int plane;
+ unsigned int i;
+
+ /* Count the tuples in question */
+ n = 0; /* initial value */
+ for (i = 0; i < boxSize; ++i)
+ n += colorfreqtable.table[boxStart + i]->value;
+
+
+ for (plane = 0; plane < depth; ++plane) {
+ sample sum;
+ int i;
+
+ sum = 0;
+
+ for (i = 0; i < boxSize; ++i)
+ sum += colorfreqtable.table[boxStart+i]->tuple[plane]
+ * colorfreqtable.table[boxStart+i]->value;
+
+ newTuple[plane] = ROUNDDIV(sum, n);
+ }
+}
+
+
+
+static tupletable2
+colormapFromBv(unsigned int const colorCt,
+ struct BoxVector const boxVector,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ enum MethodForRep const methodForRep) {
+ /*
+ ** Ok, we've got enough boxes. Now choose a representative color for
+ ** each box. There are a number of possible ways to make this choice.
+ ** One would be to choose the center of the box; this ignores any structure
+ ** within the boxes. Another method would be to average all the colors in
+ ** the box - this is the method specified in Heckbert's paper. A third
+ ** method is to average all the pixels in the box.
+ */
+ tupletable2 colormap;
+ unsigned int boxIdx;
+
+ colormap = newColorMap(colorCt, depth);
+
+ for (boxIdx = 0; boxIdx < boxVector.boxCt; ++boxIdx) {
+ switch (methodForRep) {
+ case REP_CENTER_BOX:
+ centerBox(boxVector.box[boxIdx].index,
+ boxVector.box[boxIdx].colorCt,
+ colorfreqtable, depth,
+ colormap.table[boxIdx]->tuple);
+ break;
+ case REP_AVERAGE_COLORS:
+ averageColors(boxVector.box[boxIdx].index,
+ boxVector.box[boxIdx].colorCt,
+ colorfreqtable, depth,
+ colormap.table[boxIdx]->tuple);
+ break;
+ case REP_AVERAGE_PIXELS:
+ averagePixels(boxVector.box[boxIdx].index,
+ boxVector.box[boxIdx].colorCt,
+ colorfreqtable, depth,
+ colormap.table[boxIdx]->tuple);
+ break;
+ default:
+ pm_error("Internal error: invalid value of methodForRep: %d",
+ methodForRep);
+ }
+ }
+ return colormap;
+}
+
+
+
+static void
+splitBox(struct BoxVector * const boxVectorP,
+ unsigned int const boxIdx,
+ tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ enum MethodForLargest const methodForLargest,
+ enum MethodForSplit const methodForSplit) {
+/*----------------------------------------------------------------------------
+ Split Box 'boxIdx' in the box vector 'boxVector' (so that bv contains one
+ more box than it did as input). Split it so that each new box represents
+ about half of the pixels in the distribution given by 'colorfreqtable' for
+ the colors in the original box, but with distinct colors in each of the two
+ new boxes.
+
+ Assume the box contains at least two colors.
+-----------------------------------------------------------------------------*/
+ unsigned int const boxStart = boxVectorP->box[boxIdx].index;
+ unsigned int const boxSize = boxVectorP->box[boxIdx].colorCt;
+ unsigned int const sum = boxVectorP->box[boxIdx].sum;
+
+ unsigned int medianIndex;
+ int lowersum;
+ /* Number of pixels whose value is "less than" the median */
+
+
+ /* Perhaps this sort should go after creating a box, not before splitting.
+ Because you need the sort to use the REP_CENTER_BOX method of choosing
+ a color to represent the final boxes
+ */
+
+ /* Set the gross global variable 'compareplanePlane' as a
+ parameter to compareplane(), which is called by qsort().
+ */
+ compareplanePlane = boxVectorP->box[boxIdx].maxdim;
+ qsort((char*) &colorfreqtable.table[boxStart], boxSize,
+ sizeof(colorfreqtable.table[boxStart]),
+ compareplane);
+
+ {
+ /* Find the median based on the counts, so that about half the pixels
+ (not colors, pixels) are in each subdivision.
+ */
+ unsigned int i;
+
+ lowersum = colorfreqtable.table[boxStart]->value; /* initial value */
+ for (i = 1; i < boxSize - 1 && lowersum < sum/2; ++i) {
+ lowersum += colorfreqtable.table[boxStart + i]->value;
+ }
+ medianIndex = i;
+ }
+ /* Split the box, and sort to bring the biggest boxes to the top. */
+ {
+ struct Box * const oldBoxP = &boxVectorP->box[boxIdx];
+
+ oldBoxP->colorCt = medianIndex;
+ oldBoxP->sum = lowersum;
+ computeBoxSpread(oldBoxP, colorfreqtable, depth, methodForLargest,
+ &oldBoxP->maxdim, &oldBoxP->spread);
+ }
+ {
+ struct Box * const newBoxP = &boxVectorP->box[boxVectorP->boxCt];
+
+ newBoxP->index = boxStart + medianIndex;
+ newBoxP->colorCt = boxSize - medianIndex;
+ newBoxP->sum = sum - lowersum;
+ computeBoxSpread(newBoxP, colorfreqtable, depth, methodForLargest,
+ &newBoxP->maxdim, &newBoxP->spread);
+ ++boxVectorP->boxCt;
+ }
+
+ sortBoxes(boxVectorP, methodForSplit);
+}
+
+
+
+static void
+mediancut(tupletable2 const colorfreqtable,
+ unsigned int const depth,
+ int const newcolorCt,
+ enum MethodForLargest const methodForLargest,
+ enum MethodForRep const methodForRep,
+ enum MethodForSplit const methodForSplit,
+ tupletable2 * const colormapP) {
+/*----------------------------------------------------------------------------
+ Compute a set of only 'newcolorCt' colors that best represent an
+ image whose pixels are summarized by the histogram
+ 'colorfreqtable'. Each tuple in that table has depth 'depth'.
+ colorfreqtable.table[i] tells the number of pixels in the subject image
+ have a particular color.
+
+ As a side effect, sort 'colorfreqtable'.
+-----------------------------------------------------------------------------*/
+ struct BoxVector boxVector;
+ bool multicolorBoxesExist;
+ /* There is at least one box that contains at least 2 colors; ergo,
+ there is more splitting we can do.
+ */
+
+ boxVector = newBoxVector(colorfreqtable, newcolorCt, depth,
+ methodForLargest);
+
+ multicolorBoxesExist = (colorfreqtable.size > 1);
+
+ /* Split boxes until we have enough. */
+ while (boxVector.boxCt < newcolorCt && multicolorBoxesExist) {
+ unsigned int boxIdx;
+
+ for (boxIdx = 0;
+ boxIdx < boxVector.boxCt && boxVector.box[boxIdx].colorCt < 2;
+ ++boxIdx);
+ /* Find the first splittable box. */
+
+ if (boxIdx >= boxVector.boxCt)
+ multicolorBoxesExist = FALSE;
+ else
+ splitBox(&boxVector, boxIdx, colorfreqtable, depth,
+ methodForLargest, methodForSplit);
+ }
+ *colormapP = colormapFromBv(newcolorCt, boxVector, colorfreqtable,
+ depth, methodForRep);
+
+ destroyBoxVector(boxVector);
+}
+
+
+
+
+static void
+validateCompatibleImage(struct pam * const inpamP,
+ struct pam * const firstPamP,
+ unsigned int const imageSeq) {
+
+ if (inpamP->depth != firstPamP->depth)
+ pm_error("Image %u depth (%u) is not the same as Image 0 (%u)",
+ imageSeq, inpamP->depth, firstPamP->depth);
+ if (inpamP->maxval != firstPamP->maxval)
+ pm_error("Image %u maxval (%u) is not the same as Image 0 (%u)",
+ imageSeq,
+ (unsigned)inpamP->maxval, (unsigned)firstPamP->maxval);
+ if (inpamP->format != firstPamP->format)
+ pm_error("Image %u format (%d) is not the same as Image 0 (%d)",
+ imageSeq, inpamP->format, firstPamP->format);
+ if (!streq(inpamP->tuple_type, firstPamP->tuple_type))
+ pm_error("Image %u tuple type (%s) is not the same as Image 0 (%s)",
+ imageSeq, inpamP->tuple_type, firstPamP->tuple_type);
+}
+
+
+
+static void
+addImageColorsToHash(struct pam * const pamP,
+ tuplehash const tuplehash,
+ unsigned int * const colorCountP) {
+
+ tuple * tuplerow;
+ unsigned int row;
+
+ tuplerow = pnm_allocpamrow(pamP);
+
+ for (row = 0; row < pamP->height; ++row) {
+ unsigned int col;
+
+ pnm_readpamrow(pamP, tuplerow);
+
+ for (col = 0; col < pamP->width; ++col) {
+ int firstOccurrence;
+
+ pnm_addtuplefreqoccurrence(pamP, tuplerow[col], tuplehash,
+ &firstOccurrence);
+
+ if (firstOccurrence)
+ ++(*colorCountP);
+ }
+ }
+ pnm_freepamrow(tuplerow);
+}
+
+
+
+static void
+computeHistogram(FILE * const ifP,
+ int * const formatP,
+ struct pam * const freqPamP,
+ tupletable2 * const colorfreqtableP) {
+/*----------------------------------------------------------------------------
+ Make a histogram of the colors in the image stream in the file '*ifP'.
+
+ Return as *freqPamP a description of the tuple values in the histogram.
+ Only the fields of *freqPamP that describe individual tuples are
+ meaningful (depth, maxval, tuple type);
+
+ As a fringe benefit, also return the format of the input file as
+ *formatP.
+----------------------------------------------------------------------------*/
+ unsigned int imageSeq;
+ struct pam firstPam;
+ tuplehash tuplehash;
+ unsigned int colorCount;
+ int eof;
+
+ pm_message("making histogram...");
+
+ tuplehash = pnm_createtuplehash();
+ colorCount = 0;
+
+ eof = FALSE;
+
+ for (imageSeq = 0; !eof; ++imageSeq) {
+ struct pam inpam;
+
+ pm_message("Scanning image %u", imageSeq);
+
+ pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
+
+ if (imageSeq == 0)
+ firstPam = inpam;
+ else
+ validateCompatibleImage(&inpam, &firstPam, imageSeq);
+
+ addImageColorsToHash(&inpam, tuplehash, &colorCount);
+
+ pm_message("%u colors so far", colorCount);
+
+ pnm_nextimage(ifP, &eof);
+ }
+ colorfreqtableP->table =
+ pnm_tuplehashtotable(&firstPam, tuplehash, colorCount);
+ colorfreqtableP->size = colorCount;
+
+ pnm_destroytuplehash(tuplehash);
+
+ pm_message("%u colors found", colorfreqtableP->size);
+
+ freqPamP->size = sizeof(*freqPamP);
+ freqPamP->len = PAM_STRUCT_SIZE(tuple_type);
+ freqPamP->maxval = firstPam.maxval;
+ freqPamP->bytes_per_sample = pnm_bytespersample(freqPamP->maxval);
+ freqPamP->depth = firstPam.depth;
+ STRSCPY(freqPamP->tuple_type, firstPam.tuple_type);
+
+ *formatP = firstPam.format;
+}
+
+
+
+static void
+computeColorMapFromInput(FILE * const ifP,
+ bool const allColors,
+ int const reqColors,
+ enum MethodForLargest const methodForLargest,
+ enum MethodForRep const methodForRep,
+ enum MethodForSplit const methodForSplit,
+ int * const formatP,
+ struct pam * const freqPamP,
+ tupletable2 * const colormapP) {
+/*----------------------------------------------------------------------------
+ Produce a colormap containing the best colors to represent the
+ image stream in file 'ifP'. Figure it out using the median cut
+ technique.
+
+ The colormap will have 'reqcolors' or fewer colors in it, unless
+ 'allcolors' is true, in which case it will have all the colors that
+ are in the input.
+
+ The colormap has the same maxval as the input.
+
+ Put the colormap in newly allocated storage as a tupletable2
+ and return its address as *colormapP. Return the number of colors in
+ it as *colorsP and its maxval as *colormapMaxvalP.
+
+ Return the characteristics of the input file as
+ *formatP and *freqPamP. (This information is not really
+ relevant to our colormap mission; just a fringe benefit).
+-----------------------------------------------------------------------------*/
+ tupletable2 colorfreqtable;
+
+ computeHistogram(ifP, formatP, freqPamP, &colorfreqtable);
+
+ if (allColors) {
+ *colormapP = colorfreqtable;
+ } else {
+ if (colorfreqtable.size <= reqColors) {
+ pm_message("Image already has few enough colors (<=%d). "
+ "Keeping same colors.", reqColors);
+ *colormapP = colorfreqtable;
+ } else {
+ pm_message("choosing %d colors...", reqColors);
+ mediancut(colorfreqtable, freqPamP->depth,
+ reqColors, methodForLargest, methodForRep,
+ methodForSplit, colormapP);
+ pnm_freetupletable2(freqPamP, colorfreqtable);
+ }
+ }
+}
+
+
+
+static void
+sortColormap(tupletable2 const colormap,
+ sample const depth) {
+/*----------------------------------------------------------------------------
+ Sort the colormap in place, in order of ascending Plane 0 value,
+ the Plane 1 value, etc.
+
+ Use insertion sort.
+-----------------------------------------------------------------------------*/
+ int i;
+
+ pm_message("Sorting %u colors...", colormap.size);
+
+ for (i = 0; i < colormap.size; ++i) {
+ int j;
+ for (j = i+1; j < colormap.size; ++j) {
+ unsigned int plane;
+ bool iIsGreater, iIsLess;
+
+ iIsGreater = FALSE; iIsLess = FALSE;
+ for (plane = 0;
+ plane < depth && !iIsGreater && !iIsLess;
+ ++plane) {
+ if (colormap.table[i]->tuple[plane] >
+ colormap.table[j]->tuple[plane])
+ iIsGreater = TRUE;
+ else if (colormap.table[i]->tuple[plane] <
+ colormap.table[j]->tuple[plane])
+ iIsLess = TRUE;
+ }
+ if (iIsGreater) {
+ for (plane = 0; plane < depth; ++plane) {
+ sample const temp = colormap.table[i]->tuple[plane];
+ colormap.table[i]->tuple[plane] =
+ colormap.table[j]->tuple[plane];
+ colormap.table[j]->tuple[plane] = temp;
+ }
+ }
+ }
+ }
+}
+
+
+
+static void
+colormapToSquare(struct pam * const pamP,
+ tupletable2 const colormap,
+ tuple *** const outputRasterP) {
+ {
+ unsigned int const intsqrt = (int)sqrt((float)colormap.size);
+ if (SQR(intsqrt) == colormap.size)
+ pamP->width = intsqrt;
+ else
+ pamP->width = intsqrt + 1;
+ }
+ {
+ unsigned int const intQuotient = colormap.size / pamP->width;
+ if (pamP->width * intQuotient == colormap.size)
+ pamP->height = intQuotient;
+ else
+ pamP->height = intQuotient + 1;
+ }
+ {
+ tuple ** outputRaster;
+ unsigned int row;
+ unsigned int colormapIndex;
+
+ outputRaster = pnm_allocpamarray(pamP);
+
+ colormapIndex = 0; /* initial value */
+
+ for (row = 0; row < pamP->height; ++row) {
+ unsigned int col;
+ for (col = 0; col < pamP->width; ++col) {
+ unsigned int plane;
+ for (plane = 0; plane < pamP->depth; ++plane) {
+ outputRaster[row][col][plane] =
+ colormap.table[colormapIndex]->tuple[plane];
+ }
+ if (colormapIndex < colormap.size-1)
+ ++colormapIndex;
+ }
+ }
+ *outputRasterP = outputRaster;
+ }
+}
+
+
+
+static void
+colormapToSingleRow(struct pam * const pamP,
+ tupletable2 const colormap,
+ tuple *** const outputRasterP) {
+
+ tuple ** outputRaster;
+ unsigned int col;
+
+ pamP->width = colormap.size;
+ pamP->height = 1;
+
+ outputRaster = pnm_allocpamarray(pamP);
+
+ for (col = 0; col < pamP->width; ++col) {
+ int plane;
+ for (plane = 0; plane < pamP->depth; ++plane)
+ outputRaster[0][col][plane] = colormap.table[col]->tuple[plane];
+ }
+ *outputRasterP = outputRaster;
+}
+
+
+
+static void
+colormapToImage(int const format,
+ const struct pam * const colormapPamP,
+ tupletable2 const colormap,
+ bool const sort,
+ bool const square,
+ struct pam * const outpamP,
+ tuple *** const outputRasterP) {
+/*----------------------------------------------------------------------------
+ Create a tuple array and pam structure for an image which includes
+ one pixel of each of the colors in the colormap 'colormap'.
+
+ May rearrange the contents of 'colormap'.
+-----------------------------------------------------------------------------*/
+ outpamP->size = sizeof(*outpamP);
+ outpamP->len = PAM_STRUCT_SIZE(tuple_type);
+ outpamP->format = format,
+ outpamP->plainformat = FALSE;
+ outpamP->depth = colormapPamP->depth;
+ outpamP->maxval = colormapPamP->maxval;
+ outpamP->bytes_per_sample = pnm_bytespersample(outpamP->maxval);
+ STRSCPY(outpamP->tuple_type, colormapPamP->tuple_type);
+
+ if (sort)
+ sortColormap(colormap, outpamP->depth);
+
+ if (square)
+ colormapToSquare(outpamP, colormap, outputRasterP);
+ else
+ colormapToSingleRow(outpamP, colormap, outputRasterP);
+}
+
+
+
+int
+main(int argc, const char * argv[] ) {
+
+ struct CmdlineInfo cmdline;
+ FILE * ifP;
+ int format;
+ struct pam colormapPam;
+ struct pam outpam;
+ tuple ** colormapRaster;
+ tupletable2 colormap;
+
+ pm_proginit(&argc, argv);
+
+ parseCommandLine(argc, argv, &cmdline);
+
+ ifP = pm_openr(cmdline.inputFileNm);
+
+ computeColorMapFromInput(ifP,
+ cmdline.allcolors, cmdline.newcolors,
+ cmdline.methodForLargest,
+ cmdline.methodForRep,
+ cmdline.methodForSplit,
+ &format, &colormapPam, &colormap);
+
+ pm_close(ifP);
+
+ colormapToImage(format, &colormapPam, colormap,
+ cmdline.sort, cmdline.square, &outpam, &colormapRaster);
+
+ if (cmdline.verbose)
+ pm_message("Generating %u x %u image", outpam.width, outpam.height);
+
+ outpam.file = stdout;
+
+ pnm_writepam(&outpam, colormapRaster);
+
+ pnm_freetupletable2(&colormapPam, colormap);
+
+ pnm_freepamarray(colormapRaster, &outpam);
+
+ pm_close(stdout);
+
+ return 0;
+}
+
+
+
diff --git a/urt/Runput.c b/urt/Runput.c
index 3bc562a..645a376 100644
--- a/urt/Runput.c
+++ b/urt/Runput.c
@@ -202,10 +202,11 @@ RunSetup(rle_hdr * the_hdr)
if ( the_hdr->background != 0 )
{
register int i;
- register rle_pixel *background =
- (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
- register int *bg_color;
- /*
+ register rle_pixel *background;
+ register int *bg_color;
+
+ overflow_add(the_hdr->ncolors,1);
+ background = (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) ); /*
* If even number of bg color bytes, put out one more to get to
* 16 bit boundary.
*/
@@ -224,7 +225,7 @@ RunSetup(rle_hdr * the_hdr)
/* Big-endian machines are harder */
register int i, nmap = (1 << the_hdr->cmaplen) *
the_hdr->ncmap;
- register char *h_cmap = (char *)malloc( nmap * 2 );
+ register char *h_cmap = (char *)malloc2( nmap, 2 );
if ( h_cmap == NULL )
{
fprintf( stderr,
diff --git a/urt/rle.h b/urt/rle.h
index 0071774..6a905ba 100644
--- a/urt/rle.h
+++ b/urt/rle.h
@@ -152,6 +152,17 @@ rle_hdr /* End of typedef. */
*/
extern rle_hdr rle_dflt_hdr;
+/*
+ * Provided by pm library
+ */
+
+extern void overflow_add(int, int);
+#define overflow2(a,b) __overflow2(a,b)
+extern void __overflow2(int, int);
+extern void overflow3(int, int, int);
+extern void *malloc2(int, int);
+extern void *malloc3(int, int, int);
+extern void *realloc2(void *, int, int);
/* Declare RLE library routines. */
diff --git a/urt/rle.h.orig b/urt/rle.h.orig
new file mode 100644
index 0000000..59d2670
--- /dev/null
+++ b/urt/rle.h.orig
@@ -0,0 +1,470 @@
+/*
+ * This software is copyrighted as noted below. It may be freely copied,
+ * modified, and redistributed, provided that the copyright notice is
+ * preserved on all copies.
+ *
+ * There is no warranty or other guarantee of fitness for this software,
+ * it is provided solely "as is". Bug reports or fixes may be sent
+ * to the author, who may or may not act on them as he desires.
+ *
+ * You may not include this software in a program or other software product
+ * without supplying the source, or without informing the end-user that the
+ * source is available for no extra charge.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ */
+/*
+ * rle.h - Global declarations for Utah Raster Toolkit RLE programs.
+ *
+ * Author: Todd W. Fuqua
+ * Computer Science Dept.
+ * University of Utah
+ * Date: Sun Jul 29 1984
+ * Copyright (c) 1984 Todd W. Fuqua
+ *
+ * $Id: rle.h,v 3.0.1.5 1992/04/30 14:05:56 spencer Exp $
+ */
+
+#ifndef RLE_H
+#define RLE_H
+
+#include <stdio.h> /* Declare FILE. */
+#include <string.h>
+
+enum rle_dispatch {
+ NO_DISPATCH = -1,
+ RUN_DISPATCH = 0
+};
+
+/* ****************************************************************
+ * TAG( rle_pixel rle_map )
+ *
+ * Typedef for 8-bit (or less) pixel data.
+ *
+ * Typedef for 16-bit color map data.
+ */
+typedef unsigned char rle_pixel;
+typedef unsigned short rle_map;
+
+/*
+ * Defines for traditional channel numbers.
+ */
+#define RLE_RED 0 /* Red channel traditionally here. */
+#define RLE_GREEN 1 /* Green channel traditionally here. */
+#define RLE_BLUE 2 /* Blue channel traditionally here. */
+#define RLE_ALPHA -1 /* Alpha channel here. */
+
+/*
+ * Return values from rle_get_setup.
+ */
+#define RLE_SUCCESS 0
+#define RLE_NOT_RLE -1
+#define RLE_NO_SPACE -2
+#define RLE_EMPTY -3
+#define RLE_EOF -4
+
+/*
+ * "Magic" value for is_init field. Pi * 2^29.
+ */
+#define RLE_INIT_MAGIC 0x6487ED51L
+
+/*
+ * TAG( rle_hdr )
+ *
+ * Definition of header structure used by RLE routines.
+ */
+
+#ifndef c_plusplus
+typedef
+#endif
+ struct rle_hdr {
+ enum rle_dispatch dispatch; /* Type of file to create. */
+ int ncolors; /* Number of color channels. */
+ int * bg_color; /* Pointer to bg color vector. */
+ int alpha; /* If !0, save alpha channel. */
+ int background; /* 0->just save all pixels, */
+ /* 1->overlay, 2->clear to bg first. */
+ int xmin; /* Lower X bound (left.) */
+ int xmax; /* Upper X bound (right.) */
+ int ymin; /* Lower Y bound (bottom.) */
+ int ymax; /* Upper Y bound (top.) */
+ int ncmap; /* Number of color channels in color map. */
+ /* Map only saved if != 0. */
+ int cmaplen; /* Log2 of color map length. */
+ rle_map * cmap; /* Pointer to color map array. */
+ const char ** comments; /* Pointer to array of pointers to comments. */
+ FILE * rle_file; /* Input or output file. */
+ /*
+ * Bit map of channels to read/save. Indexed by (channel mod 256).
+ * Alpha channel sets bit 255.
+ *
+ * Indexing (0 <= c <= 255):
+ * bits[c/8] & (1 << (c%8))
+ */
+#define RLE_SET_BIT(glob,bit) \
+ ((glob).bits[((bit)&0xff)/8] |= (1<<((bit)&0x7)))
+#define RLE_CLR_BIT(glob,bit) \
+ ((glob).bits[((bit)&0xff)/8] &= ~(1<<((bit)&0x7)))
+#define RLE_BIT(glob,bit) \
+ ((glob).bits[((bit)&0xff)/8] & (1<<((bit)&0x7)))
+ char bits[256/8];
+ /* Set to magic pattern if following fields are initialized. */
+ /* This gives a 2^(-32) chance of missing. */
+ long int is_init;
+ /* Command, file name and image number for error messages. */
+ const char *cmd;
+ const char *file_name;
+ int img_num;
+ /*
+ * Local storage for rle_getrow & rle_putrow.
+ * rle_getrow has
+ * scan_y int current Y scanline.
+ * vert_skip int number of lines to skip.
+ * rle_putrow has
+ * nblank int number of blank lines.
+ * brun short(*)[2] Array of background runs.
+ * fileptr long Position in output file.
+ */
+ union {
+ struct {
+ int scan_y,
+ vert_skip;
+ char is_eof, /* Set when EOF or EofOp encountered. */
+ is_seek; /* If true, can seek input file. */
+ } get;
+ struct {
+ int nblank;
+ short (*brun)[2];
+ long fileptr;
+ } put;
+ } priv;
+ }
+#ifndef c_plusplus
+rle_hdr /* End of typedef. */
+#endif
+;
+
+/*
+ * TAG( rle_dflt_hdr )
+ *
+ * Global variable with possibly useful default values.
+ */
+extern rle_hdr rle_dflt_hdr;
+
+
+/* Declare RLE library routines. */
+
+/*****************************************************************
+ * TAG( rle_get_error )
+ *
+ * Print an error message based on the error code returned by
+ * rle_get_setup.
+ */
+extern int rle_get_error( int code,
+ const char *pgmname,
+ const char *fname );
+
+/* From rle_getrow.c */
+
+/*****************************************************************
+ * TAG( rle_debug )
+ *
+ * Turn RLE debugging on or off.
+ */
+extern void rle_debug( int on_off );
+
+int
+rle_get_setup(rle_hdr * const the_hdr);
+
+/*****************************************************************
+ * TAG( rle_get_setup_ok )
+ *
+ * Call rle_get_setup. If it returns an error code, call
+ * rle_get_error to print the error message, then exit with the error
+ * code.
+ */
+extern void rle_get_setup_ok( rle_hdr *the_hdr,
+ const char *prog_name,
+ const char *file_name);
+
+/*****************************************************************
+ * TAG( rle_getrow )
+ *
+ * Read a scanline worth of data from an RLE file.
+ */
+extern int rle_getrow( rle_hdr * the_hdr,
+ rle_pixel * scanline[] );
+
+/* From rle_getskip.c */
+
+/*****************************************************************
+ * TAG( rle_getskip )
+ * Skip a scanline, return the number of the next one.
+ */
+extern unsigned int rle_getskip( rle_hdr *the_hdr );
+
+/* From rle_hdr.c. */
+
+/*****************************************************************
+ * TAG( rle_names )
+ *
+ * Load the command and file names into the rle_hdr.
+ */
+extern void rle_names( rle_hdr *the_hdr,
+ const char *pgmname,
+ const char *fname,
+ int img_num );
+
+/*****************************************************************
+ * TAG( rle_hdr_cp )
+ *
+ * Make a "safe" copy of a rle_hdr structure.
+ */
+extern rle_hdr * rle_hdr_cp( rle_hdr *from_hdr,
+ rle_hdr *to_hdr );
+
+/*****************************************************************
+ * TAG( rle_hdr_init )
+ *
+ * Initialize a rle_hdr structure.
+ */
+extern rle_hdr * rle_hdr_init( rle_hdr *the_hdr );
+
+/*****************************************************************
+ * TAG( rle_hdr_clear )
+ *
+ */
+extern void rle_hdr_clear( rle_hdr *the_hdr );
+
+/* From rle_putrow.c. */
+
+/*****************************************************************
+ * TAG( rgb_to_bw )
+ *
+ * Converts RGB data to gray data via the NTSC Y transform.
+ */
+extern void rgb_to_bw( rle_pixel *red_row,
+ rle_pixel *green_row,
+ rle_pixel *blue_row,
+ rle_pixel *bw_row,
+ int rowlen );
+
+/*****************************************************************
+ * TAG( rle_puteof )
+ *
+ * Write an End-of-image opcode to the RLE file.
+ */
+extern void rle_puteof( rle_hdr *the_hdr );
+
+/*****************************************************************
+ * TAG( rle_putrow )
+ *
+ * Write a scanline of data to the RLE file.
+ */
+extern void rle_putrow( rle_pixel *rows[], int rowlen, rle_hdr *the_hdr );
+
+/*****************************************************************
+ * TAG( rle_put_init )
+ *
+ * Initialize header for output, but don't write it to the file.
+ */
+extern void rle_put_init( rle_hdr * the_hdr );
+
+/*****************************************************************
+ * TAG( rle_put_setup )
+ *
+ * Write header information to a new RLE image file.
+ */
+extern void rle_put_setup( rle_hdr * the_hdr );
+
+/*****************************************************************
+ * TAG( rle_skiprow )
+ *
+ * Skip nrow scanlines in the output file.
+ */
+extern void rle_skiprow( rle_hdr *the_hdr, int nrow );
+
+/* From rle_cp.c */
+/*****************************************************************
+ * TAG( rle_cp )
+ * Copy image data from input to output with minimal interpretation.
+ */
+extern void rle_cp( rle_hdr *in_hdr, rle_hdr *out_hdr );
+
+/* From rle_row_alc.c. */
+/*****************************************************************
+ * TAG( rle_row_alloc )
+ *
+ * Allocate scanline memory for use by rle_getrow.
+ */
+extern int rle_row_alloc( rle_hdr * the_hdr,
+ rle_pixel *** scanp );
+
+/*****************************************************************
+ * TAG( rle_row_free )
+ *
+ * Free the above.
+ */
+extern void rle_row_free( rle_hdr *the_hdr, rle_pixel **scanp );
+
+/* From buildmap.c. */
+/*
+ * buildmap - build a more usable colormap from data in the_hdr struct.
+ */
+extern rle_pixel **buildmap( rle_hdr *the_hdr,
+ int minmap,
+ double orig_gamma,
+ double new_gamma );
+
+/* From rle_getcom.c. */
+/*****************************************************************
+ * TAG( rle_getcom )
+ *
+ * Get a specific comment from the image comments.
+ */
+const char *
+rle_getcom(const char * const name,
+ rle_hdr * const the_hdr);
+
+/* From rle_putcom.c. */
+
+/* Delete a specific comment from the image comments. */
+const char *
+rle_delcom(const char * const name,
+ rle_hdr * const the_hdr);
+
+/* Put (or replace) a comment into the image comments. */
+const char *
+rle_putcom(const char * const value,
+ rle_hdr * const the_hdr);
+
+/* From dither.c. */
+/*****************************************************************
+ * TAG( bwdithermap )
+ * Create a color map for ordered dithering in grays.
+ */
+extern void bwdithermap( int levels, double gamma, int bwmap[],
+ int divN[256], int modN[256], int magic[16][16] );
+/*****************************************************************
+ * TAG( ditherbw )
+ * Dither a gray-scale value.
+ */
+extern int ditherbw( int x, int y, int val,
+ int divN[256], int modN[256], int magic[16][16] );
+/*****************************************************************
+ * TAG( dithergb )
+ * Dither a color value.
+ */
+extern int dithergb( int x, int y, int r, int g, int b,
+ int divN[256], int modN[256], int magic[16][16] );
+/*****************************************************************
+ * TAG( dithermap )
+ * Create a color map for ordered dithering in color.
+ */
+extern void dithermap( int levels, double gamma, int rgbmap[][3],
+ int divN[256], int modN[256], int magic[16][16] );
+/*****************************************************************
+ * TAG( make_square )
+ * Make a 16x16 magic square for ordered dithering.
+ */
+extern void make_square( double N, int divN[256], int modN[256],
+ int magic[16][16] );
+
+/* From float_to_exp.c. */
+/*****************************************************************
+ * TAG( float_to_exp )
+ * Convert a list of floating point numbers to "exp" format.
+ */
+extern void float_to_exp( int count, float * floats, rle_pixel * pixels );
+
+/* From rle_open_f.c. */
+/*****************************************************************
+ * TAG( rle_open_f )
+ *
+ * Open an input/output file with default.
+ */
+FILE *
+rle_open_f(const char * prog_name, const char * file_name,
+ const char * mode);
+
+/*****************************************************************
+ * TAG( rle_open_f_noexit )
+ *
+ * Open an input/output file with default.
+ */
+FILE *
+rle_open_f_noexit(const char * const prog_name,
+ const char * const file_name,
+ const char * const mode);
+
+/*****************************************************************
+ * TAG( rle_close_f )
+ *
+ * Close a file opened by rle_open_f. If the file is stdin or stdout,
+ * it will not be closed.
+ */
+extern void
+rle_close_f( FILE *fd );
+
+/* From colorquant.c. */
+/*****************************************************************
+ * TAG( colorquant )
+ * Compute a colormap for quantizing an image to a limited set of colors.
+ */
+extern int colorquant( rle_pixel *red, rle_pixel *green, rle_pixel *blue,
+ unsigned long pixels, rle_pixel *colormap[3],
+ int colors, int bits,
+ rle_pixel *rgbmap, int fast, int otherimages );
+
+/* From rle_addhist.c. */
+
+/* Append history information to the HISTORY comment. */
+void
+rle_addhist(char * argv[],
+ rle_hdr * const in_hdr,
+ rle_hdr * const out_hdr);
+
+/* From cmd_name.c. */
+/*****************************************************************
+ * TAG( cmd_name )
+ * Extract command name from argv.
+ */
+extern char *cmd_name( char **argv );
+
+/* From scanargs.c. */
+/*****************************************************************
+ * TAG( scanargs )
+ * Scan command argument list and parse arguments.
+ */
+extern int scanargs( int argc,
+ char **argv,
+ const char *format,
+ ... );
+
+/* From hilbert.c */
+/*****************************************************************
+ * TAG( hilbert_i2c )
+ * Convert an index into a Hilbert curve to a set of coordinates.
+ */
+extern void hilbert_c2i( int n, int m, int a[], long int *r );
+
+/*****************************************************************
+ * TAG( hilbert_c2i )
+ * Convert coordinates of a point on a Hilbert curve to its index.
+ */
+extern void hilbert_i2c( int n, int m, long int r, int a[] );
+
+/* From inv_cmap.c */
+/*****************************************************************
+ * TAG( inv_cmap )
+ * Compute an inverse colormap efficiently.
+ */
+extern void inv_cmap( int colors,
+ unsigned char *colormap[3],
+ int bits,
+ unsigned long *dist_buf,
+ unsigned char *rgbmap );
+
+#endif /* RLE_H */
diff --git a/urt/rle_addhist.c b/urt/rle_addhist.c
index b165175..e09ed94 100644
--- a/urt/rle_addhist.c
+++ b/urt/rle_addhist.c
@@ -70,13 +70,18 @@ rle_addhist(char * argv[],
return;
length = 0;
- for (i = 0; argv[i]; ++i)
+ for (i = 0; argv[i]; ++i) {
+ overflow_add(length, strlen(argv[i]));
+ overflow_add(length+1, strlen(argv[i]));
length += strlen(argv[i]) +1; /* length of each arg plus space. */
+ }
time(&temp);
timedate = ctime(&temp);
length += strlen(timedate); /* length of date and time in ASCII. */
-
+ overflow_add(strlen(padding), 4);
+ overflow_add(strlen(histoire), strlen(padding) + 4);
+ overflow_add(length, strlen(histoire) + strlen(padding) + 4);
length += strlen(padding) + 3 + strlen(histoire) + 1;
/* length of padding, "on " and length of history name plus "="*/
if (in_hdr) /* if we are interested in the old comments... */
@@ -84,8 +89,10 @@ rle_addhist(char * argv[],
else
old = NULL;
- if (old && *old)
+ if (old && *old) {
+ overflow_add(length, strlen(old));
length += strlen(old); /* add length if there. */
+ }
++length; /*Cater for the null. */
diff --git a/urt/rle_getrow.c b/urt/rle_getrow.c
index ae220f5..39010ba 100644
--- a/urt/rle_getrow.c
+++ b/urt/rle_getrow.c
@@ -164,6 +164,7 @@ rle_get_setup(rle_hdr * const the_hdr) {
char * cp;
VAXSHORT(comlen, infile); /* get comment length */
+ overflow_add(comlen, 1);
evenlen = (comlen + 1) & ~1; /* make it even */
if (evenlen) {
MALLOCARRAY(comment_buf, evenlen);
diff --git a/urt/rle_getrow.c.orig b/urt/rle_getrow.c.orig
new file mode 100644
index 0000000..ae220f5
--- /dev/null
+++ b/urt/rle_getrow.c.orig
@@ -0,0 +1,520 @@
+/*
+ * This software is copyrighted as noted below. It may be freely copied,
+ * modified, and redistributed, provided that the copyright notice is
+ * preserved on all copies.
+ *
+ * There is no warranty or other guarantee of fitness for this software,
+ * it is provided solely "as is". Bug reports or fixes may be sent
+ * to the author, who may or may not act on them as he desires.
+ *
+ * You may not include this software in a program or other software product
+ * without supplying the source, or without informing the end-user that the
+ * source is available for no extra charge.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
+ * to have all "void" functions so declared.
+ */
+/*
+ * rle_getrow.c - Read an RLE file in.
+ *
+ * Author: Spencer W. Thomas
+ * Computer Science Dept.
+ * University of Utah
+ * Date: Wed Apr 10 1985
+ * Copyright (c) 1985 Spencer W. Thomas
+ *
+ * $Id: rle_getrow.c,v 3.0.1.5 1992/03/04 19:33:08 spencer Exp spencer $
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "netpbm/pm.h"
+#include "netpbm/mallocvar.h"
+
+#include "rle.h"
+#include "rle_code.h"
+#include "vaxshort.h"
+
+/* Read a two-byte "short" that started in VAX (LITTLE_ENDIAN) order */
+#define VAXSHORT( var, fp )\
+ { var = fgetc(fp)&0xFF; var |= (fgetc(fp)) << 8; }
+
+/* Instruction format -- first byte is opcode, second is datum. */
+
+#define OPCODE(inst) (inst[0] & ~LONG)
+#define LONGP(inst) (inst[0] & LONG)
+#define DATUM(inst) (inst[1] & 0xff) /* Make sure it's unsigned. */
+
+static int debug_f; /* If non-zero, print debug info. */
+
+int
+rle_get_setup(rle_hdr * const the_hdr) {
+/*-----------------------------------------------------------------------------
+ Read the initialization information from an RLE file.
+ Inputs:
+ the_hdr: Contains pointer to the input file.
+ Outputs:
+ the_hdr: Initialized with information from the input file.
+ Returns
+ 0 on success,
+ -1 if the file is not an RLE file,
+ -2 if malloc of the color map failed,
+ -3 if an immediate EOF is hit (empty input file)
+ -4 if an EOF is encountered reading the setup information.
+ Assumptions:
+ infile points to the "magic" number in an RLE file (usually byte 0
+ in the file).
+ Algorithm:
+ Read in the setup info and fill in the_hdr.
+---------------------------------------------------------------------------- */
+ struct XtndRsetup setup;
+ short magic;
+ FILE * infile = the_hdr->rle_file;
+ int i;
+ char * comment_buf;
+
+ /* Clear old stuff out of the header. */
+ rle_hdr_clear(the_hdr);
+ if (the_hdr->is_init != RLE_INIT_MAGIC)
+ rle_names(the_hdr, "Urt", "some file", 0);
+ ++the_hdr->img_num; /* Count images. */
+
+ VAXSHORT(magic, infile);
+ if (feof(infile))
+ return RLE_EMPTY;
+ if (magic != RLE_MAGIC)
+ return RLE_NOT_RLE;
+ fread(&setup, 1, SETUPSIZE, infile); /* assume VAX packing */
+ if (feof( infile))
+ return RLE_EOF;
+
+ /* Extract information from setup */
+ the_hdr->ncolors = setup.h_ncolors;
+ for (i = 0; i < the_hdr->ncolors; ++i)
+ RLE_SET_BIT(*the_hdr, i);
+
+ if (!(setup.h_flags & H_NO_BACKGROUND) && setup.h_ncolors > 0) {
+ rle_pixel * bg_color;
+
+ MALLOCARRAY(the_hdr->bg_color, setup.h_ncolors);
+ if (!the_hdr->bg_color)
+ pm_error("Failed to allocation array for %u background colors",
+ setup.h_ncolors);
+ MALLOCARRAY(bg_color, 1 + (setup.h_ncolors / 2) * 2);
+ if (!bg_color)
+ pm_error("Failed to allocation array for %u background colors",
+ 1+(setup.h_ncolors / 2) * 2);
+ fread((char *)bg_color, 1, 1 + (setup.h_ncolors / 2) * 2, infile);
+ for (i = 0; i < setup.h_ncolors; ++i)
+ the_hdr->bg_color[i] = bg_color[i];
+ free(bg_color);
+ } else {
+ getc(infile); /* skip filler byte */
+ the_hdr->bg_color = NULL;
+ }
+
+ if (setup.h_flags & H_NO_BACKGROUND)
+ the_hdr->background = 0;
+ else if (setup.h_flags & H_CLEARFIRST)
+ the_hdr->background = 2;
+ else
+ the_hdr->background = 1;
+ if (setup.h_flags & H_ALPHA) {
+ the_hdr->alpha = 1;
+ RLE_SET_BIT( *the_hdr, RLE_ALPHA );
+ } else
+ the_hdr->alpha = 0;
+
+ the_hdr->xmin = vax_gshort(setup.hc_xpos);
+ the_hdr->ymin = vax_gshort(setup.hc_ypos);
+ the_hdr->xmax = the_hdr->xmin + vax_gshort(setup.hc_xlen) - 1;
+ the_hdr->ymax = the_hdr->ymin + vax_gshort(setup.hc_ylen) - 1;
+
+ the_hdr->ncmap = setup.h_ncmap;
+ the_hdr->cmaplen = setup.h_cmaplen;
+ if (the_hdr->ncmap > 0) {
+ int const maplen = the_hdr->ncmap * (1 << the_hdr->cmaplen);
+
+ int i;
+ char *maptemp;
+
+ MALLOCARRAY(the_hdr->cmap, maplen);
+ MALLOCARRAY(maptemp, 2 * maplen);
+ if (the_hdr->cmap == NULL || maptemp == NULL) {
+ pm_error("Malloc failed for color map of size %d*%d "
+ "in rle_get_setup, reading '%s'",
+ the_hdr->ncmap, (1 << the_hdr->cmaplen),
+ the_hdr->file_name );
+ return RLE_NO_SPACE;
+ }
+ fread(maptemp, 2, maplen, infile);
+ for (i = 0; i < maplen; ++i)
+ the_hdr->cmap[i] = vax_gshort(&maptemp[i * 2]);
+ free(maptemp);
+ }
+
+ /* Check for comments */
+ if (setup.h_flags & H_COMMENT) {
+ short comlen, evenlen;
+ char * cp;
+
+ VAXSHORT(comlen, infile); /* get comment length */
+ evenlen = (comlen + 1) & ~1; /* make it even */
+ if (evenlen) {
+ MALLOCARRAY(comment_buf, evenlen);
+
+ if (comment_buf == NULL) {
+ pm_error("Malloc failed for comment buffer of size %d "
+ "in rle_get_setup, reading '%s'",
+ comlen, the_hdr->file_name );
+ return RLE_NO_SPACE;
+ }
+ fread(comment_buf, 1, evenlen, infile);
+ /* Count the comments */
+ for (i = 0, cp = comment_buf; cp < comment_buf + comlen; ++cp)
+ if (*cp == '\0')
+ ++i;
+ ++i; /* extra for NULL pointer at end */
+ /* Get space to put pointers to comments */
+ MALLOCARRAY(the_hdr->comments, i);
+ if (the_hdr->comments == NULL) {
+ pm_error("Malloc failed for %d comment pointers "
+ "in rle_get_setup, reading '%s'",
+ i, the_hdr->file_name );
+ return RLE_NO_SPACE;
+ }
+ /* Get pointers to the comments */
+ *the_hdr->comments = comment_buf;
+ for (i = 1, cp = comment_buf + 1;
+ cp < comment_buf + comlen;
+ ++cp)
+ if (*(cp - 1) == '\0')
+ the_hdr->comments[i++] = cp;
+ the_hdr->comments[i] = NULL;
+ } else
+ the_hdr->comments = NULL;
+ } else
+ the_hdr->comments = NULL;
+
+ /* Initialize state for rle_getrow */
+ the_hdr->priv.get.scan_y = the_hdr->ymin;
+ the_hdr->priv.get.vert_skip = 0;
+ the_hdr->priv.get.is_eof = 0;
+ the_hdr->priv.get.is_seek = ftell(infile) > 0;
+ debug_f = 0;
+
+ if (!feof(infile))
+ return RLE_SUCCESS; /* success! */
+ else {
+ the_hdr->priv.get.is_eof = 1;
+ return RLE_EOF;
+ }
+}
+
+
+
+void
+rle_get_setup_ok(rle_hdr * const the_hdr,
+ const char * const prog_name,
+ const char * const file_name) {
+/*-----------------------------------------------------------------------------
+ Read the initialization information from an RLE file.
+
+ Inputs:
+ the_hdr: Contains pointer to the input file.
+ prog_name: Program name to be printed in the error message.
+ file_name: File name to be printed in the error message.
+ If NULL, the string "stdin" is generated.
+
+ Outputs:
+ the_hdr: Initialized with information from the input file.
+ If reading the header fails, it prints an error message
+ and exits with the appropriate status code.
+ Algorithm:
+ rle_get_setup does all the work.
+---------------------------------------------------------------------------- */
+ int code;
+
+ /* Backwards compatibility: if is_init is not properly set,
+ * initialize the header.
+ */
+ if (the_hdr->is_init != RLE_INIT_MAGIC) {
+ FILE * const f = the_hdr->rle_file;
+ rle_hdr_init( the_hdr );
+ the_hdr->rle_file = f;
+ rle_names(the_hdr, prog_name, file_name, 0);
+ }
+
+ code = rle_get_error(rle_get_setup(the_hdr),
+ the_hdr->cmd, the_hdr->file_name);
+ if (code)
+ exit(code);
+}
+
+
+
+void
+rle_debug( on_off )
+ int on_off;
+{
+/*-----------------------------------------------------------------------------
+ Turn RLE debugging on or off.
+ Inputs:
+ on_off: if 0, stop debugging, else start.
+ Outputs:
+ Sets internal debug flag.
+ Assumptions:
+ [None]
+ Algorithm:
+ [None]
+---------------------------------------------------------------------------- */
+ debug_f = on_off;
+
+ /* Set line buffering on stderr. Character buffering is the default, and
+ * it is SLOOWWW for large amounts of output.
+ */
+ setvbuf(stderr, NULL, _IOLBF, 0);
+}
+
+
+
+int
+rle_getrow(rle_hdr * const the_hdr,
+ rle_pixel ** const scanline) {
+/*-----------------------------------------------------------------------------
+ Get a scanline from the input file.
+ Inputs:
+ the_hdr: Header structure containing information about
+ the input file.
+ Outputs:
+ scanline: an array of pointers to the individual color
+ scanlines. Scanline is assumed to have
+ the_hdr->ncolors pointers to arrays of rle_pixel,
+ each of which is at least the_hdr->xmax+1 long.
+ Returns the current scanline number.
+ Assumptions:
+ rle_get_setup has already been called.
+ Algorithm:
+ If a vertical skip is being executed, and clear-to-background is
+ specified (the_hdr->background is true), just set the
+ scanlines to the background color. If clear-to-background is
+ not set, just increment the scanline number and return.
+
+ Otherwise, read input until a vertical skip is encountered,
+ decoding the instructions into scanline data.
+
+ If ymax is reached (or, somehow, passed), continue reading and
+ discarding input until end of image.
+---------------------------------------------------------------------------- */
+ FILE * const infile = the_hdr->rle_file;
+
+ rle_pixel * scanc;
+
+ int scan_x; /* current X position */
+ int max_x; /* End of the scanline */
+ int channel; /* current color channel */
+ int ns; /* Number to skip */
+ int nc;
+ short word, long_data;
+ char inst[2];
+
+ scan_x = the_hdr->xmin; /* initial value */
+ max_x = the_hdr->xmax; /* initial value */
+ channel = 0; /* initial value */
+ /* Clear to background if specified */
+ if (the_hdr->background != 1) {
+ if (the_hdr->alpha && RLE_BIT( *the_hdr, -1))
+ memset((char *)scanline[-1] + the_hdr->xmin, 0,
+ the_hdr->xmax - the_hdr->xmin + 1);
+ for (nc = 0; nc < the_hdr->ncolors; ++nc) {
+ if (RLE_BIT( *the_hdr, nc)) {
+ /* Unless bg color given explicitly, use 0. */
+ if (the_hdr->background != 2 || the_hdr->bg_color[nc] == 0)
+ memset((char *)scanline[nc] + the_hdr->xmin, 0,
+ the_hdr->xmax - the_hdr->xmin + 1);
+ else
+ memset((char *)scanline[nc] + the_hdr->xmin,
+ the_hdr->bg_color[nc],
+ the_hdr->xmax - the_hdr->xmin + 1);
+ }
+ }
+ }
+
+ /* If skipping, then just return */
+ if (the_hdr->priv.get.vert_skip > 0) {
+ --the_hdr->priv.get.vert_skip;
+ ++the_hdr->priv.get.scan_y;
+ if (the_hdr->priv.get.vert_skip > 0) {
+ if (the_hdr->priv.get.scan_y >= the_hdr->ymax) {
+ int const y = the_hdr->priv.get.scan_y;
+ while (rle_getskip(the_hdr) != 32768)
+ ;
+ return y;
+ } else
+ return the_hdr->priv.get.scan_y;
+ }
+ }
+
+ /* If EOF has been encountered, return also */
+ if (the_hdr->priv.get.is_eof)
+ return ++the_hdr->priv.get.scan_y;
+
+ /* Otherwise, read and interpret instructions until a skipLines
+ instruction is encountered.
+ */
+ if (RLE_BIT(*the_hdr, channel))
+ scanc = scanline[channel] + scan_x;
+ else
+ scanc = NULL;
+ for (;;) {
+ inst[0] = getc(infile);
+ inst[1] = getc(infile);
+ if (feof(infile)) {
+ the_hdr->priv.get.is_eof = 1;
+ break; /* <--- one of the exits */
+ }
+
+ switch(OPCODE(inst)) {
+ case RSkipLinesOp:
+ if (LONGP(inst)) {
+ VAXSHORT(the_hdr->priv.get.vert_skip, infile);
+ } else
+ the_hdr->priv.get.vert_skip = DATUM(inst);
+ if (debug_f)
+ pm_message("Skip %d Lines (to %d)",
+ the_hdr->priv.get.vert_skip,
+ the_hdr->priv.get.scan_y +
+ the_hdr->priv.get.vert_skip);
+
+ break; /* need to break for() here, too */
+
+ case RSetColorOp:
+ channel = DATUM(inst); /* select color channel */
+ if (channel == 255)
+ channel = -1;
+ scan_x = the_hdr->xmin;
+ if (RLE_BIT(*the_hdr, channel))
+ scanc = scanline[channel]+scan_x;
+ if (debug_f)
+ pm_message("Set color to %d (reset x to %d)",
+ channel, scan_x );
+ break;
+
+ case RSkipPixelsOp:
+ if (LONGP(inst)) {
+ VAXSHORT(long_data, infile);
+ scan_x += long_data;
+ scanc += long_data;
+ if (debug_f)
+ pm_message("Skip %d pixels (to %d)", long_data, scan_x);
+ } else {
+ scan_x += DATUM(inst);
+ scanc += DATUM(inst);
+ if (debug_f)
+ pm_message("Skip %d pixels (to %d)", DATUM(inst), scan_x);
+ }
+ break;
+
+ case RByteDataOp:
+ if (LONGP(inst)) {
+ VAXSHORT(nc, infile);
+ } else
+ nc = DATUM(inst);
+ ++nc;
+ if (debug_f) {
+ if (RLE_BIT(*the_hdr, channel))
+ pm_message("Pixel data %d (to %d):", nc, scan_x + nc);
+ else
+ pm_message("Pixel data %d (to %d)", nc, scan_x + nc);
+ }
+ if (RLE_BIT(*the_hdr, channel)) {
+ /* Don't fill past end of scanline! */
+ if (scan_x + nc > max_x) {
+ ns = scan_x + nc - max_x - 1;
+ nc -= ns;
+ } else
+ ns = 0;
+ fread((char *)scanc, 1, nc, infile);
+ while (ns-- > 0)
+ getc(infile);
+ if (nc & 0x1)
+ getc(infile); /* throw away odd byte */
+ } else {
+ if (the_hdr->priv.get.is_seek)
+ fseek(infile, ((nc + 1) / 2) * 2, 1);
+ else {
+ int ii;
+ for (ii = ((nc + 1) / 2) * 2; ii > 0; --ii)
+ getc(infile); /* discard it */
+ }
+ }
+ scanc += nc;
+ scan_x += nc;
+ if (debug_f && RLE_BIT(*the_hdr, channel)) {
+ rle_pixel * cp;
+ for (cp = scanc - nc; nc > 0; --nc)
+ fprintf(stderr, "%02x", *cp++);
+ putc('\n', stderr);
+ }
+ break;
+
+ case RRunDataOp:
+ if (LONGP(inst)) {
+ VAXSHORT(nc, infile);
+ } else
+ nc = DATUM(inst);
+ ++nc;
+ scan_x += nc;
+
+ VAXSHORT(word, infile);
+ if (debug_f)
+ pm_message("Run length %d (to %d), data %02x",
+ nc, scan_x, word);
+ if (RLE_BIT(*the_hdr, channel)) {
+ if (scan_x > max_x) {
+ ns = scan_x - max_x - 1;
+ nc -= ns;
+ } else
+ ns = 0;
+ if (nc >= 10) { /* break point for 785, anyway */
+ memset((char *)scanc, word, nc);
+ scanc += nc;
+ } else {
+ for (nc--; nc >= 0; --nc, ++scanc)
+ *scanc = word;
+ }
+ }
+ break;
+
+ case REOFOp:
+ the_hdr->priv.get.is_eof = 1;
+ if (debug_f)
+ pm_message("End of Image");
+ break;
+
+ default:
+ pm_error("rle_getrow: Unrecognized opcode: %d, reading %s",
+ inst[0], the_hdr->file_name);
+ }
+ if (OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp)
+ break; /* <--- the other loop exit */
+ }
+
+ /* If at end, skip the rest of a malformed image. */
+ if (the_hdr->priv.get.scan_y >= the_hdr->ymax) {
+ int const y = the_hdr->priv.get.scan_y;
+ while (rle_getskip(the_hdr) != 32768 )
+ ;
+ return y;
+ }
+
+ return the_hdr->priv.get.scan_y;
+}
+
+
+
diff --git a/urt/rle_hdr.c b/urt/rle_hdr.c
index 1edb7a3..d306607 100644
--- a/urt/rle_hdr.c
+++ b/urt/rle_hdr.c
@@ -148,7 +148,7 @@ rle_hdr_cp(rle_hdr * const fromHdrP,
if (toHdrP->cmap) {
size_t const size =
toHdrP->ncmap * (1 << toHdrP->cmaplen) * sizeof(rle_map);
- toHdrP->cmap = malloc(size);
+ toHdrP->cmap = malloc3(toHdrP->ncmap, 1<<toHdrP->cmaplen, sizeof(rle_map));
if (!toHdrP->cmap)
pm_error("Failed to allocate memory for %u color maps "
"of length %u", toHdrP->ncmap, 1 << toHdrP->cmaplen);
@@ -164,11 +164,16 @@ rle_hdr_cp(rle_hdr * const fromHdrP,
/* Count the comments. */
for (cp = toHdrP->comments, size = 0; *cp; ++cp)
+ {
+ overflow_add(size,1);
++size;
+ }
/* Check if there are really any comments. */
if (size > 0) {
+ overflow_add(size,1);
++size; /* Copy the NULL pointer, too. */
+ overflow2(size, sizeof(char *));
size *= sizeof(char *);
toHdrP->comments = malloc(size);
if (!toHdrP->comments)
diff --git a/urt/rle_hdr.c.orig b/urt/rle_hdr.c.orig
new file mode 100644
index 0000000..1edb7a3
--- /dev/null
+++ b/urt/rle_hdr.c.orig
@@ -0,0 +1,286 @@
+/*
+ * This software is copyrighted as noted below. It may be freely copied,
+ * modified, and redistributed, provided that the copyright notice is
+ * preserved on all copies.
+ *
+ * There is no warranty or other guarantee of fitness for this software,
+ * it is provided solely "as is". Bug reports or fixes may be sent
+ * to the author, who may or may not act on them as he desires.
+ *
+ * You may not include this software in a program or other software product
+ * without supplying the source, or without informing the end-user that the
+ * source is available for no extra charge.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ */
+/*
+ * rle_hdr.c - Functions to manipulate rle_hdr structures.
+ *
+ * Author: Spencer W. Thomas
+ * EECS Dept.
+ * University of Michigan
+ * Date: Mon May 20 1991
+ * Copyright (c) 1991, University of Michigan
+ */
+
+#include <string.h>
+
+#include "nstring.h"
+#include "mallocvar.h"
+
+#include "rle_config.h"
+#include "rle.h"
+
+
+
+void
+rle_names(rle_hdr * const hdrP,
+ const char * const pgmname,
+ const char * const fname,
+ int const imgNum) {
+/*----------------------------------------------------------------------------
+ * Load program and file names into header.
+ * Inputs:
+ * hdrP: Header to modify.
+ * pgmname: The program name.
+ * fname: The file name.
+ * imgNum: Number of the image within the file.
+ * Outputs:
+ * *hdrP: Modified header.
+-----------------------------------------------------------------------------*/
+
+ /* Algorithm:
+ If values previously filled in (by testing is_init field),
+ free them. Make copies of file name and program name,
+ modifying file name for standard i/o. Set is_init field.
+ */
+ const char * newFname;
+ const char * newPgmname;
+
+ /* Mark as filled in. */
+ hdrP->is_init = RLE_INIT_MAGIC;
+
+ /* Default file name for stdin/stdout. */
+ if (!fname || streq(fname, "-") || strlen(fname) == 0)
+ newFname = "Standard I/O";
+ else
+ newFname = fname;
+
+ if (pgmname)
+ newPgmname = pgmname;
+ else
+ newPgmname = rle_dflt_hdr.cmd;
+
+ /* Fill in with copies of the strings. */
+ if (hdrP->cmd != newPgmname)
+ hdrP->cmd = pm_strdup(newPgmname);
+
+ if (hdrP->file_name != newFname)
+ hdrP->cmd = pm_strdup(newFname);
+
+ hdrP->img_num = imgNum;
+}
+
+
+
+/* Used by rle_hdr_cp and rle_hdr_init to avoid recursion loops. */
+static int noRecurse = 0;
+
+
+
+rle_hdr *
+rle_hdr_cp(rle_hdr * const fromHdrP,
+ rle_hdr * const toHdrArgP) {
+/*----------------------------------------------------------------------------
+ * Make a "safe" copy of a rle_hdr structure.
+ * Inputs:
+ * *fromHdrP: Header to be copied.
+ * Outputs:
+ * *toHdrPd: Copy of from_hdr, with all memory referred to
+ * by pointers copied. Also returned as function
+ * value. If NULL, a static header is used.
+ * Assumptions:
+ * It is safe to call rle_hdr_init on *toHdrP.
+-----------------------------------------------------------------------------*/
+ /* Algorithm:
+ Initialize *toHdrP, copy *fromHdrP to it, then copy the memory
+ referred to by all non-null pointers.
+ */
+ static rle_hdr dfltHdr;
+ rle_hdr * toHdrP;
+ const char * cmd;
+ const char * file;
+ unsigned int num;
+
+ /* Save command, file name, and image number if already initialized. */
+ if (toHdrArgP && toHdrArgP->is_init == RLE_INIT_MAGIC) {
+ cmd = toHdrArgP->cmd;
+ file = toHdrArgP->file_name;
+ num = toHdrArgP->img_num;
+ } else {
+ cmd = file = NULL;
+ num = 0;
+ }
+
+ if (!noRecurse) {
+ ++noRecurse;
+ rle_hdr_init(toHdrArgP);
+ --noRecurse;
+ }
+
+ toHdrP = toHdrArgP ? toHdrArgP : &dfltHdr;
+
+ *toHdrP = *fromHdrP;
+
+ if (toHdrP->bg_color) {
+ unsigned int i;
+
+ MALLOCARRAY(toHdrP->bg_color, toHdrP->ncolors);
+ if (!toHdrP->bg_color)
+ pm_error("Failed to allocate array for %u background colors",
+ toHdrP->ncolors);
+ for (i = 0; i < toHdrP->ncolors; ++i)
+ toHdrP->bg_color[i] = fromHdrP->bg_color[i];
+ }
+
+ if (toHdrP->cmap) {
+ size_t const size =
+ toHdrP->ncmap * (1 << toHdrP->cmaplen) * sizeof(rle_map);
+ toHdrP->cmap = malloc(size);
+ if (!toHdrP->cmap)
+ pm_error("Failed to allocate memory for %u color maps "
+ "of length %u", toHdrP->ncmap, 1 << toHdrP->cmaplen);
+ memcpy(toHdrP->cmap, fromHdrP->cmap, size);
+ }
+
+ /* Only copy array of pointers, as the original comment memory
+ * never gets overwritten.
+ */
+ if (toHdrP->comments) {
+ unsigned int size;
+ const char ** cp;
+
+ /* Count the comments. */
+ for (cp = toHdrP->comments, size = 0; *cp; ++cp)
+ ++size;
+
+ /* Check if there are really any comments. */
+ if (size > 0) {
+ ++size; /* Copy the NULL pointer, too. */
+ size *= sizeof(char *);
+ toHdrP->comments = malloc(size);
+ if (!toHdrP->comments)
+ pm_error("Failed to allocation %u bytes for comments", size);
+ memcpy(toHdrP->comments, fromHdrP->comments, size);
+ } else
+ toHdrP->comments = NULL; /* Blow off empty comment list. */
+ }
+
+ /* Restore the names to their original values. */
+ toHdrP->cmd = cmd;
+ toHdrP->file_name = file;
+
+ /* Lines above mean nothing much happens if cmd and file are != NULL. */
+ rle_names(toHdrP, toHdrP->cmd, toHdrP->file_name, num);
+
+ return toHdrP;
+}
+
+
+
+void
+rle_hdr_clear(rle_hdr * const hdrP) {
+/*----------------------------------------------------------------------------
+ * Clear out the allocated memory pieces of a header.
+ *
+ * This routine is intended to be used internally by the library, to
+ * clear a header before putting new data into it. It clears all the
+ * fields that would be set by reading in a new image header.
+ * Therefore, it does not clear the program and file names.
+ *
+ * Inputs:
+ * hdrP: To be cleared.
+ * Outputs:
+ * *hdrP: After clearing.
+ * Assumptions:
+ * If is_init field is RLE_INIT_MAGIC, the header has been
+ * properly initialized. This will fail every 2^(-32) times, on
+ * average.
+-----------------------------------------------------------------------------*/
+ /* Algorithm:
+ Free memory and set to zero all pointers, except program and
+ file name.
+ */
+
+ /* Try to free memory. Assume if is_init is properly set that this
+ * header has been previously initialized, therefore it is safe to
+ * free memory.
+ */
+ if (hdrP && hdrP->is_init == RLE_INIT_MAGIC) {
+ if (hdrP->bg_color )
+ free(hdrP->bg_color);
+ hdrP->bg_color = NULL;
+ if (hdrP->cmap )
+ free(hdrP->cmap);
+ hdrP->cmap = NULL;
+ /* Unfortunately, we don't know how to free the comment memory. */
+ if (hdrP->comments)
+ free(hdrP->comments);
+ hdrP->comments = NULL;
+ }
+}
+
+
+
+rle_hdr *
+rle_hdr_init(rle_hdr * const hdrP) {
+/*----------------------------------------------------------------------------
+ * Initialize a rle_hdr structure.
+ * Inputs:
+ * hdrP: Header to be initialized.
+ * Outputs:
+ * *hdrP: Initialized header.
+ * Assumptions:
+ * If hdrP->is_init is RLE_INIT_MAGIC, the header has been
+ * previously initialized.
+ * If the_hdr is a copy of another rle_hdr structure, the copy
+ * was made with rle_hdr_cp.
+-----------------------------------------------------------------------------*/
+ /* Algorithm:
+ Fill in fields of rle_dflt_hdr that could not be set by the loader
+ If the_hdr is rle_dflt_hdr, do nothing else
+ Else:
+ If hdrP is NULL, return a copy of rle_dflt_hdr in static storage
+ If hdrP->is_init is RLE_INIT_MAGIC, free all memory
+ pointed to by non-null pointers.
+ If this is a recursive call to rle_hdr_init, clear *hdrP and
+ return hdrP.
+ Else make a copy of rle_dflt_hdr and return its address. Make the
+ copy in static storage if hdrP is NULL, and in *hdrP otherwise.
+ */
+ rle_hdr * retval;
+
+ rle_dflt_hdr.rle_file = stdout;
+
+ /* The rest of rle_dflt_hdr is set by the loader's data initialization */
+
+ if (hdrP == &rle_dflt_hdr)
+ retval = hdrP;
+ else {
+ rle_hdr_clear(hdrP);
+
+ /* Call rle_hdr_cp only if not called from there. */
+ if (!noRecurse) {
+ ++noRecurse;
+ retval = rle_hdr_cp(&rle_dflt_hdr, hdrP);
+ --noRecurse;
+ } else
+ retval = hdrP;
+ }
+ return retval;
+}
+
+
+
diff --git a/urt/rle_hdr.c.rej b/urt/rle_hdr.c.rej
new file mode 100644
index 0000000..62f2fb0
--- /dev/null
+++ b/urt/rle_hdr.c.rej
@@ -0,0 +1,63 @@
+--- urt/rle_hdr.c
++++ urt/rle_hdr.c
+@@ -80,7 +80,10 @@ int img_num;
+ /* Fill in with copies of the strings. */
+ if ( the_hdr->cmd != pgmname )
+ {
+- char *tmp = (char *)malloc( strlen( pgmname ) + 1 );
++ char *tmp;
++
++ overflow_add(strlen(pgmname), 1);
++ tmp = malloc( strlen(pgmname) + 1 );
+ RLE_CHECK_ALLOC( pgmname, tmp, 0 );
+ strcpy( tmp, pgmname );
+ the_hdr->cmd = tmp;
+@@ -88,8 +91,10 @@ int img_num;
+
+ if ( the_hdr->file_name != fname )
+ {
+- char *tmp = (char *)malloc( strlen( fname ) + 1 );
+- RLE_CHECK_ALLOC( pgmname, tmp, 0 );
++ char *tmp;
++ overflow_add(strlen(fname), 1);
++ tmp = malloc( strlen( fname ) + 1 );
++ RLE_CHECK_ALLOC( pgmname, tmp, 0 );
+ strcpy( tmp, fname );
+ the_hdr->file_name = tmp;
+ }
+@@ -153,6 +158,7 @@ rle_hdr *from_hdr, *to_hdr;
+ if ( to_hdr->bg_color )
+ {
+ int size = to_hdr->ncolors * sizeof(int);
++ overflow2(to_hdr->ncolors, sizeof(int));
+ to_hdr->bg_color = (int *)malloc( size );
+ RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->bg_color, "background color" );
+ memcpy( to_hdr->bg_color, from_hdr->bg_color, size );
+@@ -161,7 +167,7 @@ rle_hdr *from_hdr, *to_hdr;
+ if ( to_hdr->cmap )
+ {
+ int size = to_hdr->ncmap * (1 << to_hdr->cmaplen) * sizeof(rle_map);
+- to_hdr->cmap = (rle_map *)malloc( size );
++ to_hdr->cmap = (rle_map *)malloc3( to_hdr->ncmap, 1<<to_hdr->cmaplen, sizeof(rle_map));
+ RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->cmap, "color map" );
+ memcpy( to_hdr->cmap, from_hdr->cmap, size );
+ }
+@@ -173,12 +179,17 @@ rle_hdr *from_hdr, *to_hdr;
+ {
+ int size = 0;
+ CONST_DECL char **cp;
+- for ( cp=to_hdr->comments; *cp; cp++ )
++ for ( cp=to_hdr->comments; *cp; cp++ )
++ {
++ overflow_add(size, 1);
+ size++; /* Count the comments. */
++ }
+ /* Check if there are really any comments. */
+ if ( size )
+ {
++ overflow_add(size, 1);
+ size++; /* Copy the NULL pointer, too. */
++ overflow2(size, sizeof(char *));
+ size *= sizeof(char *);
+ to_hdr->comments = (CONST_DECL char **)malloc( size );
+ RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->comments, "comments" );
diff --git a/urt/rle_open_f.c b/urt/rle_open_f.c
index 1aeb644..c2ef37d 100644
--- a/urt/rle_open_f.c
+++ b/urt/rle_open_f.c
@@ -1,7 +1,7 @@
-/*
+/*
* rle_open_f.c - Open a file with defaults.
- *
- * Author : Jerry Winters
+ *
+ * Author : Jerry Winters
* EECS Dept.
* University of Michigan
* Date: 11/14/89
@@ -37,8 +37,8 @@
static FILE *
-my_popen(const char * const cmd,
- const char * const mode,
+my_popen(const char * const cmd,
+ const char * const mode,
int * const pid) {
FILE *retfile;
@@ -55,7 +55,7 @@ my_popen(const char * const cmd,
if (pm_pipe(pipefd) < 0 )
return NULL;
-
+
/* Flush known files. */
fflush(stdout);
fflush(stderr);
@@ -86,7 +86,7 @@ my_popen(const char * const cmd,
if ( execl("/bin/sh", "sh", "-c", cmd, NULL) < 0 )
exit(127);
/* NOTREACHED */
- }
+ }
/* Close file descriptors, and gen up a FILE ptr */
if ( *mode == 'r' )
@@ -163,72 +163,14 @@ dealWithSubprocess(const char * const file_name,
FILE ** const fpP,
bool * const noSubprocessP,
const char ** const errorP) {
-
-#ifdef NO_OPEN_PIPES
*noSubprocessP = TRUE;
-#else
- const char *cp;
-
- reapChildren(catchingChildrenP, pids);
-
- /* Real file, not stdin or stdout. If name ends in ".Z",
- * pipe from/to un/compress (depending on r/w mode).
- *
- * If it starts with "|", popen that command.
- */
-
- cp = file_name + strlen(file_name) - 2;
- /* Pipe case. */
- if (file_name[0] == '|') {
- pid_t thepid; /* PID from my_popen */
-
- *noSubprocessP = FALSE;
-
- *fpP = my_popen(file_name + 1, mode, &thepid);
- if (*fpP == NULL)
- *errorP = "%s: can't invoke <<%s>> for %s: ";
- else {
- /* One more child to catch, eventually. */
- if (*catchingChildrenP < MAX_CHILDREN)
- pids[(*catchingChildrenP)++] = thepid;
- }
- } else if (cp > file_name && *cp == '.' && *(cp + 1) == 'Z' ) {
- /* Compress case. */
- pid_t thepid; /* PID from my_popen. */
- const char * command;
-
- *noSubprocessP = FALSE;
-
- if (*mode == 'w')
- pm_asprintf(&command, "compress > %s", file_name);
- else if (*mode == 'a')
- pm_asprintf(&command, "compress >> %s", file_name);
- else
- pm_asprintf(&command, "compress -d < %s", file_name);
-
- *fpP = my_popen(command, mode, &thepid);
-
- if (*fpP == NULL)
- *errorP = "%s: can't invoke 'compress' program, "
- "trying to open %s for %s";
- else {
- /* One more child to catch, eventually. */
- if (*catchingChildrenP < MAX_CHILDREN)
- pids[(*catchingChildrenP)++] = thepid;
- }
- pm_strfree(command);
- } else {
- *noSubprocessP = TRUE;
- *errorP = NULL;
- }
-#endif
}
-/*
- * Purpose : Open a file for input or output as controlled by the mode
+/*
+ * Purpose : Open a file for input or ouput as controlled by the mode
* parameter. If no file name is specified (ie. file_name is null) then
* a pointer to stdin or stdout will be returned. The calling routine may
* call this routine with a file name of "-". For this case rle_open_f
@@ -246,11 +188,11 @@ dealWithSubprocess(const char * const file_name,
*
* output:
* a file pointer
- *
+ *
*/
FILE *
-rle_open_f_noexit(const char * const prog_name,
- const char * const file_name,
+rle_open_f_noexit(const char * const prog_name,
+ const char * const file_name,
const char * const mode ) {
FILE * retval;
@@ -265,12 +207,12 @@ rle_open_f_noexit(const char * const prog_name,
fp = stdout; /* Set the default value */
else
fp = stdin;
-
+
if (file_name != NULL && !streq(file_name, "-")) {
bool noSubprocess;
dealWithSubprocess(file_name, mode, &catching_children, pids,
&fp, &noSubprocess, &err_str);
-
+
if (!err_str) {
if (noSubprocess) {
/* Ordinary, boring file case. */
@@ -286,7 +228,7 @@ rle_open_f_noexit(const char * const prog_name,
mode_string[0] = mode[0];
mode_string[1] = 'b';
strcpy( mode_string + 2, mode + 1 );
-
+
fp = fopen(file_name, mode_string);
if (fp == NULL )
err_str = "%s: can't open %s for %s: ";
@@ -325,7 +267,7 @@ rle_open_f(const char * prog_name, const char * file_name, const char * mode)
/*****************************************************************
* TAG( rle_close_f )
- *
+ *
* Close a file opened by rle_open_f. If the file is stdin or stdout,
* it will not be closed.
* Inputs:
@@ -347,6 +289,3 @@ rle_close_f( fd )
else
fclose( fd );
}
-
-
-
diff --git a/urt/rle_putcom.c b/urt/rle_putcom.c
index ab2eb20..ce83615 100644
--- a/urt/rle_putcom.c
+++ b/urt/rle_putcom.c
@@ -98,12 +98,14 @@ rle_putcom(const char * const value,
const char * v;
const char ** old_comments;
int i;
- for (i = 2, cp = the_hdr->comments; *cp != NULL; ++i, ++cp)
+ for (i = 2, cp = the_hdr->comments; *cp != NULL; ++i, ++cp) {
+ overflow_add(i, 1);
if (match(value, *cp) != NULL) {
v = *cp;
*cp = value;
return v;
}
+ }
/* Not found */
/* Can't realloc because somebody else might be pointing to this
* comments block. Of course, if this were true, then the
diff --git a/urt/scanargs.c b/urt/scanargs.c
index f3af334..5e114bb 100644
--- a/urt/scanargs.c
+++ b/urt/scanargs.c
@@ -62,9 +62,8 @@ typedef int *ptr;
/*
* Storage allocation macros
*/
-#define NEW( type, cnt ) (type *) malloc( (cnt) * sizeof( type ) )
-#define RENEW( type, ptr, cnt ) (type *) realloc( ptr, (cnt) * sizeof( type ) )
-
+#define NEW( type, cnt ) (type *) malloc2( (cnt) , sizeof( type ) )
+#define RENEW( type, ptr, cnt ) (type *) realloc2( ptr, (cnt), sizeof( type ) )
static CONST_DECL char * prformat( CONST_DECL char *, int );
static int isnum( CONST_DECL char *, int, int );
static int _do_scanargs( int argc, char **argv, CONST_DECL char *format,