[libpng15] Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left

the sBIT fields in the test pixel as 0, which resulted in a floating
point division by zero which was irrelevant but causes systems where
FP exceptions cause a crash. Added code to pngvalid to turn on FP
exceptions if the appropriate glibc support is there to ensure this is
tested in the future.
diff --git a/ANNOUNCE b/ANNOUNCE
index 46b5786..289608f 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -49,6 +49,12 @@
     be non-NULL. The cast of the profile length potentially truncated the
     value unnecessarily on a 16-bit int system, so the cast of the (byte)
     compression type to (int) is specified by ANSI-C anyway.
+  Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left
+    the sBIT fields in the test pixel as 0, which resulted in a floating
+    point division by zero which was irrelevant but causes systems where
+    FP exceptions cause a crash. Added code to pngvalid to turn on FP
+    exceptions if the appropriate glibc support is there to ensure this is
+    tested in the future.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index 9ee8950..c85a426 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3692,6 +3692,12 @@
     be non-NULL. The cast of the profile length potentially truncated the
     value unnecessarily on a 16-bit int system, so the cast of the (byte)
     compression type to (int) is specified by ANSI-C anyway.
+  Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left
+    the sBIT fields in the test pixel as 0, which resulted in a floating
+    point division by zero which was irrelevant but causes systems where
+    FP exceptions cause a crash. Added code to pngvalid to turn on FP
+    exceptions if the appropriate glibc support is there to ensure this is
+    tested in the future.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/png.h b/png.h
index 1d06ac2..9852f72 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.5.7beta02 - November 4, 2011
+ * libpng version 1.5.7beta02 - November 5, 2011
  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -11,7 +11,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.5.7beta02 - November 4, 2011: Glenn
+ *   libpng versions 0.97, January 1998, through 1.5.7beta02 - November 5, 2011: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -195,7 +195,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.5.7beta02, November 4, 2011, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.5.7beta02, November 5, 2011, are
  * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
@@ -307,7 +307,7 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    November 4, 2011
+ *    November 5, 2011
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
@@ -370,7 +370,7 @@
 /* Version information for png.h - this should match the version in png.c */
 #define PNG_LIBPNG_VER_STRING "1.5.7beta02"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.5.7beta02 - November 4, 2011\n"
+     " libpng version 1.5.7beta02 - November 5, 2011\n"
 
 #define PNG_LIBPNG_VER_SONUM   15
 #define PNG_LIBPNG_VER_DLLNUM  15
diff --git a/pngvalid.c b/pngvalid.c
index 14d198a..beb6cb5 100644
--- a/pngvalid.c
+++ b/pngvalid.c
@@ -20,8 +20,21 @@
  */
 
 #define _POSIX_SOURCE 1
+#define _ISOC99_SOURCE 1 /* For floating point */
+#define _GNU_SOURCE 1 /* For the floating point exception extension */
+
+#include <signal.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#ifdef HAVE_FEENABLEEXCEPT
+#  include <fenv.h>
+#endif
 
 #include "png.h"
+
 #if PNG_LIBPNG_VER < 10500
 /* This delibarately lacks the PNG_CONST. */
 typedef png_byte *png_const_bytep;
@@ -831,6 +844,19 @@
       store_verbose(ps, pp, is_error ? "error: " : "warning: ", message);
 }
 
+/* Internal error function, called with a png_store but no libpng stuff. */
+static void
+internal_error(png_store *ps, png_const_charp message)
+{
+   store_log(ps, NULL, message, 1 /* error */);
+
+   /* And finally throw an exception. */
+   {
+      struct exception_context *the_exception_context = &ps->exception_context;
+      Throw ps;
+   }
+}
+
 /* Functions to use as PNG callbacks. */
 static void
 store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */
@@ -3679,9 +3705,11 @@
     };
 
 static void
