Firefox · Media
CVE-2026-12325
Logic Error in Media
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
media/libpng/apng.patchmedia/libpng/pngpread.c
Patch
diff --git a/media/libpng/apng.patch b/media/libpng/apng.patch
index 10fc0184851..a06964f0d37 100644
--- a/media/libpng/apng.patch
+++ b/media/libpng/apng.patch
@@ -132,7 +132,7 @@ diff --git a/png.h b/png.h
diff --git a/pngget.c b/pngget.c
--- a/pngget.c
+++ b/pngget.c
-@@ -1367,4 +1367,166 @@ png_get_palette_max(png_const_structp pn
+@@ -1366,4 +1366,166 @@ png_get_palette_max(png_const_structp pn
# endif
#endif
@@ -324,7 +324,7 @@ diff --git a/pnginfo.h b/pnginfo.h
diff --git a/pngpread.c b/pngpread.c
--- a/pngpread.c
+++ b/pngpread.c
-@@ -200,6 +200,89 @@ png_push_read_chunk(png_structrp png_ptr
+@@ -200,6 +200,90 @@ png_push_read_chunk(png_structrp png_ptr
chunk_name = png_ptr->chunk_name;
@@ -346,9 +346,6 @@ diff --git a/pngpread.c b/pngpread.c
+
+ else if (chunk_name == png_fdAT)
+ {
-+ PNG_PUSH_SAVE_BUFFER_IF_LT(4)
-+ png_ensure_sequence_number(png_ptr, 4);
-+
+ if ((png_ptr->mode & PNG_HAVE_fcTL) == 0)
+ {
+ /* Discard trailing fdATs for frames other than the first */
@@ -356,13 +353,17 @@ diff --git a/pngpread.c b/pngpread.c
+ png_error(png_ptr, "out of place fdAT");
+
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
-+ png_crc_finish(png_ptr, png_ptr->push_length);
++ png_ensure_sequence_number(png_ptr, png_ptr->push_length);
++ png_crc_finish(png_ptr, png_ptr->push_length - 4);
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ }
+
+ else
+ {
+ /* frame data follows */
++ PNG_PUSH_SAVE_BUFFER_IF_LT(4)
++
++ png_ensure_sequence_number(png_ptr, png_ptr->push_length);
+ png_ptr->idat_size = png_ptr->push_length - 4;
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
@@ -414,7 +415,7 @@ diff --git a/pngpread.c b/pngpread.c
if (chunk_name == png_IDAT)
{
if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
-@@ -260,6 +343,9 @@ png_push_read_chunk(png_structrp png_ptr
+@@ -268,6 +352,9 @@ png_push_read_chunk(png_structrp png_ptr
else if (chunk_name == png_IDAT)
{
@@ -424,7 +425,7 @@ diff --git a/pngpread.c b/pngpread.c
png_ptr->idat_size = png_ptr->push_length;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
-@@ -270,6 +356,20 @@ png_push_read_chunk(png_structrp png_ptr
+@@ -278,6 +365,20 @@ png_push_read_chunk(png_structrp png_ptr
return;
}
@@ -445,7 +446,7 @@ diff --git a/pngpread.c b/pngpread.c
else
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
-@@ -401,7 +501,11 @@ png_push_read_IDAT(png_structrp png_ptr)
+@@ -409,7 +510,11 @@ png_push_read_IDAT(png_structrp png_ptr)
png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
@@ -457,7 +458,7 @@ diff --git a/pngpread.c b/pngpread.c
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
-@@ -409,17 +513,60 @@ png_push_read_IDAT(png_structrp png_ptr)
+@@ -417,17 +522,60 @@ png_push_read_IDAT(png_structrp png_ptr)
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
@@ -511,14 +512,14 @@ diff --git a/pngpread.c b/pngpread.c
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->num_frames_read > 0)
+ {
-+ png_ensure_sequence_number(png_ptr, 4);
++ png_ensure_sequence_number(png_ptr, png_ptr->push_length);
+ png_ptr->idat_size -= 4;
+ }
+#endif
}
if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
-@@ -493,6 +640,16 @@ png_process_IDAT_data(png_structrp png_p
+@@ -501,6 +649,16 @@ png_process_IDAT_data(png_structrp png_p
if (!(buffer_length > 0) || buffer == NULL)
png_error(png_ptr, "No IDAT data (internal error)");
@@ -535,7 +536,7 @@ diff --git a/pngpread.c b/pngpread.c
/* This routine must process all the data it has been given
* before returning, calling the row callback as required to
* handle the uncompressed results.
-@@ -926,6 +1083,18 @@ png_set_progressive_read_fn(png_structrp
+@@ -934,6 +1092,18 @@ png_set_progressive_read_fn(png_structrp
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
}
@@ -557,7 +558,7 @@ diff --git a/pngpread.c b/pngpread.c
diff --git a/pngpriv.h b/pngpriv.h
--- a/pngpriv.h
+++ b/pngpriv.h
-@@ -620,6 +620,10 @@
+@@ -653,6 +653,10 @@
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
#define PNG_WROTE_eXIf 0x4000U
#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */
@@ -568,7 +569,7 @@ diff --git a/pngpriv.h b/pngpriv.h
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001U
-@@ -884,6 +888,16 @@
+@@ -917,6 +921,16 @@
#define png_tRNS PNG_U32(116, 82, 78, 83)
#define png_zTXt PNG_U32(122, 84, 88, 116)
@@ -585,8 +586,8 @@ diff --git a/pngpriv.h b/pngpriv.h
/* The following will work on (signed char*) strings, whereas the get_uint_32
* macro will fail on top-bit-set values because of the sign extension.
*/
-@@ -1671,6 +1685,49 @@ PNG_INTERNAL_FUNCTION(void,png_read_push
- PNG_EMPTY);
+@@ -1880,6 +1894,49 @@ PNG_INTERNAL_FUNCTION(void, png_read_pus
+ PNG_EMPTY);
#endif /* PROGRESSIVE_READ */
+#ifdef PNG_APNG_SUPPORTED
@@ -638,7 +639,7 @@ diff --git a/pngpriv.h b/pngpriv.h
diff --git a/pngread.c b/pngread.c
--- a/pngread.c
+++ b/pngread.c
-@@ -155,16 +155,96 @@ png_read_info(png_structrp png_ptr, png_
+@@ -157,16 +157,96 @@ png_read_info(png_structrp png_ptr, png_
else if (chunk_name == png_IDAT)
{
@@ -750,7 +751,7 @@ diff --git a/pngrutil.c b/pngrutil.c
/* Set internal variables */
png_ptr->width = width;
png_ptr->height = height;
-@@ -2730,6 +2735,180 @@ png_handle_iTXt(png_structrp png_ptr, pn
+@@ -2706,6 +2711,180 @@ png_handle_iTXt(png_structrp png_ptr, pn
# define png_handle_iTXt NULL
#endif
@@ -931,7 +932,7 @@ diff --git a/pngrutil.c b/pngrutil.c
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
static int
-@@ -4213,6 +4392,38 @@ png_read_IDAT_data(png_structrp png_ptr,
+@@ -4189,6 +4368,38 @@ png_read_IDAT_data(png_structrp png_ptr,
uInt avail_in;
png_bytep buffer;
@@ -970,7 +971,7 @@ diff --git a/pngrutil.c b/pngrutil.c
while (png_ptr->idat_size == 0)
{
png_crc_finish(png_ptr, 0);
-@@ -4224,6 +4435,7 @@ png_read_IDAT_data(png_structrp png_ptr,
+@@ -4200,6 +4411,7 @@ png_read_IDAT_data(png_structrp png_ptr,
if (png_ptr->chunk_name != png_IDAT)
png_error(png_ptr, "Not enough image data");
}
@@ -978,7 +979,7 @@ diff --git a/pngrutil.c b/pngrutil.c
avail_in = png_ptr->IDAT_read_size;
-@@ -4295,6 +4507,9 @@ png_read_IDAT_data(png_structrp png_ptr,
+@@ -4271,6 +4483,9 @@ png_read_IDAT_data(png_structrp png_ptr,
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
@@ -988,7 +989,7 @@ diff --git a/pngrutil.c b/pngrutil.c
if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
png_chunk_benign_error(png_ptr, "Extra compressed data");
-@@ -4704,4 +4919,80 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED
+@@ -4680,4 +4895,80 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
@@ -1072,7 +1073,7 @@ diff --git a/pngrutil.c b/pngrutil.c
diff --git a/pngset.c b/pngset.c
--- a/pngset.c
+++ b/pngset.c
Loading diff…
References
On This Page