[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,