[PATCH] lib: gui: png_pico: fix use-after-free and double-free in png_open

Johannes Schneider <[email protected]>
Newsgroups org.infradead.lists.barebox
Message-ID <[email protected]>
From: Thomas Haemmerle <[email protected]>

png_alloc_free_all() frees all picopng-internal allocations, including
the image->data buffer.  The previous code stored a pointer to this
buffer in img->data and called png_alloc_free_all() — leaving img->data
as a dangling pointer.  The subsequent png_close()'s free(img->data)
then performed a double-free on already-freed memory, causing a crash or
heap corruption when displaying the boot logo.

Fix by copying the decoded pixel data into a fresh malloc buffer before
calling png_alloc_free_all().  png_close() correctly frees this copy.

Assisted-by: Claude:claude-sonnet-4-6
Signed-of-by: Thomas Haemmerle <[email protected]>
---
 lib/gui/png_pico.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/lib/gui/png_pico.c b/lib/gui/png_pico.c
index 029fee2a40..8d70521b46 100644
--- a/lib/gui/png_pico.c
+++ b/lib/gui/png_pico.c
@@ -46,6 +46,8 @@ struct image *png_open(char *inbuf, int insize)
 {
 	PNG_info_t *png_info;
 	int ret;
+	size_t imgsize;
+	void *imgcopy;
 	struct image *img = calloc(1, sizeof(struct image));
 
 	if (!img)
@@ -67,12 +69,27 @@ struct image *png_open(char *inbuf, int insize)
 	img->width = png_info->width;
 	img->height = png_info->height;
 	img->bits_per_pixel = 4 << 3;
-	img->data = png_info->image->data;
 
-	pr_debug("png: %d x %d data@0x%p\n", img->width, img->height, img->data);
+	/*
+	 * Copy decoded pixels to a stable buffer before png_alloc_free_all()
+	 * frees the picopng internal allocations (including image->data).
+	 * Without this copy, img->data would be a dangling pointer and
+	 * png_close()'s free(img->data) would be a double-free.
+	 */
+	imgsize = png_info->width * png_info->height * 4;
+	imgcopy = malloc(imgsize);
+	if (!imgcopy) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	memcpy(imgcopy, png_info->image->data, imgsize);
 
 	png_alloc_free_all();
 
+	img->data = imgcopy;
+
+	pr_debug("png: %d x %d data@0x%p\n", img->width, img->height, img->data);
+
 	return img;
 err:
 	png_alloc_free_all();
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.