diff options
author | 2024-08-02 19:25:17 +0000 | |
---|---|---|
committer | 2024-08-02 19:25:17 +0000 | |
commit | e3ec4b6073e2fb34bc89d61fb47126af5ff5689f (patch) | |
tree | 65f9ff19edf31fdf530e6b97cb8376609c4faca2 | |
parent | 24123b5755b4c3df13bdd57755c9c26f75a658ea (diff) | |
parent | 27e2797220c9982f8db4768410ff7b5b820bff11 (diff) |
Merge "Add imagedecoder_heif_fuzzer" into main
-rw-r--r-- | native/graphics/jni/Android.bp | 27 | ||||
-rw-r--r-- | native/graphics/jni/fuzz/fuzz_imagedecoder.cpp | 65 |
2 files changed, 92 insertions, 0 deletions
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index 8f16f762f7ef..0fb3049f63d8 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -127,3 +127,30 @@ cc_fuzz { "-DPNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR", ], } + +cc_fuzz { + name: "imagedecoder_heif_fuzzer", + defaults: ["imagedecoder_fuzzer_defaults"], + team: "trendy_team_android_core_graphics_stack", + shared_libs: [ + "libfakeservicemanager", + ], + target: { + android: { + shared_libs: [ + "libmediaplayerservice", + "libmediaextractorservice", + ], + }, + host: { + static_libs: [ + "libbinder_random_parcel", + "libcutils", + ], + }, + }, + include_dirs: ["frameworks/av/services/mediaextractor"], + cflags: [ + "-DFUZZ_HEIF_FORMAT", + ], +} diff --git a/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp b/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp index 6743997fb152..f739e4a1d1a2 100644 --- a/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp +++ b/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp @@ -18,6 +18,16 @@ #include <binder/IPCThreadState.h> #include <fuzzer/FuzzedDataProvider.h> +#ifdef FUZZ_HEIF_FORMAT +#include <fakeservicemanager/FakeServiceManager.h> +#ifdef __ANDROID__ +#include <MediaExtractorService.h> +#include <MediaPlayerService.h> +#else +#include <fuzzbinder/random_binder.h> +#endif //__ANDROID__ +#endif // FUZZ_HEIF_FORMAT + #ifdef PNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR #include <fuzz/png_mutator.h> #endif @@ -31,8 +41,42 @@ struct PixelFreer { using PixelPointer = std::unique_ptr<void, PixelFreer>; +#ifndef FUZZ_HEIF_FORMAT +#define FOURCC(c1, c2, c3, c4) ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4)) +/** Reverse all 4 bytes in a 32bit value. + e.g. 0x12345678 -> 0x78563412 +*/ +static uint32_t endianSwap32(uint32_t value) { + return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | + (value >> 24); +} + +static bool isFtyp(const uint8_t* data, size_t size) { + constexpr int32_t headerSize = 8; + constexpr int32_t chunkTypeOffset = 4; + constexpr int32_t ftypFourCCVal = FOURCC('f', 't', 'y', 'p'); + if (size >= headerSize) { + const uint32_t* chunk = reinterpret_cast<const uint32_t*>(data + chunkTypeOffset); + if (endianSwap32(*chunk) == ftypFourCCVal) { + return true; + } + } + return false; +} +#endif + AImageDecoder* init(const uint8_t* data, size_t size, bool useFileDescriptor) { AImageDecoder* decoder = nullptr; +#ifndef FUZZ_HEIF_FORMAT + if (isFtyp(data, size)) { + /* We want to ignore HEIF data when fuzzing non-HEIF image decoders. Use 'FTYP' + * as a signal to ignore, though note that this excludes more than just HEIF. + * But when this code was added, `AImageDecoder` did not support any formats + * in 'FTYP' besides HEIF. + */ + return nullptr; + } +#endif // FUZZ_HEIF_FORMAT if (useFileDescriptor) { constexpr char testFd[] = "tempFd"; int32_t fileDesc = open(testFd, O_RDWR | O_CREAT | O_TRUNC); @@ -47,6 +91,27 @@ AImageDecoder* init(const uint8_t* data, size_t size, bool useFileDescriptor) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider dataProvider = FuzzedDataProvider(data, size); +#ifdef FUZZ_HEIF_FORMAT + /** + * For image formats like HEIF, a new metadata object is + * created which requires "media.player" service running + */ + static std::once_flag callOnceHEIF; + std::call_once(callOnceHEIF, [&]() { + android::sp<android::IServiceManager> fakeServiceManager = + new android::FakeServiceManager(); + setDefaultServiceManager(fakeServiceManager); +#ifdef __ANDROID__ + android::MediaPlayerService::instantiate(); + android::MediaExtractorService::instantiate(); +#else + auto binderExtractor = android::getRandomBinder(&dataProvider); + auto binderPlayer = android::getRandomBinder(&dataProvider); + fakeServiceManager->addService(android::String16("media.extractor"), binderExtractor); + fakeServiceManager->addService(android::String16("media.player"), binderPlayer); +#endif //__ANDROID__ + }); +#endif // FUZZ_HEIF_FORMAT /** * Use maximum of 80% of buffer for creating decoder and save at least * 20% buffer for fuzzing other APIs |