1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "metadata_fuzzer.h"
17094332d3Sopenharmony_ci
18094332d3Sopenharmony_ci#include <cstddef>
19094332d3Sopenharmony_ci#include <cstdint>
20094332d3Sopenharmony_ci#include <securec.h>
21094332d3Sopenharmony_ci#include "hdf_base.h"
22094332d3Sopenharmony_ci#include "display_common_fuzzer.h"
23094332d3Sopenharmony_cinamespace OHOS {
24094332d3Sopenharmony_ciusing namespace OHOS::HDI::Display::Buffer::V1_1;
25094332d3Sopenharmony_ciusing namespace OHOS::HDI::Display::Composer::V1_0;
26094332d3Sopenharmony_cistatic std::shared_ptr<OHOS::HDI::Display::Buffer::V1_1::IDisplayBuffer> g_bufferInterface = nullptr;
27094332d3Sopenharmony_ci
28094332d3Sopenharmony_cistatic bool g_isInit = false;
29094332d3Sopenharmony_cistatic const uint8_t* g_data = nullptr;
30094332d3Sopenharmony_cistatic size_t g_dataSize = 0;
31094332d3Sopenharmony_cistatic size_t g_pos;
32094332d3Sopenharmony_cistatic int32_t g_maxVectorLen = 2880;     // max size of value vector
33094332d3Sopenharmony_ci/*
34094332d3Sopenharmony_ci* describe: get data from outside untrusted data(g_data) which size is according to sizeof(T)
35094332d3Sopenharmony_ci* tips: only support basic type
36094332d3Sopenharmony_ci*/
37094332d3Sopenharmony_citemplate<class T>
38094332d3Sopenharmony_ciT GetData()
39094332d3Sopenharmony_ci{
40094332d3Sopenharmony_ci    T object {};
41094332d3Sopenharmony_ci    size_t objectSize = sizeof(object);
42094332d3Sopenharmony_ci    if (g_data == nullptr || objectSize > g_dataSize - g_pos) {
43094332d3Sopenharmony_ci        return object;
44094332d3Sopenharmony_ci    }
45094332d3Sopenharmony_ci    errno_t ret = memcpy_s(&object, objectSize, g_data + g_pos, objectSize);
46094332d3Sopenharmony_ci    if (ret != EOK) {
47094332d3Sopenharmony_ci        return {};
48094332d3Sopenharmony_ci    }
49094332d3Sopenharmony_ci    g_pos += objectSize;
50094332d3Sopenharmony_ci    return object;
51094332d3Sopenharmony_ci}
52094332d3Sopenharmony_ci
53094332d3Sopenharmony_cistatic int32_t GetAllocInfo(OHOS::HDI::Display::Buffer::V1_0::AllocInfo& info)
54094332d3Sopenharmony_ci{
55094332d3Sopenharmony_ci    uint32_t lenUsage = GetArrLength(CONVERT_TABLE_USAGE);
56094332d3Sopenharmony_ci    if (lenUsage == 0) {
57094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: CONVERT_TABLE_USAGE length is equal to 0", __func__);
58094332d3Sopenharmony_ci        return DISPLAY_FAILURE;
59094332d3Sopenharmony_ci    }
60094332d3Sopenharmony_ci    uint32_t lenFormat = GetArrLength(CONVERT_TABLE_FORMAT);
61094332d3Sopenharmony_ci    if (lenFormat == 0) {
62094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: CONVERT_TABLE_FORMAT length is equal to 0", __func__);
63094332d3Sopenharmony_ci        return DISPLAY_FAILURE;
64094332d3Sopenharmony_ci    }
65094332d3Sopenharmony_ci
66094332d3Sopenharmony_ci    info.width = GetData<uint32_t>() % WIDTH;
67094332d3Sopenharmony_ci    info.height = GetData<uint32_t>() % HEIGHT;
68094332d3Sopenharmony_ci    info.usage = CONVERT_TABLE_USAGE[GetData<uint32_t>() % lenUsage];
69094332d3Sopenharmony_ci    info.format = CONVERT_TABLE_FORMAT[GetData<uint32_t>() % lenFormat];
70094332d3Sopenharmony_ci    info.expectedSize = info.width * info.height;
71094332d3Sopenharmony_ci    return DISPLAY_SUCCESS;
72094332d3Sopenharmony_ci}
73094332d3Sopenharmony_ci
74094332d3Sopenharmony_ciBufferHandle* UsingAllocmem()
75094332d3Sopenharmony_ci{
76094332d3Sopenharmony_ci    AllocInfo info = { 0 };
77094332d3Sopenharmony_ci    int32_t ret = GetAllocInfo(info);
78094332d3Sopenharmony_ci    if (ret != DISPLAY_SUCCESS) {
79094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: function GetAllocInfo failed", __func__);
80094332d3Sopenharmony_ci        return nullptr;
81094332d3Sopenharmony_ci    }
82094332d3Sopenharmony_ci
83094332d3Sopenharmony_ci    BufferHandle* handle = nullptr;
84094332d3Sopenharmony_ci    ret = g_bufferInterface->AllocMem(info, handle);
85094332d3Sopenharmony_ci    if (ret != DISPLAY_SUCCESS && handle != nullptr) {
86094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: function AllocMem failed", __func__);
87094332d3Sopenharmony_ci        g_bufferInterface->FreeMem(*handle);
88094332d3Sopenharmony_ci        return nullptr;
89094332d3Sopenharmony_ci    }
90094332d3Sopenharmony_ci    return handle;
91094332d3Sopenharmony_ci}
92094332d3Sopenharmony_ci
93094332d3Sopenharmony_civoid TestRegisterBuffer(const BufferHandle& handle)
94094332d3Sopenharmony_ci{
95094332d3Sopenharmony_ci    (void)g_bufferInterface->RegisterBuffer(handle);
96094332d3Sopenharmony_ci}
97094332d3Sopenharmony_ci
98094332d3Sopenharmony_civoid TestSetMetadata(const BufferHandle& handle)
99094332d3Sopenharmony_ci{
100094332d3Sopenharmony_ci    uint16_t key = GetData<uint16_t>();
101094332d3Sopenharmony_ci    uint32_t len = GetData<uint32_t>() % g_maxVectorLen;
102094332d3Sopenharmony_ci    std::vector<uint8_t> values;
103094332d3Sopenharmony_ci    for (uint32_t i = 0; i < len; i++) {
104094332d3Sopenharmony_ci        values.push_back(GetData<uint8_t>() % ALPHA_VALUE_RANGE);
105094332d3Sopenharmony_ci    }
106094332d3Sopenharmony_ci
107094332d3Sopenharmony_ci    (void)g_bufferInterface->SetMetadata(handle, key, values);
108094332d3Sopenharmony_ci}
109094332d3Sopenharmony_ci
110094332d3Sopenharmony_civoid TestGetMetadata(const BufferHandle& handle)
111094332d3Sopenharmony_ci{
112094332d3Sopenharmony_ci    uint16_t key = GetData<uint16_t>();
113094332d3Sopenharmony_ci    std::vector<uint8_t> values = {};
114094332d3Sopenharmony_ci    (void)g_bufferInterface->GetMetadata(handle, key, values);
115094332d3Sopenharmony_ci}
116094332d3Sopenharmony_ci
117094332d3Sopenharmony_civoid TestListMetadataKeys(const BufferHandle& handle)
118094332d3Sopenharmony_ci{
119094332d3Sopenharmony_ci    std::vector<uint32_t> keys = {};
120094332d3Sopenharmony_ci    (void)g_bufferInterface->ListMetadataKeys(handle, keys);
121094332d3Sopenharmony_ci}
122094332d3Sopenharmony_ci
123094332d3Sopenharmony_civoid TestEraseMetadataKey(const BufferHandle& handle)
124094332d3Sopenharmony_ci{
125094332d3Sopenharmony_ci    uint16_t key = GetData<uint16_t>();
126094332d3Sopenharmony_ci    (void)g_bufferInterface->EraseMetadataKey(handle, key);
127094332d3Sopenharmony_ci}
128094332d3Sopenharmony_ci
129094332d3Sopenharmony_citypedef void (*TestFuncs[])(const BufferHandle&);
130094332d3Sopenharmony_ci
131094332d3Sopenharmony_ciTestFuncs g_testFuncs = {
132094332d3Sopenharmony_ci    TestRegisterBuffer,
133094332d3Sopenharmony_ci    TestSetMetadata,
134094332d3Sopenharmony_ci    TestGetMetadata,
135094332d3Sopenharmony_ci    TestEraseMetadataKey,
136094332d3Sopenharmony_ci    TestListMetadataKeys
137094332d3Sopenharmony_ci};
138094332d3Sopenharmony_ci
139094332d3Sopenharmony_cibool FuzzTest(const uint8_t* rawData, size_t size)
140094332d3Sopenharmony_ci{
141094332d3Sopenharmony_ci    if (rawData == nullptr) {
142094332d3Sopenharmony_ci        return false;
143094332d3Sopenharmony_ci    }
144094332d3Sopenharmony_ci
145094332d3Sopenharmony_ci    if (!g_isInit) {
146094332d3Sopenharmony_ci        g_isInit = true;
147094332d3Sopenharmony_ci        g_bufferInterface.reset(OHOS::HDI::Display::Buffer::V1_1::IDisplayBuffer::Get());
148094332d3Sopenharmony_ci        if (g_bufferInterface == nullptr) {
149094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: get IDisplayBuffer failed", __func__);
150094332d3Sopenharmony_ci            return false;
151094332d3Sopenharmony_ci        }
152094332d3Sopenharmony_ci    }
153094332d3Sopenharmony_ci
154094332d3Sopenharmony_ci    // initialize data
155094332d3Sopenharmony_ci    g_data = rawData;
156094332d3Sopenharmony_ci    g_dataSize = size;
157094332d3Sopenharmony_ci    g_pos = 0;
158094332d3Sopenharmony_ci    BufferHandle* buffer = UsingAllocmem();
159094332d3Sopenharmony_ci    if (buffer == nullptr) {
160094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: function UsingAllocmem failed", __func__);
161094332d3Sopenharmony_ci        return false;
162094332d3Sopenharmony_ci    }
163094332d3Sopenharmony_ci
164094332d3Sopenharmony_ci    uint32_t code = GetData<uint32_t>();
165094332d3Sopenharmony_ci    uint32_t len = GetArrLength(g_testFuncs);
166094332d3Sopenharmony_ci    if (len == 0) {
167094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: g_testFuncs length is equal to 0", __func__);
168094332d3Sopenharmony_ci        g_bufferInterface->FreeMem(*buffer);
169094332d3Sopenharmony_ci        return false;
170094332d3Sopenharmony_ci    }
171094332d3Sopenharmony_ci
172094332d3Sopenharmony_ci    g_testFuncs[code % len](*buffer);
173094332d3Sopenharmony_ci    g_bufferInterface->FreeMem(*buffer);
174094332d3Sopenharmony_ci    return true;
175094332d3Sopenharmony_ci}
176094332d3Sopenharmony_ci} // OHOS
177094332d3Sopenharmony_ci
178094332d3Sopenharmony_ci/* Fuzzer entry point */
179094332d3Sopenharmony_ciextern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
180094332d3Sopenharmony_ci{
181094332d3Sopenharmony_ci    if (size < OHOS::THRESHOLD) {
182094332d3Sopenharmony_ci        return 0;
183094332d3Sopenharmony_ci    }
184094332d3Sopenharmony_ci
185094332d3Sopenharmony_ci    OHOS::FuzzTest(data, size);
186094332d3Sopenharmony_ci    return 0;
187094332d3Sopenharmony_ci}
188