-make_error(png_store* volatile ps, png_byte PNG_CONST colour_type,
+make_error(png_store* volatile psIn, png_byte PNG_CONST colour_type,
     png_byte bit_depth, int interlace_type, int test, png_const_charp name)
 {
+   png_store * volatile ps = psIn;
+
    context(ps, fault);
 
    Try
@@ -3965,6 +3993,8 @@
    dp->ps = ps;
    dp->colour_type = COL_FROM_ID(id);
    dp->bit_depth = DEPTH_FROM_ID(id);
+   if (dp->bit_depth < 1 || dp->bit_depth > 16)
+      internal_error(ps, "internal: bad bit depth");
    if (dp->colour_type == 3)
       dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8;
    else
@@ -5333,8 +5363,12 @@
          test_pixel.sample_depth = 8;
       else
          test_pixel.sample_depth = test_pixel.bit_depth;
-      /* Don't need sBIT here */
+      /* Don't need sBIT here, but it must be set to non-zero to avoid
+       * arithmetic overflows.
+       */
       test_pixel.have_tRNS = dp->this.is_transparent;
+      test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT =
+         test_pixel.alpha_sBIT = test_pixel.sample_depth;
 
       dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp);
 
@@ -9267,6 +9301,72 @@
 /*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} },
 };
 
+/* signal handler
+ *
+ * This attempts to trap signals and escape without crashing.  It needs a
+ * context pointer so that it can throw an exception (call longjmp) to recover
+ * from the condition; this is handled by making the png_modifier used by 'main'
+ * into a global variable.
+ */
+static png_modifier pm;
+
+static void signal_handler(int signum)
+{
+
+   size_t pos = 0;
+   char msg[64];
+
+   pos = safecat(msg, sizeof msg, pos, "caught signal: ");
+
+   switch (signum)
+   {
+      case SIGABRT:
+         pos = safecat(msg, sizeof msg, pos, "abort");
+         break;
+
+      case SIGFPE:
+         pos = safecat(msg, sizeof msg, pos, "floating point exception");
+         break;
+
+      case SIGILL:
+         pos = safecat(msg, sizeof msg, pos, "illegal instruction");
+         break;
+
+      case SIGINT:
+         pos = safecat(msg, sizeof msg, pos, "interrupt");
+         break;
+
+      case SIGSEGV:
+         pos = safecat(msg, sizeof msg, pos, "invalid memory access");
+         break;
+
+      case SIGTERM:
+         pos = safecat(msg, sizeof msg, pos, "termination request");
+         break;
+
+      default:
+         pos = safecat(msg, sizeof msg, pos, "unknown ");
+         pos = safecatn(msg, sizeof msg, pos, signum);
+         break;
+   }
+
+   store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/);
+
+   /* And finally throw an exception so we can keep going, unless this is
+    * SIGTERM in which case stop now.
+    */
+   if (signum != SIGTERM)
+   {
+      struct exception_context *the_exception_context =
+         &pm.this.exception_context;
+
+      Throw &pm.this;
+   }
+
+   else
+      exit(1);
+}
+
 /* main program */
 int main(int argc, PNG_CONST char **argv)
 {
@@ -9288,9 +9388,24 @@
    size_t cp = 0;
    char command[1024];
 
-   png_modifier pm;
    context(&pm.this, fault);
 
+   /* Add appropriate signal handlers, just the ANSI specified ones: */
+   signal(SIGABRT, signal_handler);
+   signal(SIGFPE, signal_handler);
+   signal(SIGILL, signal_handler);
+   signal(SIGINT, signal_handler);
+   signal(SIGSEGV, signal_handler);
+   signal(SIGTERM, signal_handler);
+
+#ifdef HAVE_FEENABLEEXCEPT
+   /* Only required to enable FP exceptions on platforms where they start off
+    * disabled; this is not necessary but if it is not done pngvalid will likely
+    * end up ignoring FP conditions that other platforms fault.
+    */
+   feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
+#endif
+
    modifier_init(&pm);
 
    /* Preallocate the image buffer, because we know how big it needs to be,