diff --git a/meta/recipes-multimedia/libpng/files/CVE-2026-46675.patch b/meta/recipes-multimedia/libpng/files/CVE-2026-46675.patch
new file mode 100644
index 00000000000..3af0251c553
--- /dev/null
+++ b/meta/recipes-multimedia/libpng/files/CVE-2026-46675.patch
@@ -0,0 +1,115 @@
+From aa77ef38c17ab2fc1b41bec09fb973c6a386641d Mon Sep 17 00:00:00 2001
+From: Cosmin Truta <ctruta@gmail.com>
+Date: Wed, 23 Sep 2026 18:30:11 +0300
+Subject: [PATCH] fix: Clear stale zstream pointers when releasing the inflate
+ stream
+
+The zstream buffer pointers and counters are all cleared on acquisition
+in `png_inflate_claim`, but only `next_in` and `avail_in` were cleared
+on release in `png_read_finish_IDAT`, and none were cleared on release
+in the chunk decompression paths.
+
+If `png_read_end` is called before row reading starts, the IDAT stream
+is never claimed. Previously, a leftover non-zero `avail_in` caused the
+refill in `png_read_IDAT_data` to be skipped, and inflation continued
+through a stale `next_in` into an input buffer that may since have been
+deallocated.
+
+Introduce the function `png_inflate_detach_buffers` to clear the
+pointers and the counters of zstream input and output buffers on both
+acquisition and release. Although clearing `next_out` and `avail_out`
+is not currently necessary at any call site, it makes release mirror
+acquisition at a negligible cost paid once for each zlib stream.
+
+This is a cherry-pick of commit 6c7783b151377f591c83955e23da50991ad1a600
+from branch 'libpng18'.
+
+Reported-by: Ze Sheng <OwenSanzas@users.noreply.github.com>
+Reported-by: JasonHonKL <JasonHonKL@users.noreply.github.com>
+
+CVE: CVE-2026-46675
+Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/aa77ef38c17ab2fc1b41bec09fb973c6a386641d]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ pngrutil.c | 33 +++++++++++++++++++--------------
+ 1 file changed, 19 insertions(+), 14 deletions(-)
+
+diff --git a/pngrutil.c b/pngrutil.c
+index 551395168..482f0ae8d 100644
+--- a/pngrutil.c
++++ b/pngrutil.c
+@@ -332,6 +332,18 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
+ }
+ #endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
+ 
++/* Detach the zstream from the input and output buffers left by
++ * the current or a previous owner, and possibly deallocated since.
++ */
++static void
++png_inflate_detach_buffers(png_structrp png_ptr)
++{
++   png_ptr->zstream.next_in = NULL;
++   png_ptr->zstream.avail_in = 0;
++   png_ptr->zstream.next_out = NULL;
++   png_ptr->zstream.avail_out = 0;
++}
++
+ /* png_inflate_claim: claim the zstream for some nefarious purpose that involves
+  * decompression.  Returns Z_OK on success, else a zlib error code.  It checks
+  * the owner but, in final release builds, just issues a warning if some other
+@@ -392,13 +404,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
+ 
+ #endif /* ZLIB_VERNUM >= 0x1240 */
+ 
+-      /* Set this for safety, just in case the previous owner left pointers to
+-       * memory allocations.
+-       */
+-      png_ptr->zstream.next_in = NULL;
+-      png_ptr->zstream.avail_in = 0;
+-      png_ptr->zstream.next_out = NULL;
+-      png_ptr->zstream.avail_out = 0;
++      png_inflate_detach_buffers(png_ptr);
+ 
+       if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+       {
+@@ -744,7 +750,8 @@ png_decompress_chunk(png_structrp png_ptr,
+          else if (ret == Z_OK)
+             ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ 
+-         /* Release the claimed stream */
++         /* Release the claimed stream. */
++         png_inflate_detach_buffers(png_ptr);
+          png_ptr->zowner = 0;
+       }
+ 
+@@ -1569,6 +1576,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+                                     if (errmsg == NULL)
+                                     {
++                                       png_inflate_detach_buffers(png_ptr);
+                                        png_ptr->zowner = 0;
+                                        return;
+                                     }
+@@ -1595,7 +1603,8 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                else /* profile truncated */
+                   errmsg = png_ptr->zstream.msg;
+ 
+-               /* Release the stream */
++               /* Release the claimed stream. */
++               png_inflate_detach_buffers(png_ptr);
+                png_ptr->zowner = 0;
+             }
+ 
+@@ -4294,11 +4303,7 @@ png_read_finish_IDAT(png_structrp png_ptr)
+     */
+    if (png_ptr->zowner == png_IDAT)
+    {
+-      /* Always do this; the pointers otherwise point into the read buffer. */
+-      png_ptr->zstream.next_in = NULL;
+-      png_ptr->zstream.avail_in = 0;
+-
+-      /* Now we no longer own the zstream. */
++      png_inflate_detach_buffers(png_ptr);
+       png_ptr->zowner = 0;
+ 
+       /* The slightly weird semantics of the sequential IDAT reading is that we
diff --git a/meta/recipes-multimedia/libpng/libpng_1.6.42.bb b/meta/recipes-multimedia/libpng/libpng_1.6.42.bb
index f375aa5f4e9..8e7f9d8f8ec 100644
--- a/meta/recipes-multimedia/libpng/libpng_1.6.42.bb
+++ b/meta/recipes-multimedia/libpng/libpng_1.6.42.bb
@@ -32,6 +32,7 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/project/${BPN}/${BPN}${LIBV}/${PV}/${BP}.tar.xz
            file://CVE-2026-34757_p1.patch \
            file://CVE-2026-34757_p2.patch \
            file://CVE-2026-33416-05.patch \
+           file://CVE-2026-46675.patch \
 "
 
 SRC_URI[sha256sum] = "c919dbc11f4c03b05aba3f8884d8eb7adfe3572ad228af972bb60057bdb48450"
