[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.
This commit is contained in:
John Bowler 2011-11-04 20:24:56 -05:00 committed by Glenn Randers-Pehrson
parent 88bcdc269b
commit a004e23a4c
4 changed files with 135 additions and 8 deletions

View File

@ -49,6 +49,12 @@ Version 1.5.7beta02 [November 5, 2011]
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

View File

@ -3692,6 +3692,12 @@ Version 1.5.7beta02 [November 5, 2011]
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

10
png.h
View File

@ -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

View File

@ -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_log(png_store* ps, png_structp pp, png_const_charp message, int is_error)
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 PNG_CONST struct
};
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 @@ standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id,
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 @@ transform_info_imp(transform_display *dp, png_structp pp, png_infop pi)
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 @@ static PNG_CONST color_encoding test_encodings[] =
/*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 @@ int main(int argc, PNG_CONST char **argv)
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,