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