xref: /aosp_15_r20/frameworks/base/native/graphics/jni/fuzz/fuzz_imagedecoder.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <android/imagedecoder.h>
18 #include <binder/IPCThreadState.h>
19 #include <fuzzer/FuzzedDataProvider.h>
20 
21 #ifdef FUZZ_HEIF_FORMAT
22 #include <fakeservicemanager/FakeServiceManager.h>
23 #ifdef __ANDROID__
24 #include <MediaExtractorService.h>
25 #include <MediaPlayerService.h>
26 #else
27 #include <fuzzbinder/random_binder.h>
28 #endif //__ANDROID__
29 #endif // FUZZ_HEIF_FORMAT
30 
31 #ifdef PNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR
32 #include <fuzz/png_mutator.h>
33 #endif
34 
35 constexpr int32_t kMaxDimension = 5000;
36 constexpr int32_t kMinDimension = 0;
37 
38 struct PixelFreer {
operator ()PixelFreer39     void operator()(void* pixels) const { std::free(pixels); }
40 };
41 
42 using PixelPointer = std::unique_ptr<void, PixelFreer>;
43 
44 #ifndef FUZZ_HEIF_FORMAT
45 #define FOURCC(c1, c2, c3, c4) ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
46 /** Reverse all 4 bytes in a 32bit value.
47     e.g. 0x12345678 -> 0x78563412
48 */
endianSwap32(uint32_t value)49 static uint32_t endianSwap32(uint32_t value) {
50     return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) |
51             (value >> 24);
52 }
53 
isFtyp(const uint8_t * data,size_t size)54 static bool isFtyp(const uint8_t* data, size_t size) {
55     constexpr int32_t headerSize = 8;
56     constexpr int32_t chunkTypeOffset = 4;
57     constexpr int32_t ftypFourCCVal = FOURCC('f', 't', 'y', 'p');
58     if (size >= headerSize) {
59         const uint32_t* chunk = reinterpret_cast<const uint32_t*>(data + chunkTypeOffset);
60         if (endianSwap32(*chunk) == ftypFourCCVal) {
61             return true;
62         }
63     }
64     return false;
65 }
66 #endif
67 
init(const uint8_t * data,size_t size,bool useFileDescriptor)68 AImageDecoder* init(const uint8_t* data, size_t size, bool useFileDescriptor) {
69     AImageDecoder* decoder = nullptr;
70 #ifndef FUZZ_HEIF_FORMAT
71     if (isFtyp(data, size)) {
72         /* We want to ignore HEIF data when fuzzing non-HEIF image decoders. Use 'FTYP'
73          * as a signal to ignore, though note that this excludes more than just HEIF.
74          * But when this code was added, `AImageDecoder` did not support any formats
75          * in 'FTYP' besides HEIF.
76          */
77         return nullptr;
78     }
79 #endif // FUZZ_HEIF_FORMAT
80     if (useFileDescriptor) {
81         constexpr char testFd[] = "tempFd";
82         int32_t fileDesc = open(testFd, O_RDWR | O_CREAT | O_TRUNC);
83         write(fileDesc, data, size);
84         AImageDecoder_createFromFd(fileDesc, &decoder);
85         close(fileDesc);
86     } else {
87         AImageDecoder_createFromBuffer(data, size, &decoder);
88     }
89     return decoder;
90 }
91 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)92 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
93     FuzzedDataProvider dataProvider = FuzzedDataProvider(data, size);
94 #ifdef FUZZ_HEIF_FORMAT
95     /**
96      * For image formats like HEIF, a new metadata object is
97      * created which requires "media.player" service running
98      */
99     static std::once_flag callOnceHEIF;
100     std::call_once(callOnceHEIF, [&]() {
101         android::sp<android::IServiceManager> fakeServiceManager =
102                 new android::FakeServiceManager();
103         setDefaultServiceManager(fakeServiceManager);
104 #ifdef __ANDROID__
105         android::MediaPlayerService::instantiate();
106         android::MediaExtractorService::instantiate();
107 #else
108         auto binderExtractor = android::getRandomBinder(&dataProvider);
109         auto binderPlayer = android::getRandomBinder(&dataProvider);
110         fakeServiceManager->addService(android::String16("media.extractor"), binderExtractor);
111         fakeServiceManager->addService(android::String16("media.player"), binderPlayer);
112 #endif //__ANDROID__
113     });
114 #endif // FUZZ_HEIF_FORMAT
115     /**
116      * Use maximum of 80% of buffer for creating decoder and save at least
117      * 20% buffer for fuzzing other APIs
118      */
119     const int32_t dataSize = dataProvider.ConsumeIntegralInRange<int32_t>(0, (size * 80) / 100);
120     std::vector<uint8_t> inputBuffer = dataProvider.ConsumeBytes<uint8_t>(dataSize);
121     AImageDecoder* decoder =
122             init(inputBuffer.data(), inputBuffer.size(), dataProvider.ConsumeBool());
123     if (!decoder) {
124         return 0;
125     }
126     const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(decoder);
127     AImageDecoderFrameInfo* frameInfo = AImageDecoderFrameInfo_create();
128     int32_t height = AImageDecoderHeaderInfo_getHeight(headerInfo);
129     int32_t width = AImageDecoderHeaderInfo_getWidth(headerInfo);
130     while (dataProvider.remaining_bytes()) {
131         auto invokeImageApi = dataProvider.PickValueInArray<const std::function<void()>>({
132                 [&]() {
133                     int32_t testHeight =
134                             dataProvider.ConsumeIntegralInRange<int32_t>(kMinDimension,
135                                                                          kMaxDimension);
136                     int32_t testWidth = dataProvider.ConsumeIntegralInRange<int32_t>(kMinDimension,
137                                                                                      kMaxDimension);
138                     int32_t result = AImageDecoder_setTargetSize(decoder, testHeight, testWidth);
139                     if (result == ANDROID_IMAGE_DECODER_SUCCESS) {
140                         height = testHeight;
141                         width = testWidth;
142                     }
143                 },
144                 [&]() {
145                     const bool required = dataProvider.ConsumeBool();
146                     AImageDecoder_setUnpremultipliedRequired(decoder, required);
147                 },
148                 [&]() {
149                     AImageDecoder_setAndroidBitmapFormat(
150                             decoder,
151                             dataProvider.ConsumeIntegralInRange<
152                                     int32_t>(ANDROID_BITMAP_FORMAT_NONE,
153                                              ANDROID_BITMAP_FORMAT_RGBA_1010102) /* format */);
154                 },
155                 [&]() {
156                     AImageDecoder_setDataSpace(decoder,
157                                                dataProvider
158                                                        .ConsumeIntegral<int32_t>() /* dataspace */);
159                 },
160                 [&]() {
161                     ARect rect{dataProvider.ConsumeIntegral<int32_t>() /* left */,
162                                dataProvider.ConsumeIntegral<int32_t>() /* top */,
163                                dataProvider.ConsumeIntegral<int32_t>() /* right */,
164                                dataProvider.ConsumeIntegral<int32_t>() /* bottom */};
165                     AImageDecoder_setCrop(decoder, rect);
166                 },
167                 [&]() { AImageDecoderHeaderInfo_getWidth(headerInfo); },
168                 [&]() { AImageDecoderHeaderInfo_getMimeType(headerInfo); },
169                 [&]() { AImageDecoderHeaderInfo_getAlphaFlags(headerInfo); },
170                 [&]() { AImageDecoderHeaderInfo_getAndroidBitmapFormat(headerInfo); },
171                 [&]() {
172                     int32_t tempHeight;
173                     int32_t tempWidth;
174                     AImageDecoder_computeSampledSize(decoder,
175                                                      dataProvider.ConsumeIntegral<
176                                                              int>() /* sampleSize */,
177                                                      &tempWidth, &tempHeight);
178                 },
179                 [&]() { AImageDecoderHeaderInfo_getDataSpace(headerInfo); },
180                 [&]() { AImageDecoder_getRepeatCount(decoder); },
181                 [&]() { AImageDecoder_getFrameInfo(decoder, frameInfo); },
182                 [&]() { AImageDecoderFrameInfo_getDuration(frameInfo); },
183                 [&]() { AImageDecoderFrameInfo_hasAlphaWithinBounds(frameInfo); },
184                 [&]() { AImageDecoderFrameInfo_getDisposeOp(frameInfo); },
185                 [&]() { AImageDecoderFrameInfo_getBlendOp(frameInfo); },
186                 [&]() {
187                     AImageDecoder_setInternallyHandleDisposePrevious(
188                             decoder, dataProvider.ConsumeBool() /* handle */);
189                 },
190                 [&]() { AImageDecoder_rewind(decoder); },
191                 [&]() { AImageDecoder_advanceFrame(decoder); },
192                 [&]() {
193                     size_t stride = AImageDecoder_getMinimumStride(decoder);
194                     size_t pixelSize = height * stride;
195                     auto pixels = PixelPointer(std::malloc(pixelSize));
196                     if (!pixels.get()) {
197                         return;
198                     }
199                     AImageDecoder_decodeImage(decoder, pixels.get(), stride, pixelSize);
200                 },
201         });
202         invokeImageApi();
203     }
204 
205     AImageDecoderFrameInfo_delete(frameInfo);
206     AImageDecoder_delete(decoder);
207     return 0;
208 }
209