mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Move more internal fuzzers to public.
Change-Id: Idde75f374264666e4c54a17b1606464ad5d00d9c
This commit is contained in:
		| @@ -482,6 +482,7 @@ if(WEBP_BUILD_ANIM_UTILS | |||||||
|    OR WEBP_BUILD_CWEBP |    OR WEBP_BUILD_CWEBP | ||||||
|    OR WEBP_BUILD_DWEBP |    OR WEBP_BUILD_DWEBP | ||||||
|    OR WEBP_BUILD_EXTRAS |    OR WEBP_BUILD_EXTRAS | ||||||
|  |    OR WEBP_BUILD_FUZZTEST | ||||||
|    OR WEBP_BUILD_GIF2WEBP |    OR WEBP_BUILD_GIF2WEBP | ||||||
|    OR WEBP_BUILD_IMG2WEBP |    OR WEBP_BUILD_IMG2WEBP | ||||||
|    OR WEBP_BUILD_VWEBP |    OR WEBP_BUILD_VWEBP | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ macro(add_webp_fuzztest TEST_NAME) | |||||||
|   add_executable(${TEST_NAME} ${TEST_NAME}.cc) |   add_executable(${TEST_NAME} ${TEST_NAME}.cc) | ||||||
|   # FuzzTest bundles GoogleTest so no need to link to gtest libraries. |   # FuzzTest bundles GoogleTest so no need to link to gtest libraries. | ||||||
|   target_link_libraries(${TEST_NAME} PRIVATE fuzz_utils webp ${ARGN}) |   target_link_libraries(${TEST_NAME} PRIVATE fuzz_utils webp ${ARGN}) | ||||||
|  |   target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src) | ||||||
|   link_fuzztest(${TEST_NAME}) |   link_fuzztest(${TEST_NAME}) | ||||||
|   add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) |   add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) | ||||||
|   set_property( |   set_property( | ||||||
| @@ -49,8 +50,11 @@ target_link_libraries(fuzz_utils PUBLIC webpdecoder) | |||||||
| link_fuzztest(fuzz_utils) | link_fuzztest(fuzz_utils) | ||||||
|  |  | ||||||
| add_webp_fuzztest(advanced_api_fuzzer) | add_webp_fuzztest(advanced_api_fuzzer) | ||||||
|  | add_webp_fuzztest(dec_fuzzer) | ||||||
| add_webp_fuzztest(enc_dec_fuzzer) | add_webp_fuzztest(enc_dec_fuzzer) | ||||||
|  | add_webp_fuzztest(enc_fuzzer imagedec) | ||||||
| add_webp_fuzztest(huffman_fuzzer) | add_webp_fuzztest(huffman_fuzzer) | ||||||
|  | add_webp_fuzztest(imageio_fuzzer imagedec tiff) | ||||||
| add_webp_fuzztest(simple_api_fuzzer) | add_webp_fuzztest(simple_api_fuzzer) | ||||||
|  |  | ||||||
| if(WEBP_BUILD_LIBWEBPMUX) | if(WEBP_BUILD_LIBWEBPMUX) | ||||||
| @@ -59,3 +63,7 @@ if(WEBP_BUILD_LIBWEBPMUX) | |||||||
|   add_webp_fuzztest(animencoder_fuzzer libwebpmux) |   add_webp_fuzztest(animencoder_fuzzer libwebpmux) | ||||||
|   add_webp_fuzztest(mux_demux_api_fuzzer libwebpmux webpdemux) |   add_webp_fuzztest(mux_demux_api_fuzzer libwebpmux webpdemux) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | if(WEBP_BUILD_WEBPINFO) | ||||||
|  |   add_webp_fuzztest(webp_info_fuzzer imageioutil) | ||||||
|  | endif() | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								tests/fuzzer/dec_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/fuzzer/dec_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // Copyright 2024 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 <cstdint> | ||||||
|  | #include <cstdio> | ||||||
|  | #include <string_view> | ||||||
|  |  | ||||||
|  | #include "src/webp/decode.h" | ||||||
|  | #include "tests/fuzzer/fuzz_utils.h" | ||||||
|  |  | ||||||
|  | namespace { | ||||||
|  |  | ||||||
|  | void DecodeWebP(std::string_view arbitrary_bytes) { | ||||||
|  |   WebPDecoderConfig decoder_config; | ||||||
|  |   if (!WebPInitDecoderConfig(&decoder_config)) { | ||||||
|  |     fprintf(stderr, "WebPInitDecoderConfig failed.\n"); | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |   const VP8StatusCode status = | ||||||
|  |       WebPDecode(reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()), | ||||||
|  |                  arbitrary_bytes.size(), &decoder_config); | ||||||
|  |   WebPFreeDecBuffer(&decoder_config.output); | ||||||
|  |   // The decoding may fail (because the fuzzed input can be anything) but not | ||||||
|  |   // for these reasons. | ||||||
|  |   if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_USER_ABORT) { | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | FUZZ_TEST(WebPSuite, DecodeWebP) | ||||||
|  |     .WithDomains( | ||||||
|  |         fuzztest::String() | ||||||
|  |             .WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1)); | ||||||
|  |  | ||||||
|  | }  // namespace | ||||||
							
								
								
									
										140
									
								
								tests/fuzzer/enc_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								tests/fuzzer/enc_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | // Copyright 2024 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 <cstddef> | ||||||
|  | #include <cstdint> | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <iostream> | ||||||
|  | #include <string> | ||||||
|  | #include <string_view> | ||||||
|  |  | ||||||
|  | #include "imageio/image_dec.h" | ||||||
|  | #include "src/dsp/cpu.h" | ||||||
|  | #include "src/webp/decode.h" | ||||||
|  | #include "src/webp/encode.h" | ||||||
|  | #include "src/webp/types.h" | ||||||
|  | #include "tests/fuzzer/fuzz_utils.h" | ||||||
|  |  | ||||||
|  | namespace { | ||||||
|  |  | ||||||
|  | const VP8CPUInfo default_VP8GetCPUInfo = fuzz_utils::VP8GetCPUInfo; | ||||||
|  |  | ||||||
|  | void EncTest(std::string_view file, uint32_t optimization_index, bool use_argb, | ||||||
|  |              WebPConfig config, | ||||||
|  |              const fuzz_utils::CropOrScaleParams& crop_or_scale_params) { | ||||||
|  |   fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index); | ||||||
|  |  | ||||||
|  |   // Init the source picture. | ||||||
|  |   WebPPicture pic; | ||||||
|  |   if (!WebPPictureInit(&pic)) { | ||||||
|  |     std::cerr << "WebPPictureInit failed.\n"; | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |   pic.use_argb = use_argb; | ||||||
|  |  | ||||||
|  |   const uint8_t* const file_data = | ||||||
|  |       reinterpret_cast<const uint8_t*>(file.data()); | ||||||
|  |   if (fuzz_utils::IsImageTooBig(file_data, file.size())) return; | ||||||
|  |   WebPImageReader reader = WebPGuessImageReader(file_data, file.size()); | ||||||
|  |   if (!reader(file_data, file.size(), &pic, 1, NULL)) return; | ||||||
|  |  | ||||||
|  |   // Crop and scale. | ||||||
|  |   if (!CropOrScale(&pic, crop_or_scale_params)) { | ||||||
|  |     const WebPEncodingError error_code = pic.error_code; | ||||||
|  |     WebPPictureFree(&pic); | ||||||
|  |     if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return; | ||||||
|  |     std::cerr << "CropOrScale failed. Error code: " << error_code << "\n"; | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Skip the cruncher except on small images, it's likely to timeout. | ||||||
|  |   if (config.lossless && config.quality == 100. && config.method == 6 && | ||||||
|  |       pic.width * pic.height >= 16384) { | ||||||
|  |     config.lossless = 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Encode. | ||||||
|  |   WebPMemoryWriter memory_writer; | ||||||
|  |   WebPMemoryWriterInit(&memory_writer); | ||||||
|  |   pic.writer = WebPMemoryWrite; | ||||||
|  |   pic.custom_ptr = &memory_writer; | ||||||
|  |   if (!WebPEncode(&config, &pic)) { | ||||||
|  |     const WebPEncodingError error_code = pic.error_code; | ||||||
|  |     WebPMemoryWriterClear(&memory_writer); | ||||||
|  |     WebPPictureFree(&pic); | ||||||
|  |     if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return; | ||||||
|  |     std::cerr << "WebPEncode failed. Error code: " << error_code | ||||||
|  |               << " \nFile starts with: " << file.substr(0, 20) << "\n"; | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Try decoding the result. | ||||||
|  |   int w, h; | ||||||
|  |   const uint8_t* const out_data = memory_writer.mem; | ||||||
|  |   const size_t out_size = memory_writer.size; | ||||||
|  |   uint8_t* const rgba = WebPDecodeBGRA(out_data, out_size, &w, &h); | ||||||
|  |   if (rgba == nullptr || w != pic.width || h != pic.height) { | ||||||
|  |     std::cerr << "WebPDecodeBGRA failed.\nFile starts with: " | ||||||
|  |               << file.substr(0, 20) << "\n"; | ||||||
|  |     WebPFree(rgba); | ||||||
|  |     WebPMemoryWriterClear(&memory_writer); | ||||||
|  |     WebPPictureFree(&pic); | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Compare the results if exact encoding. | ||||||
|  |   if (pic.use_argb && config.lossless && config.near_lossless == 100) { | ||||||
|  |     const uint32_t* src1 = (const uint32_t*)rgba; | ||||||
|  |     const uint32_t* src2 = pic.argb; | ||||||
|  |     for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) { | ||||||
|  |       for (int x = 0; x < w; ++x) { | ||||||
|  |         uint32_t v1 = src1[x], v2 = src2[x]; | ||||||
|  |         if (!config.exact) { | ||||||
|  |           if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) { | ||||||
|  |             // Only keep alpha for comparison of fully transparent area. | ||||||
|  |             v1 &= 0xff000000u; | ||||||
|  |             v2 &= 0xff000000u; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         if (v1 != v2) { | ||||||
|  |           std::cerr | ||||||
|  |               << "Lossless compression failed pixel-exactness.\nFile starts " | ||||||
|  |                  "with: " | ||||||
|  |               << file.substr(0, 20) << "\n"; | ||||||
|  |           WebPFree(rgba); | ||||||
|  |           WebPMemoryWriterClear(&memory_writer); | ||||||
|  |           WebPPictureFree(&pic); | ||||||
|  |           abort(); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   WebPFree(rgba); | ||||||
|  |   WebPMemoryWriterClear(&memory_writer); | ||||||
|  |   WebPPictureFree(&pic); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace | ||||||
|  |  | ||||||
|  | FUZZ_TEST(Enc, EncTest) | ||||||
|  |     .WithDomains( | ||||||
|  |         fuzztest::Arbitrary<std::string>(), | ||||||
|  |         /*optimization_index=*/ | ||||||
|  |         fuzztest::InRange<uint32_t>(0, fuzz_utils::kMaxOptimizationIndex), | ||||||
|  |         /*use_argb=*/fuzztest::Arbitrary<bool>(), | ||||||
|  |         fuzz_utils::ArbitraryWebPConfig(), | ||||||
|  |         fuzz_utils::ArbitraryCropOrScaleParams()); | ||||||
							
								
								
									
										81
									
								
								tests/fuzzer/imageio_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								tests/fuzzer/imageio_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | // Copyright 2024 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. | ||||||
|  | // | ||||||
|  | //////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | // Fuzzing of libwebp's image readers | ||||||
|  |  | ||||||
|  | #include <cstddef> | ||||||
|  | #include <cstdint> | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <iostream> | ||||||
|  | #include <tiffio.h> | ||||||
|  |  | ||||||
|  | #include "imageio/image_dec.h" | ||||||
|  | #include "imageio/metadata.h" | ||||||
|  | #include "src/webp/encode.h" | ||||||
|  | #include "tests/fuzzer/fuzz_utils.h" | ||||||
|  |  | ||||||
|  | namespace { | ||||||
|  |  | ||||||
|  | void TestReader(const uint8_t *data, size_t size, WebPImageReader reader, | ||||||
|  |                 bool keep_alpha, bool use_argb) { | ||||||
|  |   WebPPicture pic; | ||||||
|  |   if (!WebPPictureInit(&pic)) { | ||||||
|  |     std::cerr << "WebPPictureInit failed" << std::endl; | ||||||
|  |     abort(); | ||||||
|  |   } | ||||||
|  |   Metadata metadata; | ||||||
|  |   MetadataInit(&metadata); | ||||||
|  |   pic.use_argb = use_argb ? 1 : 0; | ||||||
|  |  | ||||||
|  |   if (!fuzz_utils::IsImageTooBig(data, size)) { | ||||||
|  |     (void)(*reader)(data, size, &pic, keep_alpha ? 1 : 0, &metadata); | ||||||
|  |   } | ||||||
|  |   WebPPictureFree(&pic); | ||||||
|  |   MetadataFree(&metadata); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | constexpr WebPInputFileFormat kUnknown = WEBP_UNSUPPORTED_FORMAT; | ||||||
|  |  | ||||||
|  | void Decode(std::string_view arbitrary_bytes, WebPInputFileFormat format, | ||||||
|  |             bool keep_alpha, bool use_argb) { | ||||||
|  |   if (format == kUnknown || format == WEBP_TIFF_FORMAT) { | ||||||
|  |     TIFFSetErrorHandler(NULL);    // libtiff can be verbose about errors. | ||||||
|  |     TIFFSetWarningHandler(NULL);  // Silence it to avoid timeouts. | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const uint8_t *data = | ||||||
|  |       reinterpret_cast<const uint8_t *>(arbitrary_bytes.data()); | ||||||
|  |   const size_t size = arbitrary_bytes.size(); | ||||||
|  |   if (format == kUnknown) { | ||||||
|  |     (void)WebPGuessImageType(data, size);  // shouldn't fail | ||||||
|  |     TestReader(data, size, WebPGuessImageReader(data, size), keep_alpha, | ||||||
|  |                use_argb); | ||||||
|  |   } else { | ||||||
|  |     TestReader(data, size, WebPGetImageReader(format), keep_alpha, use_argb); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | FUZZ_TEST(ImageIOSuite, Decode) | ||||||
|  |     .WithDomains( | ||||||
|  |         fuzztest::String() | ||||||
|  |             .WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1), | ||||||
|  |         fuzztest::ElementOf<WebPInputFileFormat>( | ||||||
|  |             {WEBP_PNG_FORMAT, WEBP_JPEG_FORMAT, WEBP_TIFF_FORMAT, | ||||||
|  |              WEBP_WEBP_FORMAT, WEBP_PNM_FORMAT, kUnknown}), | ||||||
|  |         /*keep_alpha=*/fuzztest::Arbitrary<bool>(), | ||||||
|  |         /*use_argb=*/fuzztest::Arbitrary<bool>()); | ||||||
|  |  | ||||||
|  | }  // namespace | ||||||
							
								
								
									
										42
									
								
								tests/fuzzer/webp_info_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								tests/fuzzer/webp_info_fuzzer.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | // Copyright 2024 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 <cstdint> | ||||||
|  |  | ||||||
|  | #include "src/webp/mux_types.h" | ||||||
|  | #include "tests/fuzzer/fuzz_utils.h" | ||||||
|  |  | ||||||
|  | // Don't do that at home! | ||||||
|  | #define main exec_main | ||||||
|  | #include "examples/webpinfo.c" | ||||||
|  | #undef main | ||||||
|  |  | ||||||
|  | void WebPInfoTest(std::string_view data) { | ||||||
|  |   WebPInfo webp_info; | ||||||
|  |   WebPInfoInit(&webp_info); | ||||||
|  |   webp_info.quiet_ = 1; | ||||||
|  |   webp_info.show_summary_ = 0; | ||||||
|  |   webp_info.show_diagnosis_ = 0; | ||||||
|  |   webp_info.parse_bitstream_ = 1; | ||||||
|  |   WebPData webp_data = {reinterpret_cast<const uint8_t *>(data.data()), | ||||||
|  |                         data.size()}; | ||||||
|  |   AnalyzeWebP(&webp_info, &webp_data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | FUZZ_TEST(WebPInfo, WebPInfoTest) | ||||||
|  |     .WithDomains( | ||||||
|  |         fuzztest::String() | ||||||
|  |             .WithMaxSize(fuzz_utils::kMaxWebPFileSize + 1)); | ||||||
		Reference in New Issue
	
	Block a user