Compare commits
10 Commits
8e54c44c7e
...
e8f675e9b5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8f675e9b5 | ||
|
|
ce1617294c | ||
|
|
005daf16e2 | ||
|
|
3a66d465e2 | ||
|
|
36e9295941 | ||
|
|
c1db22667e | ||
|
|
d2d8421e71 | ||
|
|
5ac8489df1 | ||
|
|
66c033e743 | ||
|
|
900abd5702 |
359
backport-0001-CVE-2023-4863.patch
Normal file
359
backport-0001-CVE-2023-4863.patch
Normal file
@ -0,0 +1,359 @@
|
||||
From 50f60add5c547b8c9bc4462bd2fc2840d8fc4525 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Thu, 7 Sep 2023 21:16:03 +0200
|
||||
Subject: [PATCH] Fix OOB write in BuildHuffmanTable.
|
||||
|
||||
First, BuildHuffmanTable is called to check if the data is valid.
|
||||
If it is and the table is not big enough, more memory is allocated.
|
||||
|
||||
This will make sure that valid (but unoptimized because of unbalanced
|
||||
codes) streams are still decodable.
|
||||
|
||||
Bug: chromium:1479274
|
||||
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
|
||||
(cherry picked from commit 902bc9190331343b2017211debcec8d2ab87e17a)
|
||||
(cherry picked from commit 2af26267cdfcb63a88e5c74a85927a12d6ca1d76)
|
||||
---
|
||||
src/dec/vp8l_dec.c | 46 ++++++++++---------
|
||||
src/dec/vp8li_dec.h | 2 +-
|
||||
src/utils/huffman_utils.c | 97 +++++++++++++++++++++++++++++++--------
|
||||
src/utils/huffman_utils.h | 27 +++++++++--
|
||||
4 files changed, 129 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 93615d4ed2..0d38314db8 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
|
||||
int symbol;
|
||||
int max_symbol;
|
||||
int prev_code_len = DEFAULT_CODE_LENGTH;
|
||||
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
|
||||
+ HuffmanTables tables;
|
||||
|
||||
- if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
|
||||
- code_length_code_lengths,
|
||||
- NUM_CODE_LENGTH_CODES)) {
|
||||
+ if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
|
||||
+ !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
|
||||
+ code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
|
||||
goto End;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
|
||||
int code_len;
|
||||
if (max_symbol-- == 0) break;
|
||||
VP8LFillBitWindow(br);
|
||||
- p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
+ p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
|
||||
code_len = p->value;
|
||||
if (code_len < kCodeLengthLiterals) {
|
||||
@@ -300,6 +300,7 @@ static int ReadHuffmanCodeLengths(
|
||||
ok = 1;
|
||||
|
||||
End:
|
||||
+ VP8LHuffmanTablesDeallocate(&tables);
|
||||
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
return ok;
|
||||
}
|
||||
@@ -307,7 +308,8 @@ static int ReadHuffmanCodeLengths(
|
||||
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
|
||||
// tree.
|
||||
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
- int* const code_lengths, HuffmanCode* const table) {
|
||||
+ int* const code_lengths,
|
||||
+ HuffmanTables* const table) {
|
||||
int ok = 0;
|
||||
int size = 0;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
@@ -362,8 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
uint32_t* huffman_image = NULL;
|
||||
HTreeGroup* htree_groups = NULL;
|
||||
- HuffmanCode* huffman_tables = NULL;
|
||||
- HuffmanCode* huffman_table = NULL;
|
||||
+ HuffmanTables* huffman_tables = &hdr->huffman_tables_;
|
||||
int num_htree_groups = 1;
|
||||
int num_htree_groups_max = 1;
|
||||
int max_alphabet_size = 0;
|
||||
@@ -372,6 +373,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int* mapping = NULL;
|
||||
int ok = 0;
|
||||
|
||||
+ // Check the table has been 0 initialized (through InitMetadata).
|
||||
+ assert(huffman_tables->root.start == NULL);
|
||||
+ assert(huffman_tables->curr_segment == NULL);
|
||||
+
|
||||
if (allow_recursion && VP8LReadBits(br, 1)) {
|
||||
// use meta Huffman codes.
|
||||
const int huffman_precision = VP8LReadBits(br, 3) + 2;
|
||||
@@ -434,16 +439,15 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
|
||||
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);
|
||||
|
||||
- if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
|
||||
+ if (htree_groups == NULL || code_lengths == NULL ||
|
||||
+ !VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
|
||||
+ huffman_tables)) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
- huffman_table = huffman_tables;
|
||||
for (i = 0; i < num_htree_groups_max; ++i) {
|
||||
// If the index "i" is unused in the Huffman image, just make sure the
|
||||
// coefficients are valid but do not store them.
|
||||
@@ -468,19 +472,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int max_bits = 0;
|
||||
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
|
||||
int alphabet_size = kAlphabetSize[j];
|
||||
- htrees[j] = huffman_table;
|
||||
if (j == 0 && color_cache_bits > 0) {
|
||||
alphabet_size += (1 << color_cache_bits);
|
||||
}
|
||||
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
|
||||
+ size =
|
||||
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
|
||||
+ htrees[j] = huffman_tables->curr_segment->curr_table;
|
||||
if (size == 0) {
|
||||
goto Error;
|
||||
}
|
||||
if (is_trivial_literal && kLiteralMap[j] == 1) {
|
||||
- is_trivial_literal = (huffman_table->bits == 0);
|
||||
+ is_trivial_literal = (htrees[j]->bits == 0);
|
||||
}
|
||||
- total_size += huffman_table->bits;
|
||||
- huffman_table += size;
|
||||
+ total_size += htrees[j]->bits;
|
||||
+ huffman_tables->curr_segment->curr_table += size;
|
||||
if (j <= ALPHA) {
|
||||
int local_max_bits = code_lengths[0];
|
||||
int k;
|
||||
@@ -515,14 +520,13 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
hdr->huffman_image_ = huffman_image;
|
||||
hdr->num_htree_groups_ = num_htree_groups;
|
||||
hdr->htree_groups_ = htree_groups;
|
||||
- hdr->huffman_tables_ = huffman_tables;
|
||||
|
||||
Error:
|
||||
WebPSafeFree(code_lengths);
|
||||
WebPSafeFree(mapping);
|
||||
if (!ok) {
|
||||
WebPSafeFree(huffman_image);
|
||||
- WebPSafeFree(huffman_tables);
|
||||
+ VP8LHuffmanTablesDeallocate(huffman_tables);
|
||||
VP8LHtreeGroupsFree(htree_groups);
|
||||
}
|
||||
return ok;
|
||||
@@ -1354,7 +1358,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
|
||||
assert(hdr != NULL);
|
||||
|
||||
WebPSafeFree(hdr->huffman_image_);
|
||||
- WebPSafeFree(hdr->huffman_tables_);
|
||||
+ VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
|
||||
VP8LHtreeGroupsFree(hdr->htree_groups_);
|
||||
VP8LColorCacheClear(&hdr->color_cache_);
|
||||
VP8LColorCacheClear(&hdr->saved_color_cache_);
|
||||
@@ -1670,7 +1674,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
// Sanity checks.
|
||||
if (dec == NULL) return 0;
|
||||
|
||||
- assert(dec->hdr_.huffman_tables_ != NULL);
|
||||
+ assert(dec->hdr_.huffman_tables_.root.start != NULL);
|
||||
assert(dec->hdr_.htree_groups_ != NULL);
|
||||
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||
|
||||
diff --git a/src/dec/vp8li_dec.h b/src/dec/vp8li_dec.h
|
||||
index 72b2e86120..32540a4b88 100644
|
||||
--- a/src/dec/vp8li_dec.h
|
||||
+++ b/src/dec/vp8li_dec.h
|
||||
@@ -51,7 +51,7 @@ typedef struct {
|
||||
uint32_t* huffman_image_;
|
||||
int num_htree_groups_;
|
||||
HTreeGroup* htree_groups_;
|
||||
- HuffmanCode* huffman_tables_;
|
||||
+ HuffmanTables huffman_tables_;
|
||||
} VP8LMetadata;
|
||||
|
||||
typedef struct VP8LDecoder VP8LDecoder;
|
||||
diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
|
||||
index 0cba0fbb7d..9efd6283ac 100644
|
||||
--- a/src/utils/huffman_utils.c
|
||||
+++ b/src/utils/huffman_utils.c
|
||||
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
if (num_open < 0) {
|
||||
return 0;
|
||||
}
|
||||
- if (root_table == NULL) continue;
|
||||
for (; count[len] > 0; --count[len]) {
|
||||
HuffmanCode code;
|
||||
if ((key & mask) != low) {
|
||||
- table += table_size;
|
||||
+ if (root_table != NULL) table += table_size;
|
||||
table_bits = NextTableBitSize(count, len, root_bits);
|
||||
table_size = 1 << table_bits;
|
||||
total_size += table_size;
|
||||
low = key & mask;
|
||||
- root_table[low].bits = (uint8_t)(table_bits + root_bits);
|
||||
- root_table[low].value = (uint16_t)((table - root_table) - low);
|
||||
+ if (root_table != NULL) {
|
||||
+ root_table[low].bits = (uint8_t)(table_bits + root_bits);
|
||||
+ root_table[low].value = (uint16_t)((table - root_table) - low);
|
||||
+ }
|
||||
+ }
|
||||
+ if (root_table != NULL) {
|
||||
+ code.bits = (uint8_t)(len - root_bits);
|
||||
+ code.value = (uint16_t)sorted[symbol++];
|
||||
+ ReplicateValue(&table[key >> root_bits], step, table_size, code);
|
||||
}
|
||||
- code.bits = (uint8_t)(len - root_bits);
|
||||
- code.value = (uint16_t)sorted[symbol++];
|
||||
- ReplicateValue(&table[key >> root_bits], step, table_size, code);
|
||||
key = GetNextKey(key, len);
|
||||
}
|
||||
}
|
||||
@@ -211,25 +214,83 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
|
||||
// Cut-off value for switching between heap and stack allocation.
|
||||
#define SORTED_SIZE_CUTOFF 512
|
||||
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
|
||||
const int code_lengths[], int code_lengths_size) {
|
||||
- int total_size;
|
||||
+ const int total_size =
|
||||
+ BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
|
||||
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
|
||||
- if (root_table == NULL) {
|
||||
- total_size = BuildHuffmanTable(NULL, root_bits,
|
||||
- code_lengths, code_lengths_size, NULL);
|
||||
- } else if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
|
||||
+ if (total_size == 0 || root_table == NULL) return total_size;
|
||||
+
|
||||
+ if (root_table->curr_segment->curr_table + total_size >=
|
||||
+ root_table->curr_segment->start + root_table->curr_segment->size) {
|
||||
+ // If 'root_table' does not have enough memory, allocate a new segment.
|
||||
+ // The available part of root_table->curr_segment is left unused because we
|
||||
+ // need a contiguous buffer.
|
||||
+ const int segment_size = root_table->curr_segment->size;
|
||||
+ struct HuffmanTablesSegment* next =
|
||||
+ (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
|
||||
+ if (next == NULL) return 0;
|
||||
+ // Fill the new segment.
|
||||
+ // We need at least 'total_size' but if that value is small, it is better to
|
||||
+ // allocate a big chunk to prevent more allocations later. 'segment_size' is
|
||||
+ // therefore chosen (any other arbitrary value could be chosen).
|
||||
+ next->size = total_size > segment_size ? total_size : segment_size;
|
||||
+ next->start =
|
||||
+ (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start));
|
||||
+ if (next->start == NULL) {
|
||||
+ WebPSafeFree(next);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ next->curr_table = next->start;
|
||||
+ next->next = NULL;
|
||||
+ // Point to the new segment.
|
||||
+ root_table->curr_segment->next = next;
|
||||
+ root_table->curr_segment = next;
|
||||
+ }
|
||||
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
|
||||
// use local stack-allocated array.
|
||||
uint16_t sorted[SORTED_SIZE_CUTOFF];
|
||||
- total_size = BuildHuffmanTable(root_table, root_bits,
|
||||
- code_lengths, code_lengths_size, sorted);
|
||||
- } else { // rare case. Use heap allocation.
|
||||
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
|
||||
+ code_lengths, code_lengths_size, sorted);
|
||||
+ } else { // rare case. Use heap allocation.
|
||||
uint16_t* const sorted =
|
||||
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
|
||||
if (sorted == NULL) return 0;
|
||||
- total_size = BuildHuffmanTable(root_table, root_bits,
|
||||
- code_lengths, code_lengths_size, sorted);
|
||||
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
|
||||
+ code_lengths, code_lengths_size, sorted);
|
||||
WebPSafeFree(sorted);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
+
|
||||
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
|
||||
+ // Have 'segment' point to the first segment for now, 'root'.
|
||||
+ HuffmanTablesSegment* const root = &huffman_tables->root;
|
||||
+ huffman_tables->curr_segment = root;
|
||||
+ // Allocate root.
|
||||
+ root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
|
||||
+ if (root->start == NULL) return 0;
|
||||
+ root->curr_table = root->start;
|
||||
+ root->next = NULL;
|
||||
+ root->size = size;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
|
||||
+ HuffmanTablesSegment *current, *next;
|
||||
+ if (huffman_tables == NULL) return;
|
||||
+ // Free the root node.
|
||||
+ current = &huffman_tables->root;
|
||||
+ next = current->next;
|
||||
+ WebPSafeFree(current->start);
|
||||
+ current->start = NULL;
|
||||
+ current->next = NULL;
|
||||
+ current = next;
|
||||
+ // Free the following nodes.
|
||||
+ while (current != NULL) {
|
||||
+ next = current->next;
|
||||
+ WebPSafeFree(current->start);
|
||||
+ WebPSafeFree(current);
|
||||
+ current = next;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/utils/huffman_utils.h b/src/utils/huffman_utils.h
|
||||
index 13b7ad1ac4..98415c5328 100644
|
||||
--- a/src/utils/huffman_utils.h
|
||||
+++ b/src/utils/huffman_utils.h
|
||||
@@ -43,6 +43,29 @@ typedef struct {
|
||||
// or non-literal symbol otherwise
|
||||
} HuffmanCode32;
|
||||
|
||||
+// Contiguous memory segment of HuffmanCodes.
|
||||
+typedef struct HuffmanTablesSegment {
|
||||
+ HuffmanCode* start;
|
||||
+ // Pointer to where we are writing into the segment. Starts at 'start' and
|
||||
+ // cannot go beyond 'start' + 'size'.
|
||||
+ HuffmanCode* curr_table;
|
||||
+ // Pointer to the next segment in the chain.
|
||||
+ struct HuffmanTablesSegment* next;
|
||||
+ int size;
|
||||
+} HuffmanTablesSegment;
|
||||
+
|
||||
+// Chained memory segments of HuffmanCodes.
|
||||
+typedef struct HuffmanTables {
|
||||
+ HuffmanTablesSegment root;
|
||||
+ // Currently processed segment. At first, this is 'root'.
|
||||
+ HuffmanTablesSegment* curr_segment;
|
||||
+} HuffmanTables;
|
||||
+
|
||||
+// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on
|
||||
+// memory allocation error, 1 otherwise.
|
||||
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables);
|
||||
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables);
|
||||
+
|
||||
#define HUFFMAN_PACKED_BITS 6
|
||||
#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
|
||||
|
||||
@@ -78,9 +101,7 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
|
||||
// the huffman table.
|
||||
// Returns built table size or 0 in case of error (invalid tree or
|
||||
// memory error).
|
||||
-// If root_table is NULL, it returns 0 if a lookup cannot be built, something
|
||||
-// > 0 otherwise (but not the table size).
|
||||
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
|
||||
const int code_lengths[], int code_lengths_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
43
backport-0002-CVE-2023-4863.patch
Normal file
43
backport-0002-CVE-2023-4863.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 95ea5226c870449522240ccff26f0b006037c520 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Mon, 11 Sep 2023 16:06:08 +0200
|
||||
Subject: [PATCH] Fix invalid incremental decoding check.
|
||||
|
||||
The first condition is only necessary if we have not read enough
|
||||
(enough being defined by src_last, not src_end which is the end
|
||||
of the image).
|
||||
The second condition now fits the comment below: "if not
|
||||
incremental, and we are past the end of buffer".
|
||||
|
||||
BUG=oss-fuzz:62136
|
||||
|
||||
Change-Id: I0700f67c62db8e1c02c2e429a069a71e606a5e4f
|
||||
---
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 5ab34f5..809b1aa 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -1233,9 +1233,20 @@
|
||||
}
|
||||
|
||||
br->eos_ = VP8LIsEndOfStream(br);
|
||||
- if (dec->incremental_ && br->eos_ && src < src_end) {
|
||||
+ // In incremental decoding:
|
||||
+ // br->eos_ && src < src_last: if 'br' reached the end of the buffer and
|
||||
+ // 'src_last' has not been reached yet, there is not enough data. 'dec' has to
|
||||
+ // be reset until there is more data.
|
||||
+ // !br->eos_ && src < src_last: this cannot happen as either the buffer is
|
||||
+ // fully read, either enough has been read to reach 'src_last'.
|
||||
+ // src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go
|
||||
+ // beyond 'src_last' in case the image is cropped and an LZ77 goes further.
|
||||
+ // The buffer might have been enough or there is some left. 'br->eos_' does
|
||||
+ // not matter.
|
||||
+ assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);
|
||||
+ if (dec->incremental_ && br->eos_ && src < src_last) {
|
||||
RestoreState(dec);
|
||||
- } else if (!br->eos_) {
|
||||
+ } else if ((dec->incremental_ && src >= src_last) || !br->eos_) {
|
||||
// Process the remaining rows corresponding to last row-block.
|
||||
if (process_func != NULL) {
|
||||
process_func(dec, row > last_row ? last_row : row);
|
||||
55
backport-CVE-2023-1999.patch
Normal file
55
backport-CVE-2023-1999.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From a486d800b60d0af4cc0836bf7ed8f21e12974129 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Wed, 22 Feb 2023 22:15:47 -0800
|
||||
Subject: [PATCH] EncodeAlphaInternal: clear result->bw on error
|
||||
|
||||
This avoids a double free should the function fail prior to
|
||||
VP8BitWriterInit() and a previous trial result's buffer carried over.
|
||||
Previously in ApplyFiltersAndEncode() trial.bw (with a previous
|
||||
iteration's buffer) would be freed, followed by best.bw pointing to the
|
||||
same buffer.
|
||||
|
||||
Since:
|
||||
187d379d add a fallback to ALPHA_NO_COMPRESSION
|
||||
|
||||
In addition, check the return value of VP8BitWriterInit() in this
|
||||
function.
|
||||
|
||||
Bug: webp:603
|
||||
Change-Id: Ic258381ee26c8c16bc211d157c8153831c8c6910
|
||||
|
||||
Reference:https://github.com/webmproject/libwebp/commit/a486d800b60d0af4cc0836bf7ed8f21e12974129
|
||||
Conflict:NA
|
||||
---
|
||||
src/enc/alpha_enc.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/enc/alpha_enc.c b/src/enc/alpha_enc.c
|
||||
index f7c02690e3..7d205586fe 100644
|
||||
--- a/src/enc/alpha_enc.c
|
||||
+++ b/src/enc/alpha_enc.c
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
|
||||
#include "src/enc/vp8i_enc.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
@@ -148,6 +149,7 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
||||
}
|
||||
} else {
|
||||
VP8LBitWriterWipeOut(&tmp_bw);
|
||||
+ memset(&result->bw, 0, sizeof(result->bw));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -162,7 +164,7 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
||||
header = method | (filter << 2);
|
||||
if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
|
||||
|
||||
- VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size);
|
||||
+ if (!VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size)) ok = 0;
|
||||
ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
|
||||
ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
|
||||
|
||||
Binary file not shown.
@ -1,56 +0,0 @@
|
||||
From 0b271f10c428b59d20a4415247e228f31e0030e4 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Fri, 13 Jul 2018 22:09:06 +0200
|
||||
Subject: [PATCH] Allow for a non-initialized alpha decompressor in DoRemap.
|
||||
|
||||
BUG=oss-fuzz:9364
|
||||
|
||||
Change-Id: Ib1a1c6b0ccfcc255505f019e3e8fd15db73bc4b6
|
||||
(cherry picked from commit da96d8d9ab4b10d023ffa701c8e4ff5843db010a)
|
||||
---
|
||||
src/dec/idec_dec.c | 3 +--
|
||||
src/dec/vp8l_dec.c | 6 +++---
|
||||
2 files changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/dec/idec_dec.c b/src/dec/idec_dec.c
|
||||
index 6a44236ab..738e14c95 100644
|
||||
--- a/src/dec/idec_dec.c
|
||||
+++ b/src/dec/idec_dec.c
|
||||
@@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
|
||||
if (NeedCompressedAlpha(idec)) {
|
||||
ALPHDecoder* const alph_dec = dec->alph_dec_;
|
||||
dec->alpha_data_ += offset;
|
||||
- if (alph_dec != NULL) {
|
||||
+ if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) {
|
||||
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
|
||||
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
|
||||
- assert(alph_vp8l_dec != NULL);
|
||||
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
|
||||
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
|
||||
dec->alpha_data_ + ALPHA_HEADER_LEN,
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 7549cdaee..838e7f29d 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -1527,7 +1527,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
|
||||
if (dec == NULL) return 0;
|
||||
|
||||
assert(alph_dec != NULL);
|
||||
- alph_dec->vp8l_dec_ = dec;
|
||||
|
||||
dec->width_ = alph_dec->width_;
|
||||
dec->height_ = alph_dec->height_;
|
||||
@@ -1559,11 +1558,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
|
||||
|
||||
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;
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
From 6f643f2417837286d6ab34f22e573840f4d88df6 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Thu, 21 Jun 2018 01:13:36 +0000
|
||||
Subject: [PATCH] muxread,ChunkVerifyAndAssign: validate chunk_size
|
||||
|
||||
before accounting for padding which might overflow if chunk_size is >
|
||||
MAX_CHUNK_PAYLOAD.
|
||||
|
||||
BUG=webp:387,webp:388
|
||||
---
|
||||
src/mux/muxi.h | 3 ++-
|
||||
src/mux/muxread.c | 10 ++++++++--
|
||||
2 files changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "src/dec/vp8i_dec.h"
|
||||
#include "src/dec/vp8li_dec.h"
|
||||
@@ -143,13 +144,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);
|
||||
|
||||
// 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 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
|
||||
// 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 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
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;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
From a14e0f646550f90c22395f613b9dda1c90401266 Mon Sep 17 00:00:00 2001
|
||||
From: Yannis Guyon <yguyon@google.com>
|
||||
Date: Mon, 2 Jul 2018 13:15:38 +0200
|
||||
Subject: [PATCH] Fix VP8IoTeardownHook being called twice on worker sync
|
||||
failure
|
||||
|
||||
idec_dec.c, DecodeRemaining: Set decoder state to ERROR to prevent VP8ExitCritical to be called again
|
||||
|
||||
Change-Id: Id5f893f45c348e1c529680d930e640f780a73d4c
|
||||
(cherry picked from commit 9e729fe19bb60f4ecac357a3d3f5c5c64dd080d2)
|
||||
---
|
||||
src/dec/idec_dec.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/dec/idec_dec.c b/src/dec/idec_dec.c
|
||||
index 258d15b06..205ca7a5c 100644
|
||||
--- a/src/dec/idec_dec.c
|
||||
+++ b/src/dec/idec_dec.c
|
||||
@@ -489,6 +489,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
|
||||
}
|
||||
// Synchronize the thread and check for errors.
|
||||
if (!VP8ExitCritical(dec, io)) {
|
||||
+ idec->state_ = STATE_ERROR; // prevent re-entry in IDecError
|
||||
return IDecError(idec, VP8_STATUS_USER_ABORT);
|
||||
}
|
||||
dec->ready_ = 0;
|
||||
@ -1,30 +0,0 @@
|
||||
From a0b85e4a366408be8d077ec30754213bcce8aceb Mon Sep 17 00:00:00 2001
|
||||
From: Yannis Guyon <yguyon@google.com>
|
||||
Date: Wed, 13 Jun 2018 10:39:37 +0200
|
||||
Subject: [PATCH] Fix for thread race heap-use-after-free
|
||||
|
||||
BUG=webp:385
|
||||
---
|
||||
src/dec/idec_dec.c | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/dec/idec_dec.c b/src/dec/idec_dec.c
|
||||
index a371ed7..258d15b 100644
|
||||
--- a/src/dec/idec_dec.c
|
||||
+++ b/src/dec/idec_dec.c
|
||||
@@ -283,10 +283,8 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
|
||||
|
||||
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
|
||||
if (idec->state_ == STATE_VP8_DATA) {
|
||||
- VP8Io* const io = &idec->io_;
|
||||
- if (io->teardown != NULL) {
|
||||
- io->teardown(io);
|
||||
- }
|
||||
+ // Synchronize the thread, clean-up and check for errors.
|
||||
+ VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
|
||||
}
|
||||
idec->state_ = STATE_ERROR;
|
||||
return error;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 99d079023372016da046eaea3719ba0f78da3322 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Mon, 9 Jul 2018 20:20:52 +0200
|
||||
Subject: [PATCH] Make sure partition #0 is read before VP8 data in IDecode.
|
||||
|
||||
BUG=oss-fuzz:9186
|
||||
|
||||
Change-Id: Ie0b264b6422774343206ddba3c2820a0cf37ffc0
|
||||
(cherry picked from commit 5f0f5c07c460c286c8da25f986e1b152079a79b8)
|
||||
---
|
||||
src/dec/idec_dec.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/dec/idec_dec.c b/src/dec/idec_dec.c
|
||||
index 205ca7a5c..6a44236ab 100644
|
||||
--- a/src/dec/idec_dec.c
|
||||
+++ b/src/dec/idec_dec.c
|
||||
@@ -449,7 +449,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
|
||||
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
|
||||
VP8Io* const io = &idec->io_;
|
||||
|
||||
- assert(dec->ready_);
|
||||
+ // Make sure partition #0 has been read before, to set dec to ready_.
|
||||
+ if (!dec->ready_) {
|
||||
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
+ }
|
||||
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
|
||||
if (idec->last_mb_y_ != dec->mb_y_) {
|
||||
if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
|
||||
@@ -570,6 +573,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
|
||||
status = DecodePartition0(idec);
|
||||
}
|
||||
if (idec->state_ == STATE_VP8_DATA) {
|
||||
+ const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
|
||||
+ if (dec == NULL) {
|
||||
+ return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
|
||||
+ }
|
||||
status = DecodeRemaining(idec);
|
||||
}
|
||||
if (idec->state_ == STATE_VP8L_HEADER) {
|
||||
@ -1,32 +0,0 @@
|
||||
From f4cf238a415542140dfb877d4ddee9a2b11b8183 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Fri, 29 Jun 2018 01:12:20 -0700
|
||||
Subject: [PATCH] muxread,anmf: fail on multiple image chunks
|
||||
|
||||
treat an ANMF chunk containing multiple VP8/VP8L file as malformed.
|
||||
fixes a WebPMuxImage::img_ leak.
|
||||
|
||||
Though the invalid free in #9106 was avoided in (ubsan):
|
||||
be738c6d muxread,ChunkVerifyAndAssign: validate chunk_size
|
||||
that file would still cause a leak similar to #9099.
|
||||
|
||||
BUG=oss-fuzz:9099,oss-fuzz:9106
|
||||
|
||||
Change-Id: Ib873446a1188afeeb2fe5d53a86b75e0c5de9573
|
||||
(cherry picked from commit eb82ce76ddca13ad6fb13376bb58b9fd3f850e9e)
|
||||
---
|
||||
src/mux/muxread.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/mux/muxread.c b/src/mux/muxread.c
|
||||
index ef50dae51..fbe9f0516 100644
|
||||
--- a/src/mux/muxread.c
|
||||
+++ b/src/mux/muxread.c
|
||||
@@ -138,6 +138,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
||||
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
|
||||
break;
|
||||
case WEBP_CHUNK_IMAGE:
|
||||
+ if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
|
||||
if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
|
||||
if (!MuxImageFinalize(wpi)) goto Fail;
|
||||
wpi->is_partial_ = 0; // wpi is completely filled.
|
||||
@ -1,37 +0,0 @@
|
||||
From 61ff26aeeb87386f2e1ee377d7bbe1f1ef248e3f Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <skal@google.com>
|
||||
Date: Fri, 29 Jun 2018 10:15:47 -0700
|
||||
Subject: [PATCH] fix alpha-filtering crash when image width is larger than
|
||||
radius
|
||||
|
||||
(we also limit radius based on height too, for good measure, although it's not an asan bug)
|
||||
|
||||
fixes oss-fuzz issue #9105
|
||||
|
||||
Change-Id: Ie0d79dd81480dc4e2b653b7e992e5cdcd3dfa834
|
||||
(cherry picked from commit 1344a2e947c749d231141a295327e5b99b444d63)
|
||||
---
|
||||
src/utils/quant_levels_dec_utils.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/utils/quant_levels_dec_utils.c b/src/utils/quant_levels_dec_utils.c
|
||||
index 3818a78b9..f65b6cdbb 100644
|
||||
--- a/src/utils/quant_levels_dec_utils.c
|
||||
+++ b/src/utils/quant_levels_dec_utils.c
|
||||
@@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) {
|
||||
|
||||
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
|
||||
int strength) {
|
||||
- const int radius = 4 * strength / 100;
|
||||
+ int radius = 4 * strength / 100;
|
||||
+
|
||||
if (strength < 0 || strength > 100) return 0;
|
||||
if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
|
||||
+
|
||||
+ // limit the filter size to not exceed the image dimensions
|
||||
+ if (2 * radius + 1 > width) radius = (width - 1) >> 1;
|
||||
+ if (2 * radius + 1 > height) radius = (height - 1) >> 1;
|
||||
+
|
||||
if (radius > 0) {
|
||||
SmoothParams p;
|
||||
memset(&p, 0, sizeof(p));
|
||||
@ -1,31 +0,0 @@
|
||||
From 667d17a8a403e0768cccf585455cf12807cd1604 Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <pascal.massimino@gmail.com>
|
||||
Date: Mon, 9 Jul 2018 17:33:44 -0700
|
||||
Subject: [PATCH] fix endian problems in pattern copy
|
||||
|
||||
CopyBlock8b() was over-using memcpy() of 16b values.
|
||||
|
||||
BUG=webp:393
|
||||
|
||||
Change-Id: Id56f10d334b9a453fbcf50dabfaa63529bcff7e5
|
||||
(cherry picked from commit 211f37ee633aa31c37160c84cc9b868c10fbe8b9)
|
||||
---
|
||||
src/dec/vp8l_dec.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 0570f53a7..7549cdaee 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -884,7 +884,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
|
||||
#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)
|
||||
@ -1,27 +0,0 @@
|
||||
From dad31750e374eff8e02fb467eb562d4bf236ed6e Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <pascal.massimino@gmail.com>
|
||||
Date: Fri, 25 May 2018 13:25:39 +0200
|
||||
Subject: [PATCH] fix invalid check for buffer size
|
||||
|
||||
BUG=webp:383
|
||||
---
|
||||
src/dec/buffer_dec.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/dec/buffer_dec.c b/src/dec/buffer_dec.c
|
||||
index 75eb3c4..3cd94eb 100644
|
||||
--- a/src/dec/buffer_dec.c
|
||||
+++ b/src/dec/buffer_dec.c
|
||||
@@ -74,7 +74,8 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
|
||||
} else { // RGB checks
|
||||
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
|
||||
const int stride = abs(buf->stride);
|
||||
- const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
|
||||
+ const uint64_t size =
|
||||
+ MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
|
||||
ok &= (size <= buf->size);
|
||||
ok &= (stride >= width * kModeBpp[mode]);
|
||||
ok &= (buf->rgba != NULL);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
From c0226fd91cbe5fa6fbf5a68dcc9acc9dbe1e358e Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <skal@google.com>
|
||||
Date: Sun, 1 Jul 2018 20:01:12 -0700
|
||||
Subject: [PATCH] fix read-overflow while parsing VP8X chunk
|
||||
|
||||
The available size was not checked before parsing the VP8X data
|
||||
|
||||
BUG=oss-fuzz:9100,oss-fuzz:9123
|
||||
|
||||
Change-Id: I0143cc4554883c1015e2f084a0e371229e04a8ca
|
||||
(cherry picked from commit 95fd65070662e01cc9170c4444f5c0859a710097)
|
||||
---
|
||||
src/mux/muxread.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/mux/muxread.c b/src/mux/muxread.c
|
||||
index fbe9f0516..ea07dbfd2 100644
|
||||
--- a/src/mux/muxread.c
|
||||
+++ b/src/mux/muxread.c
|
||||
@@ -264,6 +264,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
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;
|
||||
}
|
||||
@ -1,318 +0,0 @@
|
||||
From 916aac82c54d1cc78eb95ad3d916eaaf0fa2c910 Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <pascal.massimino@gmail.com>
|
||||
Date: Tue, 10 Jul 2018 17:27:21 -0700
|
||||
Subject: [PATCH] fix rescaling rounding inaccuracy
|
||||
|
||||
We should be using 'floor' when doing the final divide.
|
||||
|
||||
-> new MACRO is MULT_FIX_FLOOR()
|
||||
|
||||
XXX*** Mips code is DISABLED for now ***XXX
|
||||
|
||||
I'll update and re-enable it in a later
|
||||
patch, since this code needs some refactoring first.
|
||||
|
||||
BUG=oss-fuzz:9179
|
||||
|
||||
Change-Id: Ic0693cdca4e71f5beab1029475e35c4d06b12d13
|
||||
(cherry picked from commit 2563db475946d0ae3eb0defdb9b3805f75e6ef1e)
|
||||
---
|
||||
src/dsp/rescaler.c | 4 +++-
|
||||
src/dsp/rescaler_mips32.c | 4 +++-
|
||||
src/dsp/rescaler_mips_dsp_r2.c | 10 +++++++---
|
||||
src/dsp/rescaler_msa.c | 7 +++++--
|
||||
src/dsp/rescaler_neon.c | 18 +++++++++++++----
|
||||
src/dsp/rescaler_sse2.c | 35 ++++++++++++++++++++++++++++++++--
|
||||
6 files changed, 65 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/dsp/rescaler.c b/src/dsp/rescaler.c
|
||||
index f307d3505..753f84fcf 100644
|
||||
--- a/src/dsp/rescaler.c
|
||||
+++ b/src/dsp/rescaler.c
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
|
||||
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
|
||||
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Row import
|
||||
@@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
|
||||
if (yscale) {
|
||||
for (x_out = 0; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
dst[x_out] = v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
@@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#undef MULT_FIX_FLOOR
|
||||
#undef MULT_FIX
|
||||
#undef ROUNDER
|
||||
|
||||
diff --git a/src/dsp/rescaler_mips32.c b/src/dsp/rescaler_mips32.c
|
||||
index 542f7e597..61f63c616 100644
|
||||
--- a/src/dsp/rescaler_mips32.c
|
||||
+++ b/src/dsp/rescaler_mips32.c
|
||||
@@ -209,6 +209,7 @@ static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#if 0 // disabled for now. TODO(skal): make match the C-code
|
||||
static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
|
||||
const int x_out_max = wrk->dst_width * wrk->num_channels;
|
||||
uint8_t* dst = wrk->dst;
|
||||
@@ -273,6 +274,7 @@ static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
|
||||
);
|
||||
}
|
||||
}
|
||||
+#endif // 0
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Entry point
|
||||
@@ -283,7 +285,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
|
||||
WebPRescalerImportRowExpand = ImportRowExpand_MIPS32;
|
||||
WebPRescalerImportRowShrink = ImportRowShrink_MIPS32;
|
||||
WebPRescalerExportRowExpand = ExportRowExpand_MIPS32;
|
||||
- WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
|
||||
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
|
||||
}
|
||||
|
||||
#else // !WEBP_USE_MIPS32
|
||||
diff --git a/src/dsp/rescaler_mips_dsp_r2.c b/src/dsp/rescaler_mips_dsp_r2.c
|
||||
index b78aac15e..ce9e64862 100644
|
||||
--- a/src/dsp/rescaler_mips_dsp_r2.c
|
||||
+++ b/src/dsp/rescaler_mips_dsp_r2.c
|
||||
@@ -20,10 +20,12 @@
|
||||
|
||||
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
|
||||
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
|
||||
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Row export
|
||||
|
||||
+#if 0 // disabled for now. TODO(skal): make match the C-code
|
||||
static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
int i;
|
||||
const int x_out_max = wrk->dst_width * wrk->num_channels;
|
||||
@@ -106,7 +108,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
}
|
||||
for (i = 0; i < (x_out_max & 0x3); ++i) {
|
||||
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
|
||||
- const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
*dst++ = v;
|
||||
*irow++ = frac; // new fractional start
|
||||
@@ -154,13 +156,14 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
);
|
||||
}
|
||||
for (i = 0; i < (x_out_max & 0x3); ++i) {
|
||||
- const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
*dst++ = v;
|
||||
*irow++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+#endif // 0
|
||||
|
||||
static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
int i;
|
||||
@@ -294,6 +297,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#undef MULT_FIX_FLOOR
|
||||
#undef MULT_FIX
|
||||
#undef ROUNDER
|
||||
|
||||
@@ -304,7 +308,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
|
||||
|
||||
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
|
||||
WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2;
|
||||
- WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
|
||||
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
|
||||
}
|
||||
|
||||
#else // !WEBP_USE_MIPS_DSP_R2
|
||||
diff --git a/src/dsp/rescaler_msa.c b/src/dsp/rescaler_msa.c
|
||||
index f3bc99f1c..c55925483 100644
|
||||
--- a/src/dsp/rescaler_msa.c
|
||||
+++ b/src/dsp/rescaler_msa.c
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
|
||||
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
|
||||
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
|
||||
|
||||
#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
|
||||
v4u32 tmp0, tmp1, tmp2, tmp3; \
|
||||
@@ -262,6 +263,7 @@ static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#if 0 // disabled for now. TODO(skal): make match the C-code
|
||||
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
|
||||
uint8_t* dst, int length,
|
||||
const uint32_t yscale,
|
||||
@@ -341,7 +343,7 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
|
||||
}
|
||||
for (x_out = 0; x_out < length; ++x_out) {
|
||||
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
dst[x_out] = v;
|
||||
irow[x_out] = frac;
|
||||
@@ -426,6 +428,7 @@ static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
ExportRowShrink_1(irow, dst, x_out_max, wrk);
|
||||
}
|
||||
}
|
||||
+#endif // 0
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Entry point
|
||||
@@ -434,7 +437,7 @@ extern void WebPRescalerDspInitMSA(void);
|
||||
|
||||
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
|
||||
WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
|
||||
- WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
|
||||
+// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
|
||||
}
|
||||
|
||||
#else // !WEBP_USE_MSA
|
||||
diff --git a/src/dsp/rescaler_neon.c b/src/dsp/rescaler_neon.c
|
||||
index 3eff9fbaf..a553f06f7 100644
|
||||
--- a/src/dsp/rescaler_neon.c
|
||||
+++ b/src/dsp/rescaler_neon.c
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
|
||||
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
|
||||
+#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
|
||||
|
||||
#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
|
||||
#define LOAD_32x8(SRC, DST0, DST1) \
|
||||
@@ -35,8 +36,11 @@
|
||||
|
||||
#if (WEBP_RESCALER_RFIX == 32)
|
||||
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
|
||||
-#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
|
||||
+// note: B is actualy scale>>1. See MAKE_HALF_CST
|
||||
+#define MULT_FIX(A, B) \
|
||||
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
|
||||
+#define MULT_FIX_FLOOR(A, B) \
|
||||
+ vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
|
||||
#else
|
||||
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
|
||||
#endif
|
||||
@@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
|
||||
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
|
||||
const uint32x4_t B0 = vqsubq_u32(in2, A0);
|
||||
const uint32x4_t B1 = vqsubq_u32(in3, A1);
|
||||
- const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
|
||||
- const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
|
||||
+ const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
|
||||
+ const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
|
||||
const uint16x4_t D0 = vmovn_u32(C0);
|
||||
const uint16x4_t D1 = vmovn_u32(C1);
|
||||
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
|
||||
@@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
dst[x_out] = v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
@@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#undef MULT_FIX_FLOOR_C
|
||||
+#undef MULT_FIX_C
|
||||
+#undef MULT_FIX_FLOOR
|
||||
+#undef MULT_FIX
|
||||
+#undef ROUNDER
|
||||
+
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern void WebPRescalerDspInitNEON(void);
|
||||
diff --git a/src/dsp/rescaler_sse2.c b/src/dsp/rescaler_sse2.c
|
||||
index 64c50deab..f7461a452 100644
|
||||
--- a/src/dsp/rescaler_sse2.c
|
||||
+++ b/src/dsp/rescaler_sse2.c
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
|
||||
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
|
||||
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
|
||||
|
||||
// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
|
||||
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
|
||||
@@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
|
||||
_mm_storel_epi64((__m128i*)dst, G);
|
||||
}
|
||||
|
||||
+static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
|
||||
+ const __m128i* const A1,
|
||||
+ const __m128i* const A2,
|
||||
+ const __m128i* const A3,
|
||||
+ const __m128i* const mult,
|
||||
+ uint8_t* const dst) {
|
||||
+ const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
|
||||
+ const __m128i B0 = _mm_mul_epu32(*A0, *mult);
|
||||
+ const __m128i B1 = _mm_mul_epu32(*A1, *mult);
|
||||
+ const __m128i B2 = _mm_mul_epu32(*A2, *mult);
|
||||
+ const __m128i B3 = _mm_mul_epu32(*A3, *mult);
|
||||
+ const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
|
||||
+ const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
|
||||
+#if (WEBP_RESCALER_RFIX < 32)
|
||||
+ const __m128i D2 =
|
||||
+ _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
|
||||
+ const __m128i D3 =
|
||||
+ _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
|
||||
+#else
|
||||
+ const __m128i D2 = _mm_and_si128(B2, mask);
|
||||
+ const __m128i D3 = _mm_and_si128(B3, mask);
|
||||
+#endif
|
||||
+ const __m128i E0 = _mm_or_si128(D0, D2);
|
||||
+ const __m128i E1 = _mm_or_si128(D1, D3);
|
||||
+ const __m128i F = _mm_packs_epi32(E0, E1);
|
||||
+ const __m128i G = _mm_packus_epi16(F, F);
|
||||
+ _mm_storel_epi64((__m128i*)dst, G);
|
||||
+}
|
||||
+
|
||||
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
|
||||
int x_out;
|
||||
uint8_t* const dst = wrk->dst;
|
||||
@@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
|
||||
const __m128i G1 = _mm_or_si128(D1, F3);
|
||||
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
|
||||
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
|
||||
- ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
|
||||
+ ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
|
||||
}
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
assert(v >= 0 && v <= 255);
|
||||
dst[x_out] = v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
@@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
|
||||
}
|
||||
}
|
||||
|
||||
+#undef MULT_FIX_FLOOR
|
||||
#undef MULT_FIX
|
||||
#undef ROUNDER
|
||||
@ -1,58 +0,0 @@
|
||||
From 706ff9c325d755060a22a20af336ef913b8c5bac Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Thu, 14 Jun 2018 00:03:34 -0700
|
||||
Subject: [PATCH] muxread,CreateInternal: fix riff size checks
|
||||
|
||||
previously when adjusting size down based on a smaller riff_size the
|
||||
checks were insufficient to prevent 'size -= RIFF_HEADER_SIZE' from
|
||||
rolling over causing ChunkVerifyAndAssign to over read. the new checks
|
||||
are imported from demux.c.
|
||||
|
||||
BUG=webp:386
|
||||
---
|
||||
src/mux/muxread.c | 15 ++++++---------
|
||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
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 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
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 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
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 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
}
|
||||
|
||||
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;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,373 +0,0 @@
|
||||
From 7c2c00851ae558de4ef1453c57a7d2e1feb3c2b1 Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Massimino <pascal.massimino@gmail.com>
|
||||
Date: Thu, 28 Mar 2019 19:44:39 +0100
|
||||
Subject: [PATCH] Rescaler: fix rounding error
|
||||
|
||||
We saturate the result to [0..255]
|
||||
It's the easiest and safest, given the wide variety of scaling
|
||||
range we cover: we're not using floats, so precision is always
|
||||
an issue at one end or the other of the scaling spectrum.
|
||||
|
||||
we also use:
|
||||
round(a - floor(b))
|
||||
instead of:
|
||||
floor(a - round(b))
|
||||
to handle difficult cases (ratio ~= .99, e.g.)
|
||||
|
||||
MIPS code is still disabled (and wrong)
|
||||
|
||||
Change-Id: I18d3f5ddc4c524879c257b928329b1c648fa7fb5
|
||||
(cherry picked from commit ab2dc8939fe6945e11e23ef7760a06077619b1bd)
|
||||
---
|
||||
src/dsp/rescaler.c | 16 ++++-----
|
||||
src/dsp/rescaler_mips_dsp_r2.c | 16 ++++-----
|
||||
src/dsp/rescaler_msa.c | 16 ++++-----
|
||||
src/dsp/rescaler_neon.c | 32 ++++++++----------
|
||||
src/dsp/rescaler_sse2.c | 60 +++++++---------------------------
|
||||
5 files changed, 43 insertions(+), 97 deletions(-)
|
||||
|
||||
diff --git a/src/dsp/rescaler.c b/src/dsp/rescaler.c
|
||||
index 753f84fcf..c5a01e82d 100644
|
||||
--- a/src/dsp/rescaler.c
|
||||
+++ b/src/dsp/rescaler.c
|
||||
@@ -109,8 +109,7 @@ void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) {
|
||||
for (x_out = 0; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t J = frow[x_out];
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
} else {
|
||||
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
|
||||
@@ -120,8 +119,7 @@ void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) {
|
||||
+ (uint64_t)B * irow[x_out];
|
||||
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,17 +136,15 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
|
||||
assert(!wrk->y_expand);
|
||||
if (yscale) {
|
||||
for (x_out = 0; x_out < x_out_max; ++x_out) {
|
||||
- const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale);
|
||||
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
}
|
||||
} else {
|
||||
for (x_out = 0; x_out < x_out_max; ++x_out) {
|
||||
const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/src/dsp/rescaler_mips_dsp_r2.c b/src/dsp/rescaler_mips_dsp_r2.c
|
||||
index ce9e64862..419b741fa 100644
|
||||
--- a/src/dsp/rescaler_mips_dsp_r2.c
|
||||
+++ b/src/dsp/rescaler_mips_dsp_r2.c
|
||||
@@ -107,10 +107,9 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
);
|
||||
}
|
||||
for (i = 0; i < (x_out_max & 0x3); ++i) {
|
||||
- const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
|
||||
- const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- *dst++ = v;
|
||||
+ const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(*frow++, yscale);
|
||||
+ const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
|
||||
+ *dst++ = (v > 255) ? 255u : (uint8_t)v;
|
||||
*irow++ = frac; // new fractional start
|
||||
}
|
||||
} else {
|
||||
@@ -157,8 +156,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
}
|
||||
for (i = 0; i < (x_out_max & 0x3); ++i) {
|
||||
const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- *dst++ = v;
|
||||
+ *dst++ = (v > 255) ? 255u : (uint8_t)v;
|
||||
*irow++ = 0;
|
||||
}
|
||||
}
|
||||
@@ -219,8 +217,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
for (i = 0; i < (x_out_max & 0x3); ++i) {
|
||||
const uint32_t J = *frow++;
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- *dst++ = v;
|
||||
+ *dst++ = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
} else {
|
||||
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
|
||||
@@ -291,8 +288,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
|
||||
+ (uint64_t)B * *irow++;
|
||||
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- *dst++ = v;
|
||||
+ *dst++ = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/dsp/rescaler_msa.c b/src/dsp/rescaler_msa.c
|
||||
index c55925483..256dbdd43 100644
|
||||
--- a/src/dsp/rescaler_msa.c
|
||||
+++ b/src/dsp/rescaler_msa.c
|
||||
@@ -166,8 +166,7 @@ static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst,
|
||||
for (x_out = 0; x_out < length; ++x_out) {
|
||||
const uint32_t J = frow[x_out];
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,8 +240,7 @@ static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow,
|
||||
+ (uint64_t)B * irow[x_out];
|
||||
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,10 +340,9 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
|
||||
length -= 4;
|
||||
}
|
||||
for (x_out = 0; x_out < length; ++x_out) {
|
||||
- const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale);
|
||||
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = frac;
|
||||
}
|
||||
}
|
||||
@@ -406,8 +403,7 @@ static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst,
|
||||
}
|
||||
for (x_out = 0; x_out < length; ++x_out) {
|
||||
const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/src/dsp/rescaler_neon.c b/src/dsp/rescaler_neon.c
|
||||
index a553f06f7..b976a852c 100644
|
||||
--- a/src/dsp/rescaler_neon.c
|
||||
+++ b/src/dsp/rescaler_neon.c
|
||||
@@ -81,14 +81,13 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
|
||||
const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half);
|
||||
const uint16x4_t C0 = vmovn_u32(B0);
|
||||
const uint16x4_t C1 = vmovn_u32(B1);
|
||||
- const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1));
|
||||
+ const uint8x8_t D = vqmovn_u16(vcombine_u16(C0, C1));
|
||||
vst1_u8(dst + x_out, D);
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t J = frow[x_out];
|
||||
const int v = (int)MULT_FIX_C(J, fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
} else {
|
||||
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
|
||||
@@ -102,7 +101,7 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
|
||||
const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half);
|
||||
const uint16x4_t E0 = vmovn_u32(D0);
|
||||
const uint16x4_t E1 = vmovn_u32(D1);
|
||||
- const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1));
|
||||
+ const uint8x8_t F = vqmovn_u16(vcombine_u16(E0, E1));
|
||||
vst1_u8(dst + x_out, F);
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
@@ -110,8 +109,7 @@ static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) {
|
||||
+ (uint64_t)B * irow[x_out];
|
||||
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
|
||||
const int v = (int)MULT_FIX_C(J, fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,23 +133,22 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
|
||||
for (x_out = 0; x_out < max_span; x_out += 8) {
|
||||
LOAD_32x8(frow + x_out, in0, in1);
|
||||
LOAD_32x8(irow + x_out, in2, in3);
|
||||
- const uint32x4_t A0 = MULT_FIX(in0, yscale_half);
|
||||
- const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
|
||||
+ const uint32x4_t A0 = MULT_FIX_FLOOR(in0, yscale_half);
|
||||
+ const uint32x4_t A1 = MULT_FIX_FLOOR(in1, yscale_half);
|
||||
const uint32x4_t B0 = vqsubq_u32(in2, A0);
|
||||
const uint32x4_t B1 = vqsubq_u32(in3, A1);
|
||||
- const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
|
||||
- const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
|
||||
+ const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
|
||||
+ const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
|
||||
const uint16x4_t D0 = vmovn_u32(C0);
|
||||
const uint16x4_t D1 = vmovn_u32(C1);
|
||||
- const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
|
||||
+ const uint8x8_t E = vqmovn_u16(vcombine_u16(D0, D1));
|
||||
vst1_u8(dst + x_out, E);
|
||||
STORE_32x8(A0, A1, irow + x_out);
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
- const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ const uint32_t frac = (uint32_t)MULT_FIX_FLOOR_C(frow[x_out], yscale);
|
||||
+ const int v = (int)MULT_FIX_C(irow[x_out] - frac, fxy_scale);
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
}
|
||||
} else {
|
||||
@@ -161,14 +158,13 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
|
||||
const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half);
|
||||
const uint16x4_t B0 = vmovn_u32(A0);
|
||||
const uint16x4_t B1 = vmovn_u32(A1);
|
||||
- const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1));
|
||||
+ const uint8x8_t C = vqmovn_u16(vcombine_u16(B0, B1));
|
||||
vst1_u8(dst + x_out, C);
|
||||
STORE_32x8(zero, zero, irow + x_out);
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/src/dsp/rescaler_sse2.c b/src/dsp/rescaler_sse2.c
|
||||
index f7461a452..d7effea16 100644
|
||||
--- a/src/dsp/rescaler_sse2.c
|
||||
+++ b/src/dsp/rescaler_sse2.c
|
||||
@@ -225,35 +225,6 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
|
||||
_mm_storel_epi64((__m128i*)dst, G);
|
||||
}
|
||||
|
||||
-static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
|
||||
- const __m128i* const A1,
|
||||
- const __m128i* const A2,
|
||||
- const __m128i* const A3,
|
||||
- const __m128i* const mult,
|
||||
- uint8_t* const dst) {
|
||||
- const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
|
||||
- const __m128i B0 = _mm_mul_epu32(*A0, *mult);
|
||||
- const __m128i B1 = _mm_mul_epu32(*A1, *mult);
|
||||
- const __m128i B2 = _mm_mul_epu32(*A2, *mult);
|
||||
- const __m128i B3 = _mm_mul_epu32(*A3, *mult);
|
||||
- const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
|
||||
- const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
|
||||
-#if (WEBP_RESCALER_RFIX < 32)
|
||||
- const __m128i D2 =
|
||||
- _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
|
||||
- const __m128i D3 =
|
||||
- _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
|
||||
-#else
|
||||
- const __m128i D2 = _mm_and_si128(B2, mask);
|
||||
- const __m128i D3 = _mm_and_si128(B3, mask);
|
||||
-#endif
|
||||
- const __m128i E0 = _mm_or_si128(D0, D2);
|
||||
- const __m128i E1 = _mm_or_si128(D1, D3);
|
||||
- const __m128i F = _mm_packs_epi32(E0, E1);
|
||||
- const __m128i G = _mm_packus_epi16(F, F);
|
||||
- _mm_storel_epi64((__m128i*)dst, G);
|
||||
-}
|
||||
-
|
||||
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
|
||||
int x_out;
|
||||
uint8_t* const dst = wrk->dst;
|
||||
@@ -274,8 +245,7 @@ static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const uint32_t J = frow[x_out];
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
} else {
|
||||
const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
|
||||
@@ -308,8 +278,7 @@ static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
|
||||
+ (uint64_t)B * irow[x_out];
|
||||
const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
|
||||
const int v = (int)MULT_FIX(J, wrk->fy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,20 +297,15 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
|
||||
const int scale_xy = wrk->fxy_scale;
|
||||
const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy);
|
||||
const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale);
|
||||
- const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
|
||||
for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
|
||||
__m128i A0, A1, A2, A3, B0, B1, B2, B3;
|
||||
LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3);
|
||||
LoadDispatchAndMult_SSE2(frow + x_out, &mult_y, &B0, &B1, &B2, &B3);
|
||||
{
|
||||
- const __m128i C0 = _mm_add_epi64(B0, rounder);
|
||||
- const __m128i C1 = _mm_add_epi64(B1, rounder);
|
||||
- const __m128i C2 = _mm_add_epi64(B2, rounder);
|
||||
- const __m128i C3 = _mm_add_epi64(B3, rounder);
|
||||
- const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac
|
||||
- const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
|
||||
- const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX);
|
||||
- const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX);
|
||||
+ const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX); // = frac
|
||||
+ const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
|
||||
+ const __m128i D2 = _mm_srli_epi64(B2, WEBP_RESCALER_RFIX);
|
||||
+ const __m128i D3 = _mm_srli_epi64(B3, WEBP_RESCALER_RFIX);
|
||||
const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac
|
||||
const __m128i E1 = _mm_sub_epi64(A1, D1);
|
||||
const __m128i E2 = _mm_sub_epi64(A2, D2);
|
||||
@@ -352,14 +316,13 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
|
||||
const __m128i G1 = _mm_or_si128(D1, F3);
|
||||
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
|
||||
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
|
||||
- ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
|
||||
+ ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
|
||||
}
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
- const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
|
||||
- const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ const uint32_t frac = (int)MULT_FIX_FLOOR(frow[x_out], yscale);
|
||||
+ const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = frac; // new fractional start
|
||||
}
|
||||
} else {
|
||||
@@ -375,8 +338,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
|
||||
}
|
||||
for (; x_out < x_out_max; ++x_out) {
|
||||
const int v = (int)MULT_FIX(irow[x_out], scale);
|
||||
- assert(v >= 0 && v <= 255);
|
||||
- dst[x_out] = v;
|
||||
+ dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
|
||||
irow[x_out] = 0;
|
||||
}
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
From 4b282e13ad0cf7f1a3b4431788bddef1d6b11762 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Wed, 9 May 2018 17:36:13 -0700
|
||||
Subject: [PATCH] gif2webp: fix transcode of loop count=65535
|
||||
|
||||
with loop_compatibility disabled (the default), non-zero loop counts
|
||||
will be incremented by 1 for browser rendering compatibility. the max,
|
||||
65535, is a special case as the muxer will fail if it is exceeded; avoid
|
||||
increasing the limit in this case. this isn't 100% correct, but should
|
||||
be close enough given the high number of iterations.
|
||||
|
||||
BUG=webp:382
|
||||
---
|
||||
examples/anim_diff.c | 14 ++++++++++++--
|
||||
examples/anim_util.c | 2 ++
|
||||
examples/anim_util.h | 6 ++++++
|
||||
examples/gif2webp.c | 2 +-
|
||||
4 files changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/examples/anim_diff.c b/examples/anim_diff.c
|
||||
index e74a915..a461ce2 100644
|
||||
--- a/examples/anim_diff.c
|
||||
+++ b/examples/anim_diff.c
|
||||
@@ -143,8 +143,18 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
||||
if (!ok) return 0; // These are fatal failures, can't proceed.
|
||||
|
||||
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
||||
- ok = CompareValues(img1->loop_count, img2->loop_count,
|
||||
- "Loop count mismatch") && ok;
|
||||
+ int max_loop_count_workaround = 0;
|
||||
+ // Transcodes to webp increase the gif loop count by 1 for compatibility.
|
||||
+ // When the gif has the maximum value the webp value will be off by one.
|
||||
+ if ((img1->format == ANIM_GIF && img1->loop_count == 65536 &&
|
||||
+ img2->format == ANIM_WEBP && img2->loop_count == 65535) ||
|
||||
+ (img1->format == ANIM_WEBP && img1->loop_count == 65535 &&
|
||||
+ img2->format == ANIM_GIF && img2->loop_count == 65536)) {
|
||||
+ max_loop_count_workaround = 1;
|
||||
+ }
|
||||
+ ok = (max_loop_count_workaround ||
|
||||
+ CompareValues(img1->loop_count, img2->loop_count,
|
||||
+ "Loop count mismatch")) && ok;
|
||||
ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor,
|
||||
premultiply) && ok;
|
||||
}
|
||||
diff --git a/examples/anim_util.c b/examples/anim_util.c
|
||||
index c7a05c7..ee3e332 100644
|
||||
--- a/examples/anim_util.c
|
||||
+++ b/examples/anim_util.c
|
||||
@@ -275,6 +275,7 @@ static int ReadAnimatedWebP(const char filename[],
|
||||
prev_frame_timestamp = timestamp;
|
||||
}
|
||||
ok = dump_ok;
|
||||
+ if (ok) image->format = ANIM_WEBP;
|
||||
|
||||
End:
|
||||
WebPAnimDecoderDelete(dec);
|
||||
@@ -687,6 +688,7 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
||||
}
|
||||
}
|
||||
}
|
||||
+ image->format = ANIM_GIF;
|
||||
DGifCloseFile(gif, NULL);
|
||||
return 1;
|
||||
}
|
||||
diff --git a/examples/anim_util.h b/examples/anim_util.h
|
||||
index 8063121..574e032 100644
|
||||
--- a/examples/anim_util.h
|
||||
+++ b/examples/anim_util.h
|
||||
@@ -22,6 +22,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
+typedef enum {
|
||||
+ ANIM_GIF,
|
||||
+ ANIM_WEBP
|
||||
+} AnimatedFileFormat;
|
||||
+
|
||||
typedef struct {
|
||||
uint8_t* rgba; // Decoded and reconstructed full frame.
|
||||
int duration; // Frame duration in milliseconds.
|
||||
@@ -29,6 +34,7 @@ typedef struct {
|
||||
} DecodedFrame;
|
||||
|
||||
typedef struct {
|
||||
+ AnimatedFileFormat format;
|
||||
uint32_t canvas_width;
|
||||
uint32_t canvas_height;
|
||||
uint32_t bgcolor;
|
||||
diff --git a/examples/gif2webp.c b/examples/gif2webp.c
|
||||
index b61f273..caaed7a 100644
|
||||
--- a/examples/gif2webp.c
|
||||
+++ b/examples/gif2webp.c
|
||||
@@ -478,7 +478,7 @@ int main(int argc, const char *argv[]) {
|
||||
stored_loop_count = 1;
|
||||
loop_count = 1;
|
||||
}
|
||||
- } else if (loop_count > 0) {
|
||||
+ } else if (loop_count > 0 && loop_count < 65535) {
|
||||
// adapt GIF's semantic to WebP's (except in the infinite-loop case)
|
||||
loop_count += 1;
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
26
libwebp-freeglut.patch
Normal file
26
libwebp-freeglut.patch
Normal file
@ -0,0 +1,26 @@
|
||||
diff -rupN --no-dereference libwebp-1.1.0/CMakeLists.txt libwebp-1.1.0-new/CMakeLists.txt
|
||||
--- libwebp-1.1.0/CMakeLists.txt 2019-12-21 14:37:43.000000000 +0100
|
||||
+++ libwebp-1.1.0-new/CMakeLists.txt 2020-01-07 08:40:04.574415507 +0100
|
||||
@@ -459,8 +459,8 @@ endif()
|
||||
|
||||
if(WEBP_BUILD_VWEBP)
|
||||
# vwebp
|
||||
- find_package(GLUT)
|
||||
- if(GLUT_FOUND)
|
||||
+ find_package(FreeGLUT)
|
||||
+ if(FreeGLUT_FOUND)
|
||||
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp")
|
||||
add_executable(vwebp ${VWEBP_SRCS})
|
||||
diff -rupN --no-dereference libwebp-1.1.0/examples/vwebp.c libwebp-1.1.0-new/examples/vwebp.c
|
||||
--- libwebp-1.1.0/examples/vwebp.c 2019-12-21 14:37:43.000000000 +0100
|
||||
+++ libwebp-1.1.0-new/examples/vwebp.c 2020-01-07 08:40:04.575415463 +0100
|
||||
@@ -27,7 +27,7 @@
|
||||
#if defined(HAVE_GLUT_GLUT_H)
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
-#include <GL/glut.h>
|
||||
+#include <GL/freeglut.h>
|
||||
#ifdef FREEGLUT
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
40
libwebp.spec
40
libwebp.spec
@ -1,25 +1,15 @@
|
||||
Name: libwebp
|
||||
Version: 1.0.0
|
||||
Version: 1.1.0
|
||||
Release: 5
|
||||
URL: https://webmproject.org/
|
||||
URL: http://www.linuxfromscratch.org/blfs/view/svn/general/libwebp.html
|
||||
Summary: Library and tools for the WebP graphics format
|
||||
License: BSD
|
||||
Source0: https://downloads.webmproject.org/releases/webp/%{name}-%{version}.tar.gz
|
||||
|
||||
Patch6000: libwebp-fix-transcode-of-loop-count-to-65535.patch
|
||||
Patch6001: libwebp-fix-invalid-check-for-buffer-size.patch
|
||||
Patch6002: libwebp-Fix-for-thread-race-heap-use-after-free.patch
|
||||
Patch6003: libwebp-fix-riff-size-checks.patch
|
||||
Patch6004: libwebp-ChunkVerifyAndAssign-validate-chunk_size.patch
|
||||
Patch6005: libwebp-fix-alpha-filtering-crash-when-image-width-is-larger-than-radius.patch
|
||||
Patch6006: libwebp-fail-on-multiple-image-chunks.patch
|
||||
Patch6007: libwebp-fix-endian-problems-in-pattern-copy.patch
|
||||
Patch6008: libwebp-Fix-VP8IoTeardownHook-being-called-twice-on-worker-sync-failure.patch
|
||||
Patch6009: libwebp-fix-read-overflow-while-parsing-VP8X-chunk.patch
|
||||
Patch6010: libwebp-Make-sure-partition0-is-read-before-VP8-data-in-IDecode.patch
|
||||
Patch6011: libwebp-fix-rescaling-rounding-inaccuracy.patch
|
||||
Patch6012: libwebp-Allow-for-a-non-initialized-alpha-decompressor-in-DoRemap.patch
|
||||
Patch6013: libwebp-fix-rounding-error.patch
|
||||
Patch6000: libwebp-freeglut.patch
|
||||
Patch6001: backport-CVE-2023-1999.patch
|
||||
Patch6002: backport-0001-CVE-2023-4863.patch
|
||||
Patch6003: backport-0002-CVE-2023-4863.patch
|
||||
|
||||
BuildRequires: libjpeg-devel libpng-devel giflib-devel libtiff-devel
|
||||
BuildRequires: java-devel jpackage-utils swig freeglut-devel
|
||||
@ -124,6 +114,24 @@ cp swig/*.jar swig/*.so %{buildroot}/%{_libdir}/%{name}-java/
|
||||
%{_mandir}/man*/*
|
||||
|
||||
%changelog
|
||||
* Tue Sep 26 2023 liweigang <liweiganga@uniuontech.com> - 1.1.0-5
|
||||
- add missing patch
|
||||
|
||||
* Fri Sep 15 2023 Funda Wang <fundawang@yeah.net> - 1.1.0-4
|
||||
- fix CVE-2023-4863
|
||||
|
||||
* Fri May 26 2023 zhangpan <zhangpan103@h-partners.com> - 1.1.0-3
|
||||
- fix CVE-2023-1999
|
||||
|
||||
* Wed Dec 16 2020 hanhui <hanhui15@huawei.com> - 1.1.0-2
|
||||
- modify url
|
||||
|
||||
* Wed Apr 15 2020 fengtao<fengtao40@huawei.com> - 1.1.0-1
|
||||
- Type:enhancement
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:update to 1.1.0
|
||||
|
||||
* Fri Mar 13 2020 openEuler Buildteam <buildteam@openeuler.org> - 1.0.0-5
|
||||
- fix fuzz
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user