mirror of
https://github.com/webmproject/libwebp.git
synced 2026-04-09 14:22:31 +02:00
And fix a few bugs it already found. Bug: 497882857 Change-Id: I4af63d7e7fece0686dac931d54a5e855353aaa3a
146 lines
4.5 KiB
C++
146 lines
4.5 KiB
C++
// Copyright 2018 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string_view>
|
|
|
|
#include "./fuzz_utils.h"
|
|
#include "webp/demux.h"
|
|
#include "webp/mux.h"
|
|
#include "webp/mux_types.h"
|
|
|
|
namespace {
|
|
|
|
void MuxDemuxApiTest(std::string_view data_in, bool use_mux_api,
|
|
const std::array<int, 10>& chunk_flags) {
|
|
const size_t size = data_in.size();
|
|
WebPData webp_data;
|
|
WebPDataInit(&webp_data);
|
|
webp_data.size = size;
|
|
webp_data.bytes = reinterpret_cast<const uint8_t*>(data_in.data());
|
|
|
|
// Extracted chunks and frames are not processed or decoded,
|
|
// which is already covered extensively by the other fuzz targets.
|
|
|
|
if (use_mux_api) {
|
|
// Mux API
|
|
WebPMux* mux = WebPMuxCreate(&webp_data, size & 2);
|
|
if (!mux) return;
|
|
|
|
WebPData chunk;
|
|
(void)WebPMuxGetChunk(mux, "EXIF", &chunk);
|
|
(void)WebPMuxGetChunk(mux, "ICCP", &chunk);
|
|
(void)WebPMuxGetChunk(mux, "FUZZ", &chunk); // unknown
|
|
|
|
uint32_t flags;
|
|
(void)WebPMuxGetFeatures(mux, &flags);
|
|
|
|
int width = 0, height = 0;
|
|
(void)WebPMuxGetCanvasSize(mux, &width, &height);
|
|
|
|
WebPMuxAnimParams params;
|
|
(void)WebPMuxGetAnimationParams(mux, ¶ms);
|
|
|
|
WebPMuxError status;
|
|
WebPMuxFrameInfo info;
|
|
for (int i = 0; i < fuzz_utils::kFuzzFrameLimit; i++) {
|
|
status = WebPMuxGetFrame(mux, i + 1, &info);
|
|
if (status == WEBP_MUX_NOT_FOUND) {
|
|
break;
|
|
} else if (status == WEBP_MUX_OK) {
|
|
WebPDataClear(&info.bitstream);
|
|
}
|
|
}
|
|
|
|
// Try setting a custom chunk.
|
|
if (size > 20) {
|
|
WebPData custom_chunk;
|
|
custom_chunk.bytes = reinterpret_cast<const uint8_t*>(data_in.data()) + 4;
|
|
custom_chunk.size = size - 4;
|
|
int chunk_idx = 0;
|
|
for (std::string_view fourcc : {"VP8X", "ICCP", "ANIM", "EXIF", "XMP ",
|
|
"ANMF", "ALPH", "VP8 ", "VP8L", "FUZZ"}) {
|
|
// The last five image chunks should return WEBP_MUX_INVALID_ARGUMENT.
|
|
for (int i = 0; i < chunk_flags[chunk_idx]; i++) {
|
|
(void)WebPMuxSetChunk(mux, fourcc.data(), &custom_chunk, 0);
|
|
}
|
|
chunk_idx++;
|
|
}
|
|
}
|
|
|
|
// Try assembling the mux
|
|
WebPData assembled;
|
|
WebPDataInit(&assembled);
|
|
(void)WebPMuxAssemble(mux, &assembled);
|
|
WebPDataClear(&assembled);
|
|
|
|
// Get number of chunks of various types
|
|
for (int chunk_type = WEBP_CHUNK_VP8X; chunk_type <= WEBP_CHUNK_NIL;
|
|
++chunk_type) {
|
|
int num_chunks = 0;
|
|
(void)WebPMuxNumChunks(mux, static_cast<WebPChunkId>(chunk_type),
|
|
&num_chunks);
|
|
}
|
|
|
|
WebPMuxDelete(mux);
|
|
} else {
|
|
// Demux API
|
|
WebPDemuxer* demux;
|
|
if (size & 2) {
|
|
WebPDemuxState state;
|
|
demux = WebPDemuxPartial(&webp_data, &state);
|
|
if (state < WEBP_DEMUX_PARSED_HEADER) {
|
|
WebPDemuxDelete(demux);
|
|
return;
|
|
}
|
|
} else {
|
|
demux = WebPDemux(&webp_data);
|
|
if (!demux) return;
|
|
}
|
|
|
|
WebPChunkIterator chunk_iter;
|
|
if (WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) {
|
|
(void)WebPDemuxNextChunk(&chunk_iter);
|
|
}
|
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
|
if (WebPDemuxGetChunk(demux, "ICCP", 0, &chunk_iter)) { // 0 == last
|
|
(void)WebPDemuxPrevChunk(&chunk_iter);
|
|
}
|
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
|
// Skips FUZZ because the Demux API has no concept of (un)known chunks.
|
|
|
|
WebPIterator iter;
|
|
if (WebPDemuxGetFrame(demux, 1, &iter)) {
|
|
for (int i = 1; i < fuzz_utils::kFuzzFrameLimit; i++) {
|
|
if (!WebPDemuxNextFrame(&iter)) break;
|
|
}
|
|
}
|
|
|
|
WebPDemuxReleaseIterator(&iter);
|
|
WebPDemuxDelete(demux);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
FUZZ_TEST(MuxDemuxApi, MuxDemuxApiTest)
|
|
.WithDomains(
|
|
fuzztest::String().WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1),
|
|
/*mux=*/fuzztest::Arbitrary<bool>(),
|
|
/*chunk_flags=*/fuzztest::ArrayOf<10>(fuzztest::InRange(0, 2)));
|