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"
23namespace OHOS {
24using namespace OHOS::HDI::Display::Buffer::V1_1;
25using namespace OHOS::HDI::Display::Composer::V1_0;
26static std::shared_ptr<OHOS::HDI::Display::Buffer::V1_1::IDisplayBuffer> g_bufferInterface = nullptr;
27
28static bool g_isInit = false;
29static const uint8_t* g_data = nullptr;
30static size_t g_dataSize = 0;
31static size_t g_pos;
32static 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*/
37template<class T>
38T 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
53static 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
74BufferHandle* 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
93void TestRegisterBuffer(const BufferHandle& handle)
94{
95    (void)g_bufferInterface->RegisterBuffer(handle);
96}
97
98void 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
110void 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
117void TestListMetadataKeys(const BufferHandle& handle)
118{
119    std::vector<uint32_t> keys = {};
120    (void)g_bufferInterface->ListMetadataKeys(handle, keys);
121}
122
123void TestEraseMetadataKey(const BufferHandle& handle)
124{
125    uint16_t key = GetData<uint16_t>();
126    (void)g_bufferInterface->EraseMetadataKey(handle, key);
127}
128
129typedef void (*TestFuncs[])(const BufferHandle&);
130
131TestFuncs g_testFuncs = {
132    TestRegisterBuffer,
133    TestSetMetadata,
134    TestGetMetadata,
135    TestEraseMetadataKey,
136    TestListMetadataKeys
137};
138
139bool 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 */
179extern "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