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 */
openSUSE Build Service is sponsored by