1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <hdf_log.h>
17 #include <image_auto_initer.h>
18 #include <securec.h>
19 #include <vector>
20 #include "ashmem.h"
21 #include "v2_1/icodec_image.h"
22 #include "v1_2/display_composer_type.h"
23 #include "v1_2/display_buffer_type.h"
24 #include "v1_2/include/idisplay_buffer.h"
25 #include "imagedoheifdecode_fuzzer.h"
26
27 using namespace OHOS::HDI::Codec::Image::V2_1;
28 using namespace OHOS::HDI::Display::Buffer::V1_2;
29 using namespace OHOS::HDI::Display::Composer::V1_2;
30 using namespace OHOS;
31 using namespace std;
32 namespace OHOS {
33 namespace Codec {
34 namespace Image {
35
Convert2Uint32(const uint8_t * ptr)36 static uint32_t Convert2Uint32(const uint8_t *ptr)
37 {
38 if (ptr == nullptr) {
39 return 0;
40 }
41 return (ptr[0] << 24) | (ptr[1] << 16) | // 24:bit offset, 16: bit offset, 1:byte offset
42 (ptr[2] << 8) | (ptr[3]); // 8:bit offset, 2: byte offset, 3:byte offset
43 }
44
GetAshmem(const char * name,int32_t size)45 static sptr<Ashmem> GetAshmem(const char *name, int32_t size)
46 {
47 auto ashmem = Ashmem::CreateAshmem(name, size);
48 if (ashmem == nullptr) {
49 HDF_LOGE("%{public}s: ashmem init failed\n", __func__);
50 return ashmem;
51 }
52 if (!ashmem->MapReadAndWriteAshmem()) {
53 HDF_LOGE("%{public}s: ashmem map failed\n", __func__);
54 return ashmem;
55 }
56 return ashmem;
57 }
58
CloseAshmem(sptr<Ashmem> ashmem)59 static void CloseAshmem(sptr<Ashmem> ashmem)
60 {
61 if (ashmem != nullptr) {
62 ashmem->UnmapAshmem();
63 ashmem->CloseAshmem();
64 }
65 }
66
CreateAshmem(const CodecHeifDecInfo & decInfo,std::vector<sptr<Ashmem>> & inputs,uint8_t * data,size_t size)67 static bool CreateAshmem(const CodecHeifDecInfo &decInfo, std::vector<sptr<Ashmem>> &inputs, uint8_t *data, size_t size)
68 {
69 static constexpr uint32_t XPS_CNT = 1;
70 uint32_t gridCnt = decInfo.gridInfo.enableGrid ? (decInfo.gridInfo.rows * decInfo.gridInfo.cols) : 1;
71 uint32_t inputSize = XPS_CNT + gridCnt;
72 for (uint32_t i = 0; i < inputSize; i++) {
73 int32_t asmSize = 4;
74 sptr<OHOS::Ashmem> asmptr = GetAshmem("fuzz_ashmem", asmSize);
75 if (asmptr == nullptr) {
76 return false;
77 }
78 int32_t len = (size > asmSize) ? asmSize : size;
79 if (!asmptr->WriteToAshmem(data, len, 0)) {
80 CloseAshmem(asmptr);
81 HDF_LOGE("%{public}s: writing ashmem failed\n", __func__);
82 return false;
83 }
84
85 inputs.push_back(asmptr);
86 }
87 return true;
88 }
89
CreateNativeBuffer(sptr<NativeBuffer> & output,const CodecHeifDecInfo & decInfo)90 static bool CreateNativeBuffer(sptr<NativeBuffer> &output, const CodecHeifDecInfo &decInfo)
91 {
92 OHOS::HDI::Display::Buffer::V1_2::IDisplayBuffer *bufferMgr =
93 OHOS::HDI::Display::Buffer::V1_2::IDisplayBuffer::Get();
94 uint64_t usage = OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_READ |
95 OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_WRITE |
96 OHOS::HDI::Display::Composer::V1_2::HBM_USE_MEM_DMA;
97 AllocInfo alloc = {.width = decInfo.gridInfo.displayWidth,
98 .height = decInfo.gridInfo.displayHeight,
99 .usage = usage,
100 .format = OHOS::HDI::Display::Composer::V1_2::PIXEL_FMT_YCBCR_420_SP};
101 BufferHandle *handle = nullptr;
102 int32_t ret = bufferMgr->AllocMem(alloc, handle);
103 if (ret != HDF_SUCCESS) {
104 return false;
105 }
106 output = new NativeBuffer();
107 output->SetBufferHandle(handle, true);
108 return true;
109 }
110
GetUInt32AndMove(uint8_t * data,uint8_t * & currentPos,size_t size)111 static uint32_t GetUInt32AndMove(uint8_t *data, uint8_t *¤tPos, size_t size)
112 {
113 uint32_t value = Convert2Uint32(currentPos);
114 if ((currentPos + sizeof(uint32_t) + sizeof(uint32_t)) > (data + size)) {
115 currentPos = data;
116 } else {
117 currentPos += sizeof(uint32_t);
118 }
119 return value;
120 }
121
FillHeifDecInfo(CodecHeifDecInfo & decInfo,uint8_t * data,size_t size)122 static bool FillHeifDecInfo(CodecHeifDecInfo &decInfo, uint8_t *data, size_t size)
123 {
124 if (data == nullptr || size < sizeof(uint32_t)) {
125 return false;
126 }
127 constexpr uint32_t SIZE_FACTOR = 8192;
128 constexpr uint32_t ROW_COL_FACTOR = 1024;
129 constexpr uint32_t SAMPLE_FACTOR = 20;
130 constexpr uint8_t EVEN_FACTOR = 2;
131 uint8_t *currentPos = data;
132 decInfo.gridInfo.displayWidth = GetUInt32AndMove(data, currentPos, size) % SIZE_FACTOR;
133 decInfo.gridInfo.displayHeight = GetUInt32AndMove(data, currentPos, size) % SIZE_FACTOR;
134 decInfo.gridInfo.enableGrid = *currentPos % EVEN_FACTOR;
135 decInfo.gridInfo.tileWidth = GetUInt32AndMove(data, currentPos, size) % SIZE_FACTOR;
136 decInfo.gridInfo.tileHeight = GetUInt32AndMove(data, currentPos, size) % SIZE_FACTOR;
137 decInfo.gridInfo.cols = GetUInt32AndMove(data, currentPos, size) % ROW_COL_FACTOR;
138 decInfo.gridInfo.rows = GetUInt32AndMove(data, currentPos, size) % ROW_COL_FACTOR;
139 decInfo.sampleSize = GetUInt32AndMove(data, currentPos, size) % SAMPLE_FACTOR;
140
141 return true;
142 }
143
DoHeifDecode(const uint8_t * data,size_t size)144 bool DoHeifDecode(const uint8_t *data, size_t size)
145 {
146 if (data == nullptr || size < sizeof(unsigned int)) {
147 return false;
148 }
149
150 sptr<ICodecImage> image = ICodecImage::Get(false);
151 if (image == nullptr) {
152 HDF_LOGE("%{public}s: get ICodecImage failed\n", __func__);
153 return false;
154 }
155 CodecImageRole role = CodecImageRole(*data);
156 ImageAutoIniter autoIniter(image, role);
157
158 uint8_t *rawData = const_cast<uint8_t *>(data);
159
160 CodecHeifDecInfo decInfo;
161 if (!FillHeifDecInfo(decInfo, rawData, size)) {
162 return false;
163 }
164
165 std::vector<sptr<Ashmem>> inputs;
166 CreateAshmem(decInfo, inputs, rawData, size);
167 sptr<NativeBuffer> output = nullptr;
168 CreateNativeBuffer(output, decInfo);
169
170 auto err = image->DoHeifDecode(inputs, output, decInfo);
171 if (err != HDF_SUCCESS) {
172 HDF_LOGE("%{public}s: DoHeifDecode return %{public}d", __func__, err);
173 }
174 for (auto &input : inputs) {
175 CloseAshmem(input);
176 }
177
178 return true;
179 }
180 } // namespace Image
181 } // namespace Codec
182 } // namespace OHOS
183
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)184 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
185 {
186 OHOS::Codec::Image::DoHeifDecode(data, size);
187 return 0;
188 }
189