Update simplewebp.h.

This commit is contained in:
Miku AuahDark
2026-07-19 09:57:56 +08:00
parent 8a4a1afab6
commit 9f54bb93c6
2 changed files with 141 additions and 25 deletions
+1 -1
View File
@@ -111,7 +111,7 @@ This distribution contains code from the following projects (full license text b
- simplewebp - simplewebp
Website: https://github.com/MikuAuahDark/simplewebp Website: https://github.com/MikuAuahDark/simplewebp
Source download: https://github.com/MikuAuahDark/simplewebp/blob/85157b0e5e115a76db87d5484570e44cf5c34e87/simplewebp.h Source download: https://github.com/MikuAuahDark/simplewebp/blob/d1a728a1f8ec7348ca2a5039b6dd813b83986fbb/simplewebp.h
License: 3-Clause BSD License: 3-Clause BSD
Copyright (c) 2010 Google Inc., 2023 Miku AuahDark Copyright (c) 2010 Google Inc., 2023 Miku AuahDark
+140 -24
View File
@@ -4395,6 +4395,24 @@ static simplewebp_error swebp__vp8l_canonical_code(
} }
} }
if (symbol_count == 0)
return SIMPLEWEBP_CORRUPT_ERROR;
else if (symbol_count > 1)
{
int open_slots = 1;
/* Max allowed code length is 15 */
for (i = 0; i < 15; i++)
{
open_slots = (open_slots << 1) - base[i];
if (open_slots < 0)
return SIMPLEWEBP_CORRUPT_ERROR;
}
if (open_slots != 0)
return SIMPLEWEBP_CORRUPT_ERROR;
}
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
simplewebp_u16 c = base[i]; simplewebp_u16 c = base[i];
@@ -4480,6 +4498,8 @@ static simplewebp_error swebp__vp8l_decode_code_complex(
if (br->eos) if (br->eos)
return SIMPLEWEBP_IO_ERROR; return SIMPLEWEBP_IO_ERROR;
if (limit > size)
return SIMPLEWEBP_CORRUPT_ERROR;
err = swebp__vp8l_canonical_code(simplewebp, lencode_lengths, 19, &lc, lencode_treemem); err = swebp__vp8l_canonical_code(simplewebp, lencode_lengths, 19, &lc, lencode_treemem);
if (err != SIMPLEWEBP_NO_ERROR) if (err != SIMPLEWEBP_NO_ERROR)
@@ -4496,10 +4516,7 @@ static simplewebp_error swebp__vp8l_decode_code_complex(
c = 0; c = 0;
if (br->eos) if (br->eos)
{
swebp__dealloc(simplewebp, lc.tree);
return SIMPLEWEBP_IO_ERROR; return SIMPLEWEBP_IO_ERROR;
}
switch (s) switch (s)
{ {
@@ -4540,10 +4557,9 @@ static simplewebp_error swebp__vp8l_decode_code_complex(
} }
if (br->eos) if (br->eos)
{
swebp__dealloc(simplewebp, lc.tree);
return SIMPLEWEBP_IO_ERROR; return SIMPLEWEBP_IO_ERROR;
} if (s > (size - count))
return SIMPLEWEBP_CORRUPT_ERROR;
while (s--) while (s--)
lengths[count++] = (simplewebp_u8) c; lengths[count++] = (simplewebp_u8) c;
@@ -4562,11 +4578,36 @@ static simplewebp_error swebp__vp8l_decode_code(
{ {
if (swebp__vp8l_bitread_read(br, 1)) if (swebp__vp8l_bitread_read(br, 1))
{ {
simplewebp_u8 symbol[2];
simplewebp_bool two_symbols = (simplewebp_bool) swebp__vp8l_bitread_read(br, 1); simplewebp_bool two_symbols = (simplewebp_bool) swebp__vp8l_bitread_read(br, 1);
symbol[0] = (simplewebp_u8) swebp__vp8l_bitread_read(br, 1 + swebp__vp8l_bitread_read(br, 1) * 7);
symbol[1] = two_symbols ? ((simplewebp_u8) swebp__vp8l_bitread_read(br, 8)) : 0;
if (br->eos)
return SIMPLEWEBP_IO_ERROR;
if (symbol[0] >= size || (two_symbols && symbol[1] >= size))
return SIMPLEWEBP_CORRUPT_ERROR;
if (two_symbols)
{
/* Reorder symbol if needed */
if (symbol[0] > symbol[1])
{
simplewebp_u8 tempsym = symbol[0];
symbol[0] = symbol[1];
symbol[1] = tempsym;
}
else if (symbol[0] == symbol[1])
{
two_symbols = 0;
symbol[1] = 0;
}
}
code->tree = NULL; code->tree = NULL;
code->size = two_symbols + 1; code->size = (simplewebp_u16) two_symbols + 1;
code->symbol[0] = swebp__vp8l_bitread_read(br, 1 + swebp__vp8l_bitread_read(br, 1) * 7); code->symbol[0] = symbol[0];
code->symbol[1] = two_symbols ? swebp__vp8l_bitread_read(br, 8) : 0; code->symbol[1] = symbol[1];
return br->eos ? SIMPLEWEBP_IO_ERROR : SIMPLEWEBP_NO_ERROR; return br->eos ? SIMPLEWEBP_IO_ERROR : SIMPLEWEBP_NO_ERROR;
} }
else else
@@ -4613,8 +4654,13 @@ static simplewebp_error swebp__vp8l_decode_group(
static size_t swebp__hash_color(simplewebp_u8 bits, struct swebp__pixel c) static size_t swebp__hash_color(simplewebp_u8 bits, struct swebp__pixel c)
{ {
size_t value = (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b; simplewebp_u32 r, g, b, a, value;
return ((0x1e35a7bd * value) & 0xFFFFFFFF) >> (32 - bits); r = c.r;
g = c.g;
b = c.b;
a = c.a;
value = (a << 24) | (r << 16) | (g << 8) | b;
return ((0x1e35a7bdU * value) & 0xFFFFFFFFU) >> (32 - bits);
} }
static void swebp__vp8l_put_cache(simplewebp_u8 bits, struct swebp__pixel *ccache, struct swebp__pixel color) static void swebp__vp8l_put_cache(simplewebp_u8 bits, struct swebp__pixel *ccache, struct swebp__pixel color)
@@ -4643,13 +4689,16 @@ static simplewebp_error swebp__decode_vp8l_image(
struct swebp__pixel **dest struct swebp__pixel **dest
) )
{ {
simplewebp_bool has_ccache;
simplewebp_u8 ccache_bits, entropy_bits; simplewebp_u8 ccache_bits, entropy_bits;
struct swebp__pixel *color_cache, *entropy, *image; struct swebp__pixel *color_cache, *entropy, *image;
struct swebp__vp8l_group *groups; struct swebp__vp8l_group *groups;
size_t group_count, entropy_stride, i; size_t group_count, entropy_stride, i, dimensions;
simplewebp_error err; simplewebp_error err;
dimensions = width * height;
color_cache = NULL; color_cache = NULL;
ccache_bits = 0;
group_count = 1; group_count = 1;
entropy_bits = 0; entropy_bits = 0;
entropy_stride = 0; entropy_stride = 0;
@@ -4664,14 +4713,25 @@ static simplewebp_error swebp__decode_vp8l_image(
} }
image = *dest; image = *dest;
ccache_bits = swebp__vp8l_bitread_read(br, 1) ? swebp__vp8l_bitread_read(br, 4) : 0; has_ccache = (simplewebp_bool) swebp__vp8l_bitread_read(br, 1);
if (br->eos) if (br->eos)
return SIMPLEWEBP_IO_ERROR; return SIMPLEWEBP_IO_ERROR;
if (ccache_bits)
if (has_ccache)
{ {
color_cache = (struct swebp__pixel*) swebp__alloc(simplewebp, (1 << ccache_bits) * 4); size_t ccache_bits_size;
ccache_bits = (simplewebp_u8) swebp__vp8l_bitread_read(br, 4);
if (br->eos)
return SIMPLEWEBP_IO_ERROR;
if (ccache_bits < 1 || ccache_bits > 11)
return SIMPLEWEBP_CORRUPT_ERROR;
ccache_bits_size = (1 << ccache_bits) * 4;
color_cache = (struct swebp__pixel*) swebp__alloc(simplewebp, ccache_bits_size);
if (!color_cache) if (!color_cache)
return SIMPLEWEBP_ALLOC_ERROR; return SIMPLEWEBP_ALLOC_ERROR;
memset(color_cache, 0, ccache_bits_size);
} }
if (is_main) if (is_main)
@@ -4733,7 +4793,7 @@ static simplewebp_error swebp__decode_vp8l_image(
if (err == SIMPLEWEBP_NO_ERROR) if (err == SIMPLEWEBP_NO_ERROR)
{ {
/* Main image decoding routines. */ /* Main image decoding routines. */
for (i = 0; i < width * height;) for (i = 0; i < dimensions;)
{ {
struct swebp__pixel *pixel; struct swebp__pixel *pixel;
struct swebp__vp8l_group *g = groups; struct swebp__vp8l_group *g = groups;
@@ -4754,6 +4814,11 @@ static simplewebp_error swebp__decode_vp8l_image(
} }
codeword = swebp__vp8l_read_code(br, &g->code[0]); codeword = swebp__vp8l_read_code(br, &g->code[0]);
if (br->eos)
{
err = SIMPLEWEBP_IO_ERROR;
break;
}
if (codeword < swebp__vp8l_literals_count) if (codeword < swebp__vp8l_literals_count)
{ {
@@ -4762,6 +4827,12 @@ static simplewebp_error swebp__decode_vp8l_image(
color.g = (simplewebp_u8) codeword; color.g = (simplewebp_u8) codeword;
color.b = (simplewebp_u8) swebp__vp8l_read_code(br, &g->code[2]); color.b = (simplewebp_u8) swebp__vp8l_read_code(br, &g->code[2]);
color.a = (simplewebp_u8) swebp__vp8l_read_code(br, &g->code[3]); color.a = (simplewebp_u8) swebp__vp8l_read_code(br, &g->code[3]);
if (br->eos)
{
err = SIMPLEWEBP_IO_ERROR;
break;
}
*pixel = color; *pixel = color;
i++; i++;
@@ -4777,12 +4848,26 @@ static simplewebp_error swebp__decode_vp8l_image(
distcode = swebp__vp8l_read_code(br, &g->code[4]); distcode = swebp__vp8l_read_code(br, &g->code[4]);
distance = swebp__vp8l_lendst(br, distcode); distance = swebp__vp8l_lendst(br, distcode);
if (br->eos)
{
err = SIMPLEWEBP_IO_ERROR;
break;
}
if (distance < swebp__vp8l_offset_count) if (distance < swebp__vp8l_offset_count)
offset = swebp__vp8l_offsets[distance][0] + swebp__vp8l_offsets[distance][1] * width; offset = (ptrdiff_t) swebp__vp8l_offsets[distance][0]
+ (ptrdiff_t) swebp__vp8l_offsets[distance][1]
* (ptrdiff_t) width;
else else
offset = distance - swebp__vp8l_offset_count + 1; offset = (ptrdiff_t) (distance - swebp__vp8l_offset_count + 1);
offset = offset < 1 ? 1 : offset; offset = offset < 1 ? 1 : offset;
if ((size_t) offset > i || (length + 1) > (dimensions - i))
{
err = SIMPLEWEBP_CORRUPT_ERROR;
break;
}
for (j = 0; j <= length; j++) for (j = 0; j <= length; j++)
{ {
*pixel = pixel[-offset]; *pixel = pixel[-offset];
@@ -4796,6 +4881,12 @@ static simplewebp_error swebp__decode_vp8l_image(
*pixel = color_cache[codeword - swebp__vp8l_litlen_count]; *pixel = color_cache[codeword - swebp__vp8l_litlen_count];
i++; i++;
} }
if (br->eos)
{
err = SIMPLEWEBP_IO_ERROR;
break;
}
} }
} }
@@ -4943,10 +5034,10 @@ static struct swebp__pixel swebp__clamp_add_subtract_half(struct swebp__pixel a,
static struct swebp__pixel swebp__apply_predictor( static struct swebp__pixel swebp__apply_predictor(
simplewebp_u8 type, simplewebp_u8 type,
struct swebp__pixel *l, const struct swebp__pixel *l,
struct swebp__pixel *tl, const struct swebp__pixel *tl,
struct swebp__pixel *t, const struct swebp__pixel *t,
struct swebp__pixel *tr const struct swebp__pixel *tr
) )
{ {
const struct swebp__pixel black = {0, 0, 0, 255}; const struct swebp__pixel black = {0, 0, 0, 255};
@@ -5000,30 +5091,48 @@ static void swebp__apply_predictor_transform(
{ {
size_t x, y; size_t x, y;
size_t tiles_per_row = swebp__subsample_size(width, bits); size_t tiles_per_row = swebp__subsample_size(width, bits);
const struct swebp__pixel black = {0, 0, 0, 255};
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
{ {
const struct swebp__pixel *l, *tl, *t, *tr;
struct swebp__pixel result; struct swebp__pixel result;
simplewebp_u8 type = 0; simplewebp_u8 type = 0;
l = tl = t = tr = &black;
if (x > 0) if (x > 0)
{ {
l = rgba - 1;
if (y > 0) if (y > 0)
{ {
size_t tile_x = x >> bits; size_t tile_x = x >> bits;
size_t tile_y = y >> bits; size_t tile_y = y >> bits;
size_t tile_index = tile_y * tiles_per_row + tile_x; size_t tile_index = tile_y * tiles_per_row + tile_x;
type = predictor_data[tile_index].g; type = predictor_data[tile_index].g;
tl = rgba - width - 1;
t = rgba - width;
tr = rgba - width + 1;
} }
else else
type = 1; type = 1;
} }
else else
type = y > 0 ? 2 : 0; {
if (y > 0)
{
type = 2;
t = rgba - width;
tr = rgba - width + 1;
}
else
type = 0;
}
result = swebp__apply_predictor(type, rgba - 1, rgba - (width + 1), rgba - width, rgba - (width - 1)); result = swebp__apply_predictor(type, l, tl, t, tr);
rgba->r += result.r; rgba->r += result.r;
rgba->g += result.g; rgba->g += result.g;
rgba->b += result.b; rgba->b += result.b;
@@ -5177,7 +5286,10 @@ static simplewebp_error swebp__decode_lossless_bitstream_main(
ttype = swebp__vp8l_bitread_read(br, 2); ttype = swebp__vp8l_bitread_read(br, 2);
if (br->eos) if (br->eos)
{
swebp__batch_free(simplewebp, (void **) filter_data, 4);
return SIMPLEWEBP_CORRUPT_ERROR; return SIMPLEWEBP_CORRUPT_ERROR;
}
switch (ttype) switch (ttype)
{ {
@@ -5214,6 +5326,8 @@ static simplewebp_error swebp__decode_lossless_bitstream_main(
if (err != SIMPLEWEBP_NO_ERROR) if (err != SIMPLEWEBP_NO_ERROR)
{ {
/* Error occured. Rollback. */ /* Error occured. Rollback. */
if (filter_out)
swebp__dealloc(simplewebp, filter_out);
swebp__batch_free(simplewebp, (void **) filter_data, 4); swebp__batch_free(simplewebp, (void **) filter_data, 4);
return err; return err;
} }
@@ -5457,6 +5571,7 @@ simplewebp_error simplewebp_load_from_file(FILE *file, const simplewebp_allocato
simplewebp_input input; simplewebp_input input;
simplewebp_error err; simplewebp_error err;
*out = NULL;
err = simplewebp_input_from_file(file, &input); err = simplewebp_input_from_file(file, &input);
if (err != SIMPLEWEBP_NO_ERROR) if (err != SIMPLEWEBP_NO_ERROR)
return err; return err;
@@ -5473,6 +5588,7 @@ simplewebp_error simplewebp_load_from_filename(const char *filename, const simpl
simplewebp_input input; simplewebp_input input;
simplewebp_error err; simplewebp_error err;
*out = NULL;
err = simplewebp_input_from_filename(filename, &input); err = simplewebp_input_from_filename(filename, &input);
if (err != SIMPLEWEBP_NO_ERROR) if (err != SIMPLEWEBP_NO_ERROR)
return err; return err;