1 /*
2 * Copyright (c) 2023 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 "metadata_fuzzer.h"
17
18 #include <cstddef>
19 #include <cstdint>
20 #include <securec.h>
21 #include "hdf_base.h"
22 #include "display_common_fuzzer.h"
23 namespace OHOS {
24 using namespace OHOS::HDI::Display::Buffer::V1_1;
25 using namespace OHOS::HDI::Display::Composer::V1_0;
26 static std::shared_ptr<OHOS::HDI::Display::Buffer::V1_1::IDisplayBuffer> g_bufferInterface = nullptr;
27
28 static bool g_isInit = false;
29 static const uint8_t* g_data = nullptr;
30 static size_t g_dataSize = 0;
31 static size_t g_pos;
32 static int32_t g_maxVectorLen = 2880; // max size of value vector
33 /*
34 * describe: get data from outside untrusted data(g_data) which size is according to sizeof(T)
35 * tips: only support basic type
36 */
37 template<class T>
GetData()38 T GetData()
39 {
40 T object {};
41 size_t objectSize = sizeof(object);
42 if (g_data == nullptr || objectSize > g_dataSize - g_pos) {
43 return object;
44 }
45 errno_t ret = memcpy_s(&object, objectSize, g_data + g_pos, objectSize);
46 if (ret != EOK) {
47 return {};
48 }
49 g_pos += objectSize;
50 return object;
51 }
52
GetAllocInfo(OHOS::HDI::Display::Buffer::V1_0::AllocInfo & info)53 static int32_t GetAllocInfo(OHOS::HDI::Display::Buffer::V1_0::AllocInfo& info)
54 {
55 uint32_t lenUsage = GetArrLength(CONVERT_TABLE_USAGE);
56 if (lenUsage == 0) {
57 HDF_LOGE("%{public}s: CONVERT_TABLE_USAGE length is equal to 0", __func__);
58 return DISPLAY_FAILURE;
59 }
60 uint32_t lenFormat = GetArrLength(CONVERT_TABLE_FORMAT);
61 if (lenFormat == 0) {
62 HDF_LOGE("%{public}s: CONVERT_TABLE_FORMAT length is equal to 0", __func__);
63 return DISPLAY_FAILURE;
64 }
65
66 info.width = GetData<uint32_t>() % WIDTH;
67 info.height = GetData<uint32_t>() % HEIGHT;
68 info.usage = CONVERT_TABLE_USAGE[GetData<uint32_t>() % lenUsage];
69 info.format = CONVERT_TABLE_FORMAT[GetData<uint32_t>() % lenFormat];
70 info.expectedSize = info.width * info.height;
71 return DISPLAY_SUCCESS;
72 }
73
UsingAllocmem()74 BufferHandle* UsingAllocmem()
75 {
76 AllocInfo info = { 0 };
77 int32_t ret = GetAllocInfo(info);
78 if (ret != DISPLAY_SUCCESS) {
79 HDF_LOGE("%{public}s: function GetAllocInfo failed", __func__);
80 return nullptr;
81 }
82
83 BufferHandle* handle = nullptr;
84 ret = g_bufferInterface->AllocMem(info, handle);
85 if (ret != DISPLAY_SUCCESS && handle != nullptr) {
86 HDF_LOGE("%{public}s: function AllocMem failed", __func__);
87 g_bufferInterface->FreeMem(*handle);
88 return nullptr;
89 }
90 return handle;
91 }
92
TestRegisterBuffer(const BufferHandle & handle)93 void TestRegisterBuffer(const BufferHandle& handle)
94 {
95 (void)g_bufferInterface->RegisterBuffer(handle);
96 }
97
TestSetMetadata(const BufferHandle & handle)98 void TestSetMetadata(const BufferHandle& handle)
99 {
100 uint16_t key = GetData<uint16_t>();
101 uint32_t len = GetData<uint32_t>() % g_maxVectorLen;
102 std::vector<uint8_t> values;
103 for (uint32_t i = 0; i < len; i++) {
104 values.push_back(GetData<uint8_t>() % ALPHA_VALUE_RANGE);
105 }
106
107 (void)g_bufferInterface->SetMetadata(handle, key, values);
108 }
109
TestGetMetadata(const BufferHandle & handle)110 void TestGetMetadata(const BufferHandle& handle)
111 {
112 uint16_t key = GetData<uint16_t>();
113 std::vector<uint8_t> values = {};
114 (void)g_bufferInterface->GetMetadata(handle, key, values);
115 }
116
TestListMetadataKeys(const BufferHandle & handle)117 void TestListMetadataKeys(const BufferHandle& handle)
118 {
119 std::vector<uint32_t> keys = {};
120 (void)g_bufferInterface->ListMetadataKeys(handle, keys);
121 }
122
TestEraseMetadataKey(const BufferHandle & handle)123 void TestEraseMetadataKey(const BufferHandle& handle)
124 {
125 uint16_t key = GetData<uint16_t>();
126 (void)g_bufferInterface->EraseMetadataKey(handle, key);
127 }
128
129 typedef void (*TestFuncs[])(const BufferHandle&);
130
131 TestFuncs g_testFuncs = {
132 TestRegisterBuffer,
133 TestSetMetadata,
134 TestGetMetadata,
135 TestEraseMetadataKey,
136 TestListMetadataKeys
137 };
138
FuzzTest(const uint8_t * rawData,size_t size)139 bool FuzzTest(const uint8_t* rawData, size_t size)
140 {
141 if (rawData == nullptr) {
142 return false;
143 }
144
145 if (!g_isInit) {
146 g_isInit = true;
147 g_bufferInterface.reset(OHOS::HDI::Display::Buffer::V1_1::IDisplayBuffer::Get());
148 if (g_bufferInterface == nullptr) {
149 HDF_LOGE("%{public}s: get IDisplayBuffer failed", __func__);
150 return false;
151 }
152 }
153
154 // initialize data
155 g_data = rawData;
156 g_dataSize = size;
157 g_pos = 0;
158 BufferHandle* buffer = UsingAllocmem();
159 if (buffer == nullptr) {
160 HDF_LOGE("%{public}s: function UsingAllocmem failed", __func__);
161 return false;
162 }
163
164 uint32_t code = GetData<uint32_t>();
165 uint32_t len = GetArrLength(g_testFuncs);
166 if (len == 0) {
167 HDF_LOGE("%{public}s: g_testFuncs length is equal to 0", __func__);
168 g_bufferInterface->FreeMem(*buffer);
169 return false;
170 }
171
172 g_testFuncs[code % len](*buffer);
173 g_bufferInterface->FreeMem(*buffer);
174 return true;
175 }
176 } // OHOS
177
178 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)179 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
180 {
181 if (size < OHOS::THRESHOLD) {
182 return 0;
183 }
184
185 OHOS::FuzzTest(data, size);
186 return 0;
187 }
188