diff options
| author | Peter Marko <peter.marko@siemens.com> | 2025-11-27 19:03:45 +0100 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2025-12-05 06:56:34 -0800 |
| commit | d4925371886786849fe0e4408aaf285cf3c5e04b (patch) | |
| tree | dc67f024c5562fb6e904dadd9d2a6ff0ddb26a97 | |
| parent | 052e4214aaf17308023e7b91286bc18f407217cc (diff) | |
| download | poky-d4925371886786849fe0e4408aaf285cf3c5e04b.tar.gz | |
libpng: patch CVE-2025-64505
Pick commit per NVD report.
Add two patches to apply it cleanly.
(From OE-Core rev: 1470546924765d134c83b50e62974f048614b121)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
4 files changed, 329 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/libpng/files/CVE-2025-64505-01.patch b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-01.patch new file mode 100644 index 0000000000..c8ca222d14 --- /dev/null +++ b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-01.patch | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | From 0fa3c0f698c2ca618a0fa44e10a822678df85373 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Cosmin Truta <ctruta@gmail.com> | ||
| 3 | Date: Thu, 15 Feb 2024 21:53:24 +0200 | ||
| 4 | Subject: [PATCH] chore: Clean up the spurious uses of `sizeof(png_byte)`; fix | ||
| 5 | the manual | ||
| 6 | |||
| 7 | By definition, `sizeof(png_byte)` is 1. | ||
| 8 | |||
| 9 | Remove all the occurences of `sizeof(png_byte)` from the code, and fix | ||
| 10 | a related typo in the libpng manual. | ||
| 11 | |||
| 12 | Also update the main .editorconfig file to reflect the fixing expected | ||
| 13 | by a FIXME note. | ||
| 14 | |||
| 15 | CVE: CVE-2025-64505 | ||
| 16 | Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/0fa3c0f698c2ca618a0fa44e10a822678df85373] | ||
| 17 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 18 | --- | ||
| 19 | libpng-manual.txt | 4 ++-- | ||
| 20 | libpng.3 | 4 ++-- | ||
| 21 | pngrtran.c | 17 +++++++---------- | ||
| 22 | 3 files changed, 11 insertions(+), 14 deletions(-) | ||
| 23 | |||
| 24 | diff --git a/libpng-manual.txt b/libpng-manual.txt | ||
| 25 | index eb24ef483..d2918ce31 100644 | ||
| 26 | --- a/libpng-manual.txt | ||
| 27 | +++ b/libpng-manual.txt | ||
| 28 | @@ -1180,11 +1180,11 @@ where row_pointers is an array of pointers to the pixel data for each row: | ||
| 29 | If you know your image size and pixel size ahead of time, you can allocate | ||
| 30 | row_pointers prior to calling png_read_png() with | ||
| 31 | |||
| 32 | - if (height > PNG_UINT_32_MAX/(sizeof (png_byte))) | ||
| 33 | + if (height > PNG_UINT_32_MAX / (sizeof (png_bytep))) | ||
| 34 | png_error (png_ptr, | ||
| 35 | "Image is too tall to process in memory"); | ||
| 36 | |||
| 37 | - if (width > PNG_UINT_32_MAX/pixel_size) | ||
| 38 | + if (width > PNG_UINT_32_MAX / pixel_size) | ||
| 39 | png_error (png_ptr, | ||
| 40 | "Image is too wide to process in memory"); | ||
| 41 | |||
| 42 | diff --git a/libpng.3 b/libpng.3 | ||
| 43 | index 57d06f2db..8875b219a 100644 | ||
| 44 | --- a/libpng.3 | ||
| 45 | +++ b/libpng.3 | ||
| 46 | @@ -1699,11 +1699,11 @@ where row_pointers is an array of pointers to the pixel data for each row: | ||
| 47 | If you know your image size and pixel size ahead of time, you can allocate | ||
| 48 | row_pointers prior to calling png_read_png() with | ||
| 49 | |||
| 50 | - if (height > PNG_UINT_32_MAX/(sizeof (png_byte))) | ||
| 51 | + if (height > PNG_UINT_32_MAX / (sizeof (png_bytep))) | ||
| 52 | png_error (png_ptr, | ||
| 53 | "Image is too tall to process in memory"); | ||
| 54 | |||
| 55 | - if (width > PNG_UINT_32_MAX/pixel_size) | ||
| 56 | + if (width > PNG_UINT_32_MAX / pixel_size) | ||
| 57 | png_error (png_ptr, | ||
| 58 | "Image is too wide to process in memory"); | ||
| 59 | |||
| 60 | diff --git a/pngrtran.c b/pngrtran.c | ||
| 61 | index 74cca476b..041f9306c 100644 | ||
| 62 | --- a/pngrtran.c | ||
| 63 | +++ b/pngrtran.c | ||
| 64 | @@ -441,7 +441,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 65 | int i; | ||
| 66 | |||
| 67 | png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, | ||
| 68 | - (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); | ||
| 69 | + (png_alloc_size_t)num_palette); | ||
| 70 | for (i = 0; i < num_palette; i++) | ||
| 71 | png_ptr->quantize_index[i] = (png_byte)i; | ||
| 72 | } | ||
| 73 | @@ -458,7 +458,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 74 | |||
| 75 | /* Initialize an array to sort colors */ | ||
| 76 | png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, | ||
| 77 | - (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); | ||
| 78 | + (png_alloc_size_t)num_palette); | ||
| 79 | |||
| 80 | /* Initialize the quantize_sort array */ | ||
| 81 | for (i = 0; i < num_palette; i++) | ||
| 82 | @@ -592,11 +592,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 83 | |||
| 84 | /* Initialize palette index arrays */ | ||
| 85 | png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, | ||
| 86 | - (png_alloc_size_t)((png_uint_32)num_palette * | ||
| 87 | - (sizeof (png_byte)))); | ||
| 88 | + (png_alloc_size_t)num_palette); | ||
| 89 | png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, | ||
| 90 | - (png_alloc_size_t)((png_uint_32)num_palette * | ||
| 91 | - (sizeof (png_byte)))); | ||
| 92 | + (png_alloc_size_t)num_palette); | ||
| 93 | |||
| 94 | /* Initialize the sort array */ | ||
| 95 | for (i = 0; i < num_palette; i++) | ||
| 96 | @@ -761,12 +759,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 97 | size_t num_entries = ((size_t)1 << total_bits); | ||
| 98 | |||
| 99 | png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, | ||
| 100 | - (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); | ||
| 101 | + (png_alloc_size_t)(num_entries)); | ||
| 102 | |||
| 103 | - distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * | ||
| 104 | - (sizeof (png_byte)))); | ||
| 105 | + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries); | ||
| 106 | |||
| 107 | - memset(distance, 0xff, num_entries * (sizeof (png_byte))); | ||
| 108 | + memset(distance, 0xff, num_entries); | ||
| 109 | |||
| 110 | for (i = 0; i < num_palette; i++) | ||
| 111 | { | ||
diff --git a/meta/recipes-multimedia/libpng/files/CVE-2025-64505-02.patch b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-02.patch new file mode 100644 index 0000000000..5a3e50b642 --- /dev/null +++ b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-02.patch | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | From ea094764f3436e3c6524622724c2d342a3eff235 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Cosmin Truta <ctruta@gmail.com> | ||
| 3 | Date: Sat, 8 Nov 2025 17:16:59 +0200 | ||
| 4 | Subject: [PATCH] Fix a memory leak in function `png_set_quantize`; refactor | ||
| 5 | |||
| 6 | Release the previously-allocated array `quantize_index` before | ||
| 7 | reallocating it. This avoids leaking memory when the function | ||
| 8 | `png_set_quantize` is called multiple times on the same `png_struct`. | ||
| 9 | |||
| 10 | This function assumed single-call usage, but fuzzing revealed that | ||
| 11 | repeated calls would overwrite the pointers without freeing the | ||
| 12 | original allocations, leaking 256 bytes per call for `quantize_index` | ||
| 13 | and additional memory for `quantize_sort` when histogram-based | ||
| 14 | quantization is used. | ||
| 15 | |||
| 16 | Also remove the array `quantize_sort` from the list of `png_struct` | ||
| 17 | members and make it a local variable. This array is initialized, | ||
| 18 | used and released exclusively inside the function `png_set_quantize`. | ||
| 19 | |||
| 20 | Reported-by: Samsung-PENTEST <Samsung-PENTEST@users.noreply.github.com> | ||
| 21 | Analyzed-by: degrigis <degrigis@users.noreply.github.com> | ||
| 22 | Reviewed-by: John Bowler <jbowler@acm.org> | ||
| 23 | |||
| 24 | CVE: CVE-2025-64505 | ||
| 25 | Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/ea094764f3436e3c6524622724c2d342a3eff235] | ||
| 26 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 27 | --- | ||
| 28 | pngrtran.c | 43 +++++++++++++++++++++++-------------------- | ||
| 29 | pngstruct.h | 1 - | ||
| 30 | 2 files changed, 23 insertions(+), 21 deletions(-) | ||
| 31 | |||
| 32 | diff --git a/pngrtran.c b/pngrtran.c | ||
| 33 | index 1809db704..4632dd521 100644 | ||
| 34 | --- a/pngrtran.c | ||
| 35 | +++ b/pngrtran.c | ||
| 36 | @@ -440,6 +440,12 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 37 | { | ||
| 38 | int i; | ||
| 39 | |||
| 40 | + /* Initialize the array to index colors. | ||
| 41 | + * | ||
| 42 | + * Be careful to avoid leaking memory. Applications are allowed to call | ||
| 43 | + * this function more than once per png_struct. | ||
| 44 | + */ | ||
| 45 | + png_free(png_ptr, png_ptr->quantize_index); | ||
| 46 | png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, | ||
| 47 | (png_alloc_size_t)num_palette); | ||
| 48 | for (i = 0; i < num_palette; i++) | ||
| 49 | @@ -454,15 +460,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 50 | * Perhaps not the best solution, but good enough. | ||
| 51 | */ | ||
| 52 | |||
| 53 | - int i; | ||
| 54 | + png_bytep quantize_sort; | ||
| 55 | + int i, j; | ||
| 56 | |||
| 57 | - /* Initialize an array to sort colors */ | ||
| 58 | - png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, | ||
| 59 | + /* Initialize the local array to sort colors. */ | ||
| 60 | + quantize_sort = (png_bytep)png_malloc(png_ptr, | ||
| 61 | (png_alloc_size_t)num_palette); | ||
| 62 | - | ||
| 63 | - /* Initialize the quantize_sort array */ | ||
| 64 | for (i = 0; i < num_palette; i++) | ||
| 65 | - png_ptr->quantize_sort[i] = (png_byte)i; | ||
| 66 | + quantize_sort[i] = (png_byte)i; | ||
| 67 | |||
| 68 | /* Find the least used palette entries by starting a | ||
| 69 | * bubble sort, and running it until we have sorted | ||
| 70 | @@ -474,19 +479,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 71 | for (i = num_palette - 1; i >= maximum_colors; i--) | ||
| 72 | { | ||
| 73 | int done; /* To stop early if the list is pre-sorted */ | ||
| 74 | - int j; | ||
| 75 | |||
| 76 | done = 1; | ||
| 77 | for (j = 0; j < i; j++) | ||
| 78 | { | ||
| 79 | - if (histogram[png_ptr->quantize_sort[j]] | ||
| 80 | - < histogram[png_ptr->quantize_sort[j + 1]]) | ||
| 81 | + if (histogram[quantize_sort[j]] | ||
| 82 | + < histogram[quantize_sort[j + 1]]) | ||
| 83 | { | ||
| 84 | png_byte t; | ||
| 85 | |||
| 86 | - t = png_ptr->quantize_sort[j]; | ||
| 87 | - png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; | ||
| 88 | - png_ptr->quantize_sort[j + 1] = t; | ||
| 89 | + t = quantize_sort[j]; | ||
| 90 | + quantize_sort[j] = quantize_sort[j + 1]; | ||
| 91 | + quantize_sort[j + 1] = t; | ||
| 92 | done = 0; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | @@ -498,18 +502,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 96 | /* Swap the palette around, and set up a table, if necessary */ | ||
| 97 | if (full_quantize != 0) | ||
| 98 | { | ||
| 99 | - int j = num_palette; | ||
| 100 | + j = num_palette; | ||
| 101 | |||
| 102 | /* Put all the useful colors within the max, but don't | ||
| 103 | * move the others. | ||
| 104 | */ | ||
| 105 | for (i = 0; i < maximum_colors; i++) | ||
| 106 | { | ||
| 107 | - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) | ||
| 108 | + if ((int)quantize_sort[i] >= maximum_colors) | ||
| 109 | { | ||
| 110 | do | ||
| 111 | j--; | ||
| 112 | - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); | ||
| 113 | + while ((int)quantize_sort[j] >= maximum_colors); | ||
| 114 | |||
| 115 | palette[i] = palette[j]; | ||
| 116 | } | ||
| 117 | @@ -517,7 +521,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 118 | } | ||
| 119 | else | ||
| 120 | { | ||
| 121 | - int j = num_palette; | ||
| 122 | + j = num_palette; | ||
| 123 | |||
| 124 | /* Move all the used colors inside the max limit, and | ||
| 125 | * develop a translation table. | ||
| 126 | @@ -525,13 +529,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 127 | for (i = 0; i < maximum_colors; i++) | ||
| 128 | { | ||
| 129 | /* Only move the colors we need to */ | ||
| 130 | - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) | ||
| 131 | + if ((int)quantize_sort[i] >= maximum_colors) | ||
| 132 | { | ||
| 133 | png_color tmp_color; | ||
| 134 | |||
| 135 | do | ||
| 136 | j--; | ||
| 137 | - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); | ||
| 138 | + while ((int)quantize_sort[j] >= maximum_colors); | ||
| 139 | |||
| 140 | tmp_color = palette[j]; | ||
| 141 | palette[j] = palette[i]; | ||
| 142 | @@ -569,8 +573,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 143 | } | ||
| 144 | } | ||
| 145 | } | ||
| 146 | - png_free(png_ptr, png_ptr->quantize_sort); | ||
| 147 | - png_ptr->quantize_sort = NULL; | ||
| 148 | + png_free(png_ptr, quantize_sort); | ||
| 149 | } | ||
| 150 | else | ||
| 151 | { | ||
| 152 | diff --git a/pngstruct.h b/pngstruct.h | ||
| 153 | index 084422bc1..fe5fa0415 100644 | ||
| 154 | --- a/pngstruct.h | ||
| 155 | +++ b/pngstruct.h | ||
| 156 | @@ -413,7 +413,6 @@ struct png_struct_def | ||
| 157 | |||
| 158 | #ifdef PNG_READ_QUANTIZE_SUPPORTED | ||
| 159 | /* The following three members were added at version 1.0.14 and 1.2.4 */ | ||
| 160 | - png_bytep quantize_sort; /* working sort array */ | ||
| 161 | png_bytep index_to_palette; /* where the original index currently is | ||
| 162 | in the palette */ | ||
| 163 | png_bytep palette_to_index; /* which original index points to this | ||
diff --git a/meta/recipes-multimedia/libpng/files/CVE-2025-64505-03.patch b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-03.patch new file mode 100644 index 0000000000..ddda8678ce --- /dev/null +++ b/meta/recipes-multimedia/libpng/files/CVE-2025-64505-03.patch | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | From 6a528eb5fd0dd7f6de1c39d30de0e41473431c37 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Cosmin Truta <ctruta@gmail.com> | ||
| 3 | Date: Sat, 8 Nov 2025 23:58:26 +0200 | ||
| 4 | Subject: [PATCH] Fix a buffer overflow in `png_do_quantize` | ||
| 5 | |||
| 6 | Allocate the quantize_index array to PNG_MAX_PALETTE_LENGTH (256 bytes) | ||
| 7 | instead of num_palette bytes. This approach matches the allocation | ||
| 8 | pattern for `palette[]`, `trans_alpha[]` and `riffled_palette[]` which | ||
| 9 | were similarly oversized in libpng 1.2.1 to prevent buffer overflows | ||
| 10 | from malformed PNG files with out-of-range palette indices. | ||
| 11 | |||
| 12 | Out-of-range palette indices `index >= num_palette` will now read | ||
| 13 | identity-mapped values from the `quantize_index` array (where index N | ||
| 14 | maps to palette entry N). This prevents undefined behavior while | ||
| 15 | avoiding runtime bounds checking overhead in the performance-critical | ||
| 16 | pixel processing loop. | ||
| 17 | |||
| 18 | Reported-by: Samsung-PENTEST <Samsung-PENTEST@users.noreply.github.com> | ||
| 19 | Analyzed-by: degrigis <degrigis@users.noreply.github.com> | ||
| 20 | |||
| 21 | CVE: CVE-2025-64505 | ||
| 22 | Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/6a528eb5fd0dd7f6de1c39d30de0e41473431c37] | ||
| 23 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 24 | --- | ||
| 25 | pngrtran.c | 8 ++++++-- | ||
| 26 | 1 file changed, 6 insertions(+), 2 deletions(-) | ||
| 27 | |||
| 28 | diff --git a/pngrtran.c b/pngrtran.c | ||
| 29 | index 4632dd521..9c2475fde 100644 | ||
| 30 | --- a/pngrtran.c | ||
| 31 | +++ b/pngrtran.c | ||
| 32 | @@ -441,14 +441,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, | ||
| 33 | int i; | ||
| 34 | |||
| 35 | /* Initialize the array to index colors. | ||
| 36 | + * | ||
| 37 | + * Ensure quantize_index can fit 256 elements (PNG_MAX_PALETTE_LENGTH) | ||
| 38 | + * rather than num_palette elements. This is to prevent buffer overflows | ||
| 39 | + * caused by malformed PNG files with out-of-range palette indices. | ||
| 40 | * | ||
| 41 | * Be careful to avoid leaking memory. Applications are allowed to call | ||
| 42 | * this function more than once per png_struct. | ||
| 43 | */ | ||
| 44 | png_free(png_ptr, png_ptr->quantize_index); | ||
| 45 | png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, | ||
| 46 | - (png_alloc_size_t)num_palette); | ||
| 47 | - for (i = 0; i < num_palette; i++) | ||
| 48 | + PNG_MAX_PALETTE_LENGTH); | ||
| 49 | + for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++) | ||
| 50 | png_ptr->quantize_index[i] = (png_byte)i; | ||
| 51 | } | ||
| 52 | |||
diff --git a/meta/recipes-multimedia/libpng/libpng_1.6.39.bb b/meta/recipes-multimedia/libpng/libpng_1.6.39.bb index 011eec94a2..62e3e81b4f 100644 --- a/meta/recipes-multimedia/libpng/libpng_1.6.39.bb +++ b/meta/recipes-multimedia/libpng/libpng_1.6.39.bb | |||
| @@ -13,6 +13,9 @@ LIBV = "16" | |||
| 13 | SRC_URI = "\ | 13 | SRC_URI = "\ |
| 14 | ${SOURCEFORGE_MIRROR}/${BPN}/${BPN}${LIBV}/${BP}.tar.xz \ | 14 | ${SOURCEFORGE_MIRROR}/${BPN}/${BPN}${LIBV}/${BP}.tar.xz \ |
| 15 | file://run-ptest \ | 15 | file://run-ptest \ |
| 16 | file://CVE-2025-64505-01.patch \ | ||
| 17 | file://CVE-2025-64505-02.patch \ | ||
| 18 | file://CVE-2025-64505-03.patch \ | ||
| 16 | " | 19 | " |
| 17 | 20 | ||
| 18 | SRC_URI[sha256sum] = "1f4696ce70b4ee5f85f1e1623dc1229b210029fa4b7aee573df3e2ba7b036937" | 21 | SRC_URI[sha256sum] = "1f4696ce70b4ee5f85f1e1623dc1229b210029fa4b7aee573df3e2ba7b036937" |
