From c696aadf69fcfa240e713888b8057034df6e945f Mon Sep 17 00:00:00 2001 From: James Zern Date: Thu, 2 Apr 2026 10:20:09 -0700 Subject: [PATCH] ALPHInit: move assignment closer to first use This fixes a spurious unsigned integer overflow with invalid content: ``` src/dec/alpha_dec.c:61:44: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long') ``` Bug: 498965803, 498966235, 498966511, 498967090 Change-Id: I350d9144d0c1e4e35286e9e1ca68a574ff6f86a1 --- src/dec/alpha_dec.c | 24 +++++++++++++----------- tests/fuzzer/advanced_api_fuzzer.cc | 24 ++++++++++++++++++++++++ tests/fuzzer/animation_api_fuzzer.cc | 14 ++++++++++++++ tests/fuzzer/animdecoder_fuzzer.cc | 11 +++++++++++ tests/fuzzer/simple_api_fuzzer.cc | 14 ++++++++++++++ 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/dec/alpha_dec.c b/src/dec/alpha_dec.c index 4ef11188..2777e3ce 100644 --- a/src/dec/alpha_dec.c +++ b/src/dec/alpha_dec.c @@ -58,7 +58,6 @@ WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, uint8_t* output) { int ok = 0; const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; - const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; int rsrv; VP8Io* const io = &dec->io; @@ -101,16 +100,19 @@ WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, io->crop_bottom = src_io->crop_bottom; // No need to copy the scaling parameters. - if (dec->method == ALPHA_NO_COMPRESSION) { - const size_t alpha_decoded_size = dec->width * dec->height; - ok = (alpha_data_size >= alpha_decoded_size); - } else { - assert(dec->method == ALPHA_LOSSLESS_COMPRESSION); - { - const uint8_t* WEBP_BIDI_INDEXABLE const bounded_alpha_data = - WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(const uint8_t*, alpha_data, - alpha_data_size); - ok = VP8LDecodeAlphaHeader(dec, bounded_alpha_data, alpha_data_size); + { + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; + if (dec->method == ALPHA_NO_COMPRESSION) { + const size_t alpha_decoded_size = dec->width * dec->height; + ok = (alpha_data_size >= alpha_decoded_size); + } else { + assert(dec->method == ALPHA_LOSSLESS_COMPRESSION); + { + const uint8_t* WEBP_BIDI_INDEXABLE const bounded_alpha_data = + WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(const uint8_t*, alpha_data, + alpha_data_size); + ok = VP8LDecodeAlphaHeader(dec, bounded_alpha_data, alpha_data_size); + } } } diff --git a/tests/fuzzer/advanced_api_fuzzer.cc b/tests/fuzzer/advanced_api_fuzzer.cc index 8edc87b9..2a437354 100644 --- a/tests/fuzzer/advanced_api_fuzzer.cc +++ b/tests/fuzzer/advanced_api_fuzzer.cc @@ -18,9 +18,11 @@ #include #include #include +#include #include #include "./fuzz_utils.h" +#include "gtest/gtest.h" #include "src/dec/webpi_dec.h" #include "src/utils/rescaler_utils.h" #include "webp/decode.h" @@ -162,3 +164,25 @@ FUZZ_TEST(AdvancedApi, AdvancedApiTest) #endif /*incremental=*/fuzztest::Arbitrary(), fuzz_utils::ArbitraryValidWebPDecoderOptions()); + +TEST(AdvancedApi, Buganizer498966235) { + AdvancedApiTest( + std::string( + "RIFF\014|" + "\000\000WEBPVP8X\n\000\000\000\020\000\000D\002\000\000\017\000\000A" + "LPH5\000\000\000\004\327\000\000\000\000\000\000c8\345S\000\243\000" + "\253c\311\000\027\000\000\000\200\000\000\000\000\240\"AE\001\000" + "\000\0008<" + "ALP\010\000s\002\000\000\000\000\000\000\000\000\000ALPH\000\000\000" + "\000VP8 " + "(\000\000\000\224\001\000\235\001*\003\000\020\000\003,\000~" + "\342\000\000se\002ionR\265Vq\302M}\"webp\"r\010\003\000\020#" + "\366\356\002\323\220\000 " + "\212N@\000\026\327A\367\266\201\201\"IFF@\"RIFF\"&\226!" + "VP\n8Rg\000\0001\"\335\"I\"XEBP\"\002\002\"\367\\x0\203\203\203\341" + "\341l,\203\\sectiqncJUN=\"sectistre\\x9D\\x01\\x2A\"JUKQ\"", + 257), + 68, 3, true, + fuzz_utils::WebPDecoderOptionsCpp{ + 0, 0, 1, 5, 10, 5, 9, 0, 1, 3, 0, 72, 0, 83, {0, 0, 0, 0, 0}}); +} diff --git a/tests/fuzzer/animation_api_fuzzer.cc b/tests/fuzzer/animation_api_fuzzer.cc index c7363197..90af64f3 100644 --- a/tests/fuzzer/animation_api_fuzzer.cc +++ b/tests/fuzzer/animation_api_fuzzer.cc @@ -16,9 +16,11 @@ #include #include +#include #include #include "./fuzz_utils.h" +#include "gtest/gtest.h" #include "webp/decode.h" #include "webp/demux.h" #include "webp/mux_types.h" @@ -88,3 +90,15 @@ FUZZ_TEST(AnimationApi, AnimationApiTest) // Animations only support 4 (out of 12) modes. fuzztest::ElementOf({MODE_RGBA, MODE_BGRA, MODE_rgbA, MODE_bgrA})); + +TEST(AnimationApi, Buganizer498965803) { + AnimationApiTest( + std::string("ALPH\000\000\000\000\000\000\000\000\021\000\000\000\t\305" + "\006d\301\013\177\000\000webp\034\205\000#@VP8 " + "!\000\000\000v\003\000\235\001*\007\200\"\000\0020(" + "\000\377\377\377\003\000\000\000\311\311\311\311\311\311\311" + "\311\311\311\311\311\311\311\311\311\311\311\311\311\311\211" + "\311\311\311\311\311\030\030\030\030\030\030\311\311", + 98), + false, static_cast(1)); +} diff --git a/tests/fuzzer/animdecoder_fuzzer.cc b/tests/fuzzer/animdecoder_fuzzer.cc index a092c710..4ad8604e 100644 --- a/tests/fuzzer/animdecoder_fuzzer.cc +++ b/tests/fuzzer/animdecoder_fuzzer.cc @@ -16,10 +16,12 @@ #include #include +#include #include #include "./fuzz_utils.h" #include "./nalloc.h" +#include "gtest/gtest.h" #include "imageio/imageio_util.h" #include "webp/decode.h" #include "webp/demux.h" @@ -79,3 +81,12 @@ End: FUZZ_TEST(AnimDecoder, AnimDecoderTest) .WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1)); + +TEST(AnimDecoder, Buganizer498967090) { + AnimDecoderTest(std::string( + "ALPH\000\000\000\000\000\000\000\000\003\000\000\000\014EBPVP8 " + "\030\000\000\0000\001\000\235\001*\002\000\001\000\003\0004%" + "\244\000\003~\000*\316\373\224\"AFM\"<0\334\"\231J\002`" + "\256\233\233\233\233\272\000\000", + 72)); +} diff --git a/tests/fuzzer/simple_api_fuzzer.cc b/tests/fuzzer/simple_api_fuzzer.cc index 053510da..e2e20856 100644 --- a/tests/fuzzer/simple_api_fuzzer.cc +++ b/tests/fuzzer/simple_api_fuzzer.cc @@ -17,9 +17,11 @@ #include #include #include +#include #include #include "./fuzz_utils.h" +#include "gtest/gtest.h" #include "webp/decode.h" #include "webp/types.h" @@ -101,3 +103,15 @@ void SimpleApiTest(std::string_view data_in) { FUZZ_TEST(SimpleApi, SimpleApiTest) .WithDomains(fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1)); + +TEST(SimpleApi, Buganizer498966511) { + SimpleApiTest( + std::string("ALPH\004\000\000\000A\377\377\377\377LP\010\000\000\000\000" + "\000\000\311H\006\000\000\000\"E\356PW\"ALPH\000\000\000\000" + "ALpH\004\000\000\000\004\010\000\200VP8 " + "T\000\000\000\266\003\000\235\001*" + "\001\000\002\000y\336n\366\001O\363\374\243\000\003LPS\"\002" + "iF\000FjRsa\232vP\"EO\"K\217OM;rOect\275n\"Wsection_JUNQ=" + "\"JUNQ\"\250YO,_I\362\021\"ANIM\"", + 150)); +}