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