diff options
-rwxr-xr-x | buildtools/configure.pl | 56 | ||||
-rw-r--r-- | doc/HISTORY | 11 | ||||
-rw-r--r-- | lib/libppmd.c | 91 | ||||
-rw-r--r-- | version.mk | 2 |
4 files changed, 136 insertions, 24 deletions
diff --git a/buildtools/configure.pl b/buildtools/configure.pl index efb44ef7..a4683385 100755 --- a/buildtools/configure.pl +++ b/buildtools/configure.pl @@ -99,13 +99,17 @@ sub tmpdir() { my $retval; - if ($ENV{"TMPDIR"}) { - $retval = $ENV{"TMPDIR"}; + if ($ENV{'TMPDIR'}) { + $retval = $ENV{'TMPDIR'}; + } elsif ($ENV{'TEMP'}) { + $retval = $ENV{'TEMP'}; } else { - if ($Config{'osvers'} eq "djgpp") { - $retval = "/dev/env/DJDIR/tmp"; + if ($Config{'osvers'} eq 'djgpp') { + $retval = '/dev/env/DJDIR/tmp'; } else { - $retval = "/tmp"; + if (-d('/tmp')) { + $retval = '/tmp'; + } } } return $retval; @@ -122,14 +126,43 @@ sub tempFile($) { # DIR=>File::Spec->tmpdir(), # UNLINK=>0); my ($suffix) = @_; + my $fileName; local *file; # For some inexplicable reason, must be local, not my - my $i; - $i = 0; - do { - $fileName = tmpdir() . "/netpbm" . $i++ . $suffix; - } until sysopen(*file, $fileName, O_RDWR|O_CREAT|O_EXCL); + my $tmpdir = tmpdir(); + + if (!defined($tmpdir)) { + print STDERR ("Cannot determine what directory to use for " . + "temporary files. " . + "Set TMPDIR environment variable to fix this.\n"); + exit(1); + } else { + if (!-d($tmpdir)) { + print STDERR ("Temporary file directory '$tmpdir' does not " . + "exist. Create it or set TMPDIR environment " . + "variable appropriately\n"); + exit(1); + } else { + for (my $i = 0; $i < 50 && !defined($fileName); ++$i) { + my $trialFileName = tmpdir() . "/netpbm" . $i . $suffix; + + my $success = sysopen(*file, + $trialFileName, + O_RDWR|O_CREAT|O_EXCL); + + if ($success) { + $fileName = $trialFileName; + } + } + + if (!defined($fileName)) { + print STDERR ("Unable to create a temporary file in " . + "directory '$tmpdir'\n"); + exit(1); + } + } + } return(*file, $fileName); } @@ -487,7 +520,7 @@ sub getCompiler($$) { "TRU64" => 1, "SCO" => 1, "AIX" => 1, - "HP" => 1); + "HP-UX" => 1); my %gccUsualPlatform = ("GNU" => 1, "NETBSD" => 1, @@ -2060,6 +2093,7 @@ if ($platform eq "GNU") { # We don't know what to do here. We used to (before 10.20) just # just assume the compiler was gcc. We know that the gcc stuff # above does NOT work for HP native compiler. + push(@config_mk, "LDSHLIB =\n"); } } elsif ($platform eq "AIX") { push(@config_mk, 'LDFLAGS += -L /usr/pubsw/lib', "\n"); diff --git a/doc/HISTORY b/doc/HISTORY index 07c5517c..21d0c915 100644 --- a/doc/HISTORY +++ b/doc/HISTORY @@ -4,6 +4,17 @@ Netpbm. CHANGE HISTORY -------------- +09.06.26 BJH Release 10.46.06 + + libppmd (ppmdraw, ppmpat): Fix bugs with coordinates too large. + Thanks Prophet of the Way <afu@wta.att.ne.jp>. + + configure: use TEMP environment variable for TMPDIR if TMPDIR + is not set. Don't try different temp file names forever; the + problem may not be the filename. + + configure: offer Gcc as an optional compiler for HP-UX. + 09.05.08 BJH Release 10.46.05 pnmremap: fix: -firstisdefault uses an arbitrary color from the diff --git a/lib/libppmd.c b/lib/libppmd.c index 0c1bfe00..4852de69 100644 --- a/lib/libppmd.c +++ b/lib/libppmd.c @@ -26,7 +26,6 @@ #include "ppmdraw.h" -#define DDA_SCALE 8192 struct penpos { int x; @@ -47,6 +46,40 @@ static struct rectangle const emptyRectangle = { +static long int const DDA_SCALE = 8192; + +#define PPMD_MAXCOORD 32767 +/* + Several factors govern the limit of x, y coordination values. + + The limit must be representable as (signed) int for coordinates to + be carried in struct penpos (immediately above). + + The following calculation, done with long ints, must not overflow: + cy0 = cy0 + (y1 - cy0) * (cols - 1 - cx0) / (x1 - cx0); + + The following must not overflow when DDA_SCALE is set to 8092: + dy = (y1 - y0) * DDA_SCALE / abs(x1 - x0); + + Overflow conditions for ppmd_text are rather complicated, for commands + come from an external PPMD font file. See comments below. +*/ + + + +static void +ppmd_validateCoords(int const x, + int const y) { + + if (x < -PPMD_MAXCOORD || x > PPMD_MAXCOORD) + pm_error("x coordinate out of bounds: %d", x); + + if (y < -PPMD_MAXCOORD || y > PPMD_MAXCOORD) + pm_error("y coordinate out of bounds: %d", y); +} + + + static void drawPoint(ppmd_drawproc drawproc, const void * const clientdata, @@ -500,6 +533,10 @@ ppmd_line(pixel ** const pixels, int cx0, cy0, cx1, cy1; bool noLine; /* There's no line left after clipping */ + ppmd_validateCoords(cols, rows); + ppmd_validateCoords(x0, y0); + ppmd_validateCoords(x1, y1); + if (lineclip) { clipLine(x0, y0, x1, y1, cols, rows, &cx0, &cy0, &cx1, &cy1, &noLine); } else { @@ -647,17 +684,34 @@ ppmd_circle(pixel ** const pixels, ppmd_drawproc drawProc, const void * const clientdata) { - if (radius != 0) { int x0, y0, x, y, prevx, prevy, nopointsyet; long sx, sy, e; + if (radius < 0) + pm_error("Error drawing circle. Radius must be positive: %d", radius); + else if (radius == 0) + return; + else if (radius >= DDA_SCALE) + pm_error("Error drawing circle. Radius too large: %d", radius); + + ppmd_validateCoords(cx + radius, cy + radius); + ppmd_validateCoords(cx - radius, cy - radius); + x0 = x = radius; y0 = y = 0; sx = x * DDA_SCALE + DDA_SCALE / 2; sy = y * DDA_SCALE + DDA_SCALE / 2; e = DDA_SCALE / radius; - drawPoint(drawProc, clientdata, - pixels, cols, rows, maxval, x + cx, y + cy); + + /* If lineclip is on, draw only points within pixmap. + Initial point is 3 o'clock. + If lineclip is off, "draw" all points (by designated drawproc). + */ + + if ((x + cx >= 0 && x + cx < cols && y + cy >= 0 && y + cy < rows) || + !lineclip) + drawPoint(drawProc, clientdata, + pixels, cols, rows, maxval, x + cx, y + cy); nopointsyet = 1; do { @@ -669,12 +723,13 @@ ppmd_circle(pixel ** const pixels, y = sy / DDA_SCALE; if (x != prevx || y != prevy) { nopointsyet = 0; - drawPoint(drawProc, clientdata, - pixels, cols, rows, maxval, x + cx, y + cy); + if ((x + cx >= 0 && x + cx < cols && y + cy >= 0 && y + cy < rows) + || !lineclip) + drawPoint(drawProc, clientdata, + pixels, cols, rows, maxval, x + cx, y + cy); } } while (nopointsyet || x != x0 || y != y0); - } } @@ -683,9 +738,9 @@ ppmd_circle(pixel ** const pixels, typedef struct { - short x; - short y; - short edge; + int x; + int y; + int edge; } coord; typedef struct fillobj { @@ -778,6 +833,8 @@ ppmd_fill_drawproc(pixel** const pixels, REALLOCARRAY(fh->coords, fh->size); if (fh->coords == NULL) pm_error( "out of memory enlarging a fillhandle" ); + + ocp = &(fh->coords[fh->n - 1]); } /* Check for extremum and set the edge number. */ @@ -798,12 +855,14 @@ ppmd_fill_drawproc(pixel** const pixels, /* Oops, first edge and last edge are the same. Renumber the first edge in the old segment. */ + const coord * const fcpLast= &(fh->coords[fh->n -1]); coord * fcp; + int oldedge; fcp = &(fh->coords[fh->segstart]); oldedge = fcp->edge; - for ( ; fcp->edge == oldedge; ++fcp ) + for (; fcp <= fcpLast && fcp->edge == oldedge ; ++fcp) fcp->edge = ocp->edge; } /* And start new segment. */ @@ -892,12 +951,13 @@ ppmd_fill(pixel ** const pixels, if (fh->startydir == fh->ydir) { /* Oops, first edge and last edge are the same. */ coord * fcp; + const coord * const fcpLast = & (fh->coords[fh->n - 1]); int lastedge, oldedge; lastedge = fh->coords[fh->n - 1].edge; fcp = &(fh->coords[fh->segstart]); oldedge = fcp->edge; - for ( ; fcp->edge == oldedge; ++fcp ) + for ( ; fcp<=fcpLast && fcp->edge == oldedge; ++fcp ) fcp->edge = lastedge; } } @@ -1114,6 +1174,9 @@ drawGlyph(const struct ppmd_glyph * const glyphP, ty1 = ypos + (mx1 * rotsin + my1 * rotcos) / 65536; tx2 = xpos + (mx2 * rotcos - my2 * rotsin) / 65536; ty2 = ypos + (mx2 * rotsin + my2 * rotcos) / 65536; + + ppmd_validateCoords(tx1, ty1); + ppmd_validateCoords(tx2, ty2); ppmd_line(pixels, cols, rows, maxval, tx1, ty1, tx2, ty2, drawProc, clientdata); @@ -1159,6 +1222,8 @@ ppmd_text(pixel** const pixels, int x, y; const char * s; + ppmd_validateCoords(xpos, ypos); + x = y = 0; rotsin = isin(-angle); rotcos = icos(-angle); @@ -1173,6 +1238,8 @@ ppmd_text(pixel** const pixels, const struct ppmd_glyph * const glyphP = &fontP->glyphTable[ch - fontP->header.firstCodePoint]; + ppmd_validateCoords(x, y); + drawGlyph(glyphP, &x, y, pixels, cols, rows, maxval, height, xpos, ypos, rotcos, rotsin, drawProc, clientdata); diff --git a/version.mk b/version.mk index d43d21a4..a14c021d 100644 --- a/version.mk +++ b/version.mk @@ -1,4 +1,4 @@ NETPBM_MAJOR_RELEASE = 10 NETPBM_MINOR_RELEASE = 46 -NETPBM_POINT_RELEASE = 5 +NETPBM_POINT_RELEASE = 6 |