about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xbuildtools/configure.pl56
-rw-r--r--doc/HISTORY11
-rw-r--r--lib/libppmd.c91
-rw-r--r--version.mk2
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