diff --git a/SOURCES/rhbz-1956853.patch b/SOURCES/rhbz-1956853.patch new file mode 100644 index 0000000..eb9e93c --- /dev/null +++ b/SOURCES/rhbz-1956853.patch @@ -0,0 +1,42 @@ +diff --git a/src/mux/muxread.c b/src/mux/muxread.c +index 0b55286..eb5070b 100644 +--- a/src/mux/muxread.c ++++ b/src/mux/muxread.c + +@@ -187,7 +187,7 @@ + size = bitstream->size; + + if (data == NULL) return NULL; +- if (size < RIFF_HEADER_SIZE) return NULL; ++ if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL; + if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') || + GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) { + return NULL; +@@ -196,8 +196,6 @@ + mux = WebPMuxNew(); + if (mux == NULL) return NULL; + +- if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err; +- + tag = GetLE32(data + RIFF_HEADER_SIZE); + if (tag != kChunks[IDX_VP8].tag && + tag != kChunks[IDX_VP8L].tag && +@@ -206,12 +204,11 @@ + } + + riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE)); +- if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) { +- goto Err; +- } else { +- if (riff_size < size) { // Redundant data after last chunk. +- size = riff_size; // To make sure we don't read any data beyond mux_size. +- } ++ if (riff_size < CHUNK_HEADER_SIZE) goto Err; ++ if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) goto Err; ++ // There's no point in reading past the end of the RIFF chunk. ++ if (size > riff_size + CHUNK_HEADER_SIZE) { ++ size = riff_size + CHUNK_HEADER_SIZE; + } + + end = data + size; + diff --git a/SOURCES/rhbz-1956856.patch b/SOURCES/rhbz-1956856.patch new file mode 100644 index 0000000..f13e4b9 --- /dev/null +++ b/SOURCES/rhbz-1956856.patch @@ -0,0 +1,61 @@ +diff --git a/src/mux/muxi.h b/src/mux/muxi.h +index 6b57eea..14fd6e2 100644 +--- a/src/mux/muxi.h ++++ b/src/mux/muxi.h + +@@ -14,6 +14,7 @@ + #ifndef WEBP_MUX_MUXI_H_ + #define WEBP_MUX_MUXI_H_ + ++#include + #include + #include "src/dec/vp8i_dec.h" + #include "src/dec/vp8li_dec.h" +@@ -143,13 +144,13 @@ + + // Returns size of the chunk including chunk header and padding byte (if any). + static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { ++ assert(chunk_size <= MAX_CHUNK_PAYLOAD); + return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); + } + + // Size of a chunk including header and padding. + static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { + const size_t data_size = chunk->data_.size; +- assert(data_size < MAX_CHUNK_PAYLOAD); + return SizeWithPadding(data_size); + } + + +diff --git a/src/mux/muxread.c b/src/mux/muxread.c +index eb5070b..ef50dae 100644 +--- a/src/mux/muxread.c ++++ b/src/mux/muxread.c + +@@ -59,6 +59,7 @@ + // Sanity checks. + if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; + chunk_size = GetLE32(data + TAG_SIZE); ++ if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA; + + { + const size_t chunk_disk_size = SizeWithPadding(chunk_size); +@@ -203,9 +204,14 @@ + goto Err; // First chunk should be VP8, VP8L or VP8X. + } + +- riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE)); ++ riff_size = GetLE32(data + TAG_SIZE); ++ if (riff_size > MAX_CHUNK_PAYLOAD) goto Err; ++ ++ // Note this padding is historical and differs from demux.c which does not ++ // pad the file size. ++ riff_size = SizeWithPadding(riff_size); + if (riff_size < CHUNK_HEADER_SIZE) goto Err; +- if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) goto Err; ++ if (riff_size > size) goto Err; + // There's no point in reading past the end of the RIFF chunk. + if (size > riff_size + CHUNK_HEADER_SIZE) { + size = riff_size + CHUNK_HEADER_SIZE; + + diff --git a/SOURCES/rhbz-1956868.patch b/SOURCES/rhbz-1956868.patch new file mode 100644 index 0000000..ee98fca --- /dev/null +++ b/SOURCES/rhbz-1956868.patch @@ -0,0 +1,213 @@ +diff -up libwebp-1.0.0/src/dec/vp8l_dec.c.old libwebp-1.0.0/src/dec/vp8l_dec.c +--- libwebp-1.0.0/src/dec/vp8l_dec.c.old 2018-04-21 05:04:55.000000000 +0200 ++++ libwebp-1.0.0/src/dec/vp8l_dec.c 2018-11-09 00:29:51.000000000 +0100 +@@ -362,12 +362,19 @@ static int ReadHuffmanCodes(VP8LDecoder* + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* huffman_image = NULL; + HTreeGroup* htree_groups = NULL; ++ // When reading htrees, some might be unused, as the format allows it. ++ // We will still read them but put them in this htree_group_bogus. ++ HTreeGroup htree_group_bogus; + HuffmanCode* huffman_tables = NULL; ++ HuffmanCode* huffman_tables_bogus = NULL; + HuffmanCode* next = NULL; + int num_htree_groups = 1; ++ int num_htree_groups_max = 1; + int max_alphabet_size = 0; + int* code_lengths = NULL; + const int table_size = kTableSize[color_cache_bits]; ++ int* mapping = NULL; ++ int ok = 0; + + if (allow_recursion && VP8LReadBits(br, 1)) { + // use meta Huffman codes. +@@ -384,10 +391,42 @@ static int ReadHuffmanCodes(VP8LDecoder* + // The huffman data is stored in red and green bytes. + const int group = (huffman_image[i] >> 8) & 0xffff; + huffman_image[i] = group; +- if (group >= num_htree_groups) { +- num_htree_groups = group + 1; ++ if (group >= num_htree_groups_max) { ++ num_htree_groups_max = group + 1; + } + } ++ // Check the validity of num_htree_groups_max. If it seems too big, use a ++ // smaller value for later. This will prevent big memory allocations to end ++ // up with a bad bitstream anyway. ++ // The value of 1000 is totally arbitrary. We know that num_htree_groups_max ++ // is smaller than (1 << 16) and should be smaller than the number of pixels ++ // (though the format allows it to be bigger). ++ if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) { ++ // Create a mapping from the used indices to the minimal set of used ++ // values [0, num_htree_groups) ++ mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); ++ if (mapping == NULL) { ++ dec->status_ = VP8_STATUS_OUT_OF_MEMORY; ++ goto Error; ++ } ++ // -1 means a value is unmapped, and therefore unused in the Huffman ++ // image. ++ memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping)); ++ for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) { ++ // Get the current mapping for the group and remap the Huffman image. ++ int* const mapped_group = &mapping[huffman_image[i]]; ++ if (*mapped_group == -1) *mapped_group = num_htree_groups++; ++ huffman_image[i] = *mapped_group; ++ } ++ huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc( ++ table_size, sizeof(*huffman_tables_bogus)); ++ if (huffman_tables_bogus == NULL) { ++ dec->status_ = VP8_STATUS_OUT_OF_MEMORY; ++ goto Error; ++ } ++ } else { ++ num_htree_groups = num_htree_groups_max; ++ } + } + + if (br->eos_) goto Error; +@@ -403,11 +442,11 @@ static int ReadHuffmanCodes(VP8LDecoder* + } + } + ++ code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, ++ sizeof(*code_lengths)); + huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, + sizeof(*huffman_tables)); + htree_groups = VP8LHtreeGroupsNew(num_htree_groups); +- code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, +- sizeof(*code_lengths)); + + if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; +@@ -415,28 +454,35 @@ static int ReadHuffmanCodes(VP8LDecoder* + } + + next = huffman_tables; +- for (i = 0; i < num_htree_groups; ++i) { +- HTreeGroup* const htree_group = &htree_groups[i]; ++ for (i = 0; i < num_htree_groups_max; ++i) { ++ // If the index "i" is unused in the Huffman image, read the coefficients ++ // but store them to a bogus htree_group. ++ const int is_bogus = (mapping != NULL && mapping[i] == -1); ++ HTreeGroup* const htree_group = ++ is_bogus ? &htree_group_bogus : ++ &htree_groups[(mapping == NULL) ? i : mapping[i]]; + HuffmanCode** const htrees = htree_group->htrees; ++ HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next; + int size; + int total_size = 0; + int is_trivial_literal = 1; + int max_bits = 0; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; +- htrees[j] = next; ++ htrees[j] = huffman_tables_i; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += 1 << color_cache_bits; + } +- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); ++ size = ++ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i); + if (size == 0) { + goto Error; + } + if (is_trivial_literal && kLiteralMap[j] == 1) { +- is_trivial_literal = (next->bits == 0); ++ is_trivial_literal = (huffman_tables_i->bits == 0); + } +- total_size += next->bits; +- next += size; ++ total_size += huffman_tables_i->bits; ++ huffman_tables_i += size; + if (j <= ALPHA) { + int local_max_bits = code_lengths[0]; + int k; +@@ -448,38 +494,41 @@ static int ReadHuffmanCodes(VP8LDecoder* + max_bits += local_max_bits; + } + } ++ if (!is_bogus) next = huffman_tables_i; + htree_group->is_trivial_literal = is_trivial_literal; + htree_group->is_trivial_code = 0; + if (is_trivial_literal) { + const int red = htrees[RED][0].value; + const int blue = htrees[BLUE][0].value; + const int alpha = htrees[ALPHA][0].value; +- htree_group->literal_arb = +- ((uint32_t)alpha << 24) | (red << 16) | blue; ++ htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; + if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { + htree_group->is_trivial_code = 1; + htree_group->literal_arb |= htrees[GREEN][0].value << 8; + } + } +- htree_group->use_packed_table = !htree_group->is_trivial_code && +- (max_bits < HUFFMAN_PACKED_BITS); ++ htree_group->use_packed_table = ++ !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); + if (htree_group->use_packed_table) BuildPackedTable(htree_group); + } +- WebPSafeFree(code_lengths); ++ ok = 1; + +- // All OK. Finalize pointers and return. ++ // All OK. Finalize pointers. + hdr->huffman_image_ = huffman_image; + hdr->num_htree_groups_ = num_htree_groups; + hdr->htree_groups_ = htree_groups; + hdr->huffman_tables_ = huffman_tables; +- return 1; + + Error: + WebPSafeFree(code_lengths); +- WebPSafeFree(huffman_image); +- WebPSafeFree(huffman_tables); +- VP8LHtreeGroupsFree(htree_groups); +- return 0; ++ WebPSafeFree(huffman_tables_bogus); ++ WebPSafeFree(mapping); ++ if (!ok) { ++ WebPSafeFree(huffman_image); ++ WebPSafeFree(huffman_tables); ++ VP8LHtreeGroupsFree(htree_groups); ++ } ++ return ok; + } + + //------------------------------------------------------------------------------ +@@ -884,7 +933,11 @@ static WEBP_INLINE void CopyBlock8b(uint + #endif + break; + case 2: ++#if !defined(WORDS_BIGENDIAN) + memcpy(&pattern, src, sizeof(uint16_t)); ++#else ++ pattern = ((uint32_t)src[0] << 8) | src[1]; ++#endif + #if defined(__arm__) || defined(_M_ARM) + pattern |= pattern << 16; + #elif defined(WEBP_USE_MIPS_DSP_R2) +@@ -1523,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* c + if (dec == NULL) return 0; + + assert(alph_dec != NULL); +- alph_dec->vp8l_dec_ = dec; + + dec->width_ = alph_dec->width_; + dec->height_ = alph_dec->height_; +@@ -1555,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* c + + if (!ok) goto Err; + ++ // Only set here, once we are sure it is valid (to avoid thread races). ++ alph_dec->vp8l_dec_ = dec; + return 1; + + Err: +- VP8LDelete(alph_dec->vp8l_dec_); +- alph_dec->vp8l_dec_ = NULL; ++ VP8LDelete(dec); + return 0; + } + diff --git a/SOURCES/rhbz-1956917.patch b/SOURCES/rhbz-1956917.patch new file mode 100644 index 0000000..c9aca87 --- /dev/null +++ b/SOURCES/rhbz-1956917.patch @@ -0,0 +1,14 @@ +diff --git a/src/mux/muxread.c b/src/mux/muxread.c +index fbe9f05..ea07dbf 100644 +--- a/src/mux/muxread.c ++++ b/src/mux/muxread.c + +@@ -264,6 +264,7 @@ + chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk. + if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err; + if (id == WEBP_CHUNK_VP8X) { // grab global specs ++ if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err; + mux->canvas_width_ = GetLE24(data + 12) + 1; + mux->canvas_height_ = GetLE24(data + 15) + 1; + } + diff --git a/SPECS/libwebp.spec b/SPECS/libwebp.spec index bff6cbe..be33260 100644 --- a/SPECS/libwebp.spec +++ b/SPECS/libwebp.spec @@ -2,7 +2,7 @@ Name: libwebp Version: 1.0.0 -Release: 3%{?dist} +Release: 5%{?dist} URL: http://webmproject.org/ Summary: Library and tools for the WebP graphics format # Additional IPR is licensed as well. See PATENTS file for details @@ -12,6 +12,10 @@ Source1: libwebp_jni_example.java Patch0: rhbz-1956829.patch Patch1: rhbz-1956843.patch Patch2: rhbz-1956919.patch +Patch3: rhbz-1956853.patch +Patch4: rhbz-1956856.patch +Patch5: rhbz-1956917.patch +Patch6: rhbz-1956868.patch BuildRequires: libjpeg-devel BuildRequires: libpng-devel @@ -143,6 +147,9 @@ cp swig/*.jar swig/*.so %{buildroot}/%{_libdir}/%{name}-java/ %changelog +* Thu May 27 2021 Martin Stransky - 1.0.0-5 +- Added fixes for rhbz#1956853, rhbz#1956856, rhbz#1956868, rhbz#1956917 + * Mon May 17 2021 Martin Stransky - 1.0.0-3 - Added fixes for rhbz#1956829, rhbz#1956843, rhbz#1956919