File libpng16-CVE-2025-28162,28164.patch of Package libpng16.42472
From fce5f2a42d7fbe7cc0e89333b9ebc539b858b4be Mon Sep 17 00:00:00 2001
From: John Bowler <jbowler@acm.org>
Date: Thu, 13 Feb 2025 13:00:49 -0800
Subject: [PATCH] pngimage: clean up on user/internal errors
pngimage: The code simply exited with a return code of 99 in the event
of a user error including giving pngimage invalid PNG files and an
internal error. It now attempts to clean up the state before doing so,
matching the normal behaviour.
pngimage: Non-ISO use of setjmp(3) corrected.
pngerror.c: Failure to call png_image_free on a false result from a
png_safe_execute function call fixed. This was a regression caused by
the 'volatile' clean-up. Not normally detectable because png_image_free
will often be called by the application.
Signed-off-by: John Bowler <jbowler@acm.org>
---
contrib/libtests/pngimage.c | 19 ++++++++++++++-----
pngerror.c | 26 ++++++++++++++++++++------
2 files changed, 34 insertions(+), 11 deletions(-)
Index: libpng-1.6.40/contrib/libtests/pngimage.c
===================================================================
--- libpng-1.6.40.orig/contrib/libtests/pngimage.c
+++ libpng-1.6.40/contrib/libtests/pngimage.c
@@ -543,6 +543,7 @@ typedef enum
struct display
{
jmp_buf error_return; /* Where to go to on error */
+ error_level error_code; /* Set before longjmp */
const char *filename; /* The name of the original file */
const char *operation; /* Operation being performed */
@@ -763,7 +764,10 @@ display_log(struct display *dp, error_le
/* Errors cause this routine to exit to the fail code */
if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE)))
+ {
+ dp->error_code = level;
longjmp(dp->error_return, level);
+ }
}
/* error handler callbacks for libpng */
@@ -1566,18 +1570,19 @@ static int
do_test(struct display *dp, const char *file)
/* Exists solely to isolate the setjmp clobbers */
{
- int ret = setjmp(dp->error_return);
+ dp->error_code = VERBOSE; /* The "lowest" level */
- if (ret == 0)
+ if (setjmp(dp->error_return) == 0)
{
test_one_file(dp, file);
return 0;
}
- else if (ret < ERRORS) /* shouldn't longjmp on warnings */
- display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret);
+ else if (dp->error_code < ERRORS) /* shouldn't longjmp on warnings */
+ display_log(dp, INTERNAL_ERROR, "unexpected return code %d",
+ dp->error_code);
- return ret;
+ return dp->error_code;
}
int
@@ -1677,7 +1682,11 @@ main(int argc, char **argv)
int ret = do_test(&d, argv[i]);
if (ret > QUIET) /* abort on user or internal error */
+ {
+ display_clean(&d);
+ display_destroy(&d);
return 99;
+ }
}
/* Here on any return, including failures, except user/internal issues
Index: libpng-1.6.40/pngerror.c
===================================================================
--- libpng-1.6.40.orig/pngerror.c
+++ libpng-1.6.40/pngerror.c
@@ -933,31 +933,39 @@ png_safe_warning(png_structp png_noncons
#endif
int /* PRIVATE */
-png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
+png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
{
- volatile png_imagep image = image_in;
- volatile int result;
- volatile png_voidp saved_error_buf;
+ const png_voidp saved_error_buf = image->opaque->error_buf;
jmp_buf safe_jmpbuf;
- /* Safely execute function(arg) with png_error returning to this function. */
- saved_error_buf = image->opaque->error_buf;
- result = setjmp(safe_jmpbuf) == 0;
-
- if (result != 0)
+ /* Safely execute function(arg), with png_error returning back here. */
+ if (setjmp(safe_jmpbuf) == 0)
{
+ int result; /*bool*/
image->opaque->error_buf = safe_jmpbuf;
result = function(arg);
+ image->opaque->error_buf = saved_error_buf;
+
+ if (result)
+ return 1; /*true*/
}
+ /* The function failed either because of a caught png_error and a regular
+ * return of false above or because of an uncaught png_error from the
+ * function itself. Ensure that the error_buf is always set back to the
+ * value saved above:
+ */
image->opaque->error_buf = saved_error_buf;
- /* And do the cleanup prior to any failure return. */
- if (result == 0)
+ /* On the final false return, when about to return control to the caller, the
+ * image is freed (png_image_free does this check but it is duplicated here
+ * for clarity:
+ */
+ if (saved_error_buf == NULL)
png_image_free(image);
- return result;
+ return 0; /*false*/
}
#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
#endif /* READ || WRITE */