• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *&currentPos, 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