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 "camera.h"
17#include "camera_metadata_operator.h"
18#include "metadata_utils.h"
19
20using namespace OHOS::Camera;
21namespace OHOS {
22const size_t THRESHOLD = 12;
23
24enum BitOperat {
25    INDEX_0 = 0,
26    INDEX_1,
27    INDEX_2,
28    INDEX_3,
29    OFFSET,
30    MOVE_EIGHT_BITS = 8,
31    MOVE_SIXTEEN_BITS = 16,
32    DATA_TYPE_OFFSET = 20,
33    MOVE_TWENTY_FOUR_BITS = 24,
34    META_HEADER_SIZE = 28,
35};
36static uint32_t ConvertUint32(const uint8_t *bitOperat)
37{
38    if (bitOperat == nullptr) {
39        return 0;
40    }
41
42    return (bitOperat[INDEX_0] << MOVE_TWENTY_FOUR_BITS) | (bitOperat[INDEX_1] << MOVE_SIXTEEN_BITS) |
43        (bitOperat[INDEX_2] << MOVE_EIGHT_BITS) | (bitOperat[INDEX_3]);
44}
45
46uint32_t GetMinInputSize(const uint8_t *rawData)
47{
48    uint32_t dataType = ConvertUint32(rawData + DATA_TYPE_OFFSET);
49    uint32_t dataSize;
50    switch (dataType) {
51        case META_TYPE_BYTE:
52            dataSize = sizeof(uint8_t);
53            break;
54        case META_TYPE_INT32:
55            dataSize = sizeof(int32_t);
56            break;
57        case META_TYPE_UINT32:
58            dataSize = sizeof(uint32_t);
59            break;
60        case META_TYPE_FLOAT:
61            dataSize = sizeof(float);
62            break;
63        case META_TYPE_INT64:
64            dataSize = sizeof(int64_t);
65            break;
66        case META_TYPE_DOUBLE:
67            dataSize = sizeof(double);
68            break;
69        case META_TYPE_RATIONAL:
70            dataSize = sizeof(camera_rational_t);
71            break;
72        default:
73            dataSize = 0;
74            break;
75    }
76    uint32_t dataCount = ConvertUint32(rawData + MOVE_TWENTY_FOUR_BITS);
77    uint32_t maxValue = std::numeric_limits<uint32_t>::max();
78    if (dataSize == 0 || dataCount == 0 || dataCount > (maxValue - META_HEADER_SIZE)/dataSize) {
79        return 0;
80    }
81    return (META_HEADER_SIZE + dataSize * dataCount);
82}
83
84void FuncEncodeCameraMetadata(const uint8_t *rawData, size_t size)
85{
86    MessageParcel data;
87    std::shared_ptr<CameraMetadata> metadata
88        = std::make_shared<CameraMetadata>(MAX_ITEM_CAPACITY, MAX_ITEM_CAPACITY);
89    std::vector<uint8_t> cameraAbility(rawData, rawData + size);
90    MetadataUtils::ConvertVecToMetadata(cameraAbility, metadata);
91
92    MetadataUtils::EncodeCameraMetadata(metadata, data);
93}
94
95void FuncDecodeCameraMetadata(const uint8_t *rawData, size_t size)
96{
97    MessageParcel data;
98    std::vector<uint32_t> dataVec(rawData, rawData + size);
99    data.WriteUInt32Vector(dataVec);
100    std::shared_ptr<CameraMetadata> metadata
101        = std::make_shared<CameraMetadata>(MAX_ITEM_CAPACITY, MAX_ITEM_CAPACITY);
102
103    MetadataUtils::DecodeCameraMetadata(data, metadata);
104}
105
106void FuncEncodeToString(const uint8_t *rawData, size_t size)
107{
108    std::shared_ptr<CameraMetadata> metadata
109        = std::make_shared<CameraMetadata>(MAX_ITEM_CAPACITY, MAX_ITEM_CAPACITY);
110    std::vector<uint8_t> cameraAbility(rawData, rawData + size);
111    MetadataUtils::ConvertVecToMetadata(cameraAbility, metadata);
112
113    MetadataUtils::EncodeToString(metadata);
114}
115
116void FuncDecodeFromString(const uint8_t *rawData, size_t size)
117{
118    std::string str(rawData, rawData + size);
119    MetadataUtils::DecodeFromString(str);
120}
121
122void FuncConvertMetadataToVec(const uint8_t *rawData, size_t size)
123{
124    std::shared_ptr<CameraMetadata> metadata
125        = std::make_shared<CameraMetadata>(MAX_ITEM_CAPACITY, MAX_ITEM_CAPACITY);
126    std::vector<uint8_t> cameraAbility(rawData, rawData + size);
127    MetadataUtils::ConvertVecToMetadata(cameraAbility, metadata);
128
129    std::vector<uint8_t> metaVec;
130    MetadataUtils::ConvertMetadataToVec(metadata, metaVec);
131}
132
133void FuncConvertVecToMetadata(const uint8_t *rawData, size_t size)
134{
135    std::shared_ptr<CameraMetadata> metadata
136        = std::make_shared<CameraMetadata>(MAX_ITEM_CAPACITY, MAX_ITEM_CAPACITY);
137    std::vector<uint8_t> cameraAbility(rawData, rawData + size);
138    MetadataUtils::ConvertVecToMetadata(cameraAbility, metadata);
139}
140
141typedef void (*TestFuncDef)(const uint8_t *rawData, size_t size);
142static TestFuncDef g_allTestFunc[] = {
143    FuncEncodeCameraMetadata,
144    FuncDecodeCameraMetadata,
145    FuncEncodeToString,
146    FuncDecodeFromString,
147    FuncConvertMetadataToVec,
148    FuncConvertVecToMetadata,
149};
150
151
152static void TestFuncSwitch(uint32_t cmd, const uint8_t *rawData, size_t size)
153{
154    int testCount = sizeof(g_allTestFunc) / sizeof(g_allTestFunc[0]);
155    TestFuncDef curFunc = g_allTestFunc[cmd % testCount];
156    curFunc(rawData, size);
157}
158
159bool DoSomethingInterestingWithMyApi(const uint8_t *rawData, size_t size)
160{
161    if (rawData == nullptr) {
162        return false;
163    }
164
165    uint32_t cmd = 0;
166    rawData += sizeof(cmd);
167
168    uint32_t minInputSize = GetMinInputSize(rawData);
169    if (size < minInputSize || minInputSize == 0) {
170        return false;
171    }
172
173    TestFuncSwitch(cmd, rawData, size);
174    return true;
175}
176
177extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
178{
179    if (size < OHOS::THRESHOLD) {
180        CAMERA_LOGW("Fuzz test input is invalid. The size is smaller than %{public}zu", OHOS::THRESHOLD);
181        return 0;
182    }
183
184    OHOS::DoSomethingInterestingWithMyApi(data, size);
185    return 0;
186}
187} // namespace OHOS