1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "common/DepthPhotoProcessor.h"
18
19 #include <random>
20
21 #include <fuzzer/FuzzedDataProvider.h>
22
23 using namespace android;
24 using namespace android::camera3;
25
26 static const float kMinRatio = 0.1f;
27 static const float kMaxRatio = 0.9f;
28
29 static const uint8_t kTotalDepthJpegBufferCount = 3;
30 static const uint8_t kIntrinsicCalibrationSize = 5;
31 static const uint8_t kLensDistortionSize = 5;
32
33 static const DepthPhotoOrientation kDepthPhotoOrientations[] = {
34 DepthPhotoOrientation::DEPTH_ORIENTATION_0_DEGREES,
35 DepthPhotoOrientation::DEPTH_ORIENTATION_90_DEGREES,
36 DepthPhotoOrientation::DEPTH_ORIENTATION_180_DEGREES,
37 DepthPhotoOrientation::DEPTH_ORIENTATION_270_DEGREES};
38
generateDepth16Buffer(std::vector<uint16_t> * depth16Buffer,size_t length,FuzzedDataProvider & fdp)39 void generateDepth16Buffer(std::vector<uint16_t>* depth16Buffer /*out*/, size_t length,
40 FuzzedDataProvider& fdp) {
41 std::default_random_engine gen(fdp.ConsumeIntegral<uint8_t>());
42 std::uniform_int_distribution uniDist(0, UINT16_MAX - 1);
43 for (size_t i = 0; i < length; ++i) {
44 (*depth16Buffer)[i] = uniDist(gen);
45 }
46 }
47
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)48 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
49 FuzzedDataProvider fdp(data, size);
50
51 DepthPhotoInputFrame inputFrame;
52
53 /**
54 * Consuming 80% of the data to set mMainJpegBuffer. This ensures that we
55 * don't completely exhaust data and use the rest 20% for fuzzing of APIs.
56 */
57 std::vector<uint8_t> buffer = fdp.ConsumeBytes<uint8_t>((size * 80) / 100);
58 inputFrame.mMainJpegBuffer = reinterpret_cast<const char*>(buffer.data());
59
60 /**
61 * Calculate height and width based on buffer size and a ratio within [0.1, 0.9].
62 * The ratio adjusts the dimensions while maintaining a relationship to the total buffer size.
63 */
64 const float ratio = fdp.ConsumeFloatingPointInRange<float>(kMinRatio, kMaxRatio);
65 const size_t height = std::sqrt(buffer.size()) * ratio;
66 const size_t width = std::sqrt(buffer.size()) / ratio;
67
68 inputFrame.mMainJpegHeight = height;
69 inputFrame.mMainJpegWidth = width;
70 inputFrame.mMainJpegSize = buffer.size();
71 // Worst case both depth and confidence maps have the same size as the main color image.
72 inputFrame.mMaxJpegSize = inputFrame.mMainJpegSize * kTotalDepthJpegBufferCount;
73
74 std::vector<uint16_t> depth16Buffer(height * width);
75 generateDepth16Buffer(&depth16Buffer, height * width, fdp);
76 inputFrame.mDepthMapBuffer = depth16Buffer.data();
77 inputFrame.mDepthMapHeight = height;
78 inputFrame.mDepthMapWidth = inputFrame.mDepthMapStride = width;
79
80 inputFrame.mIsLogical = fdp.ConsumeBool();
81
82 inputFrame.mOrientation = fdp.PickValueInArray<DepthPhotoOrientation>(kDepthPhotoOrientations);
83
84 if (fdp.ConsumeBool()) {
85 for (uint8_t i = 0; i < kIntrinsicCalibrationSize; ++i) {
86 inputFrame.mIntrinsicCalibration[i] = fdp.ConsumeFloatingPoint<float>();
87 }
88 inputFrame.mIsIntrinsicCalibrationValid = 1;
89 }
90
91 if (fdp.ConsumeBool()) {
92 for (uint8_t i = 0; i < kLensDistortionSize; ++i) {
93 inputFrame.mLensDistortion[i] = fdp.ConsumeFloatingPoint<float>();
94 }
95 inputFrame.mIsLensDistortionValid = 1;
96 }
97
98 std::vector<uint8_t> depthPhotoBuffer(inputFrame.mMaxJpegSize);
99 size_t actualDepthPhotoSize = 0;
100
101 processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
102 &actualDepthPhotoSize);
103
104 return 0;
105 }
106