mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
[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:
parent
88bcdc269b
commit
a004e23a4c
6
ANNOUNCE
6
ANNOUNCE
@ -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
|
||||
|
6
CHANGES
6
CHANGES
@ -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
10
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
|
||||
|
121
pngvalid.c
121
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_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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user