1 // Copyright 2020 Google Inc.
2 //
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 #include <cstddef>
16 #include <cstdint>
17
18 #include <opencv2/opencv.hpp>
19 #include <fuzzer/FuzzedDataProvider.h>
20
21 namespace {
22
GetCVImage(const std::string & image_string,const int max_pixels,cv::Mat * original_image)23 bool GetCVImage(const std::string& image_string, const int max_pixels,
24 cv::Mat* original_image) {
25 if (image_string.empty()) return false;
26 std::vector<uchar> raw_data(image_string.size());
27 const char* ptr = image_string.data();
28 std::copy(ptr, ptr + image_string.size(), raw_data.data());
29 try {
30 *original_image = cv::imdecode(raw_data, cv::IMREAD_UNCHANGED);
31 } catch (cv::Exception e) {}
32 return !original_image->empty();
33 }
34
TestExternalMethods(const cv::Mat & mat)35 void TestExternalMethods(const cv::Mat& mat) {
36 try{
37 cv::sum(mat);
38 } catch (cv::Exception e) {}
39 try {
40 cv::mean(mat);
41 } catch (cv::Exception e) {}
42 try {
43 cv::trace(mat);
44 } catch (cv::Exception e) {}
45 }
46
TestInternalMethods(const cv::Mat & mat)47 void TestInternalMethods(const cv::Mat& mat) {
48 try {
49 mat.t();
50 } catch (cv::Exception e) {}
51 try {
52 mat.inv();
53 } catch (cv::Exception e) {}
54 try {
55 mat.diag();
56 } catch (cv::Exception e) {}
57 }
58
TestSplitAndMerge(const cv::Mat & image)59 void TestSplitAndMerge(const cv::Mat& image) {
60 std::vector<cv::Mat> split_image(image.channels());
61 cv::split(image, split_image);
62 if (!split_image.empty()) {
63 cv::Mat new_image;
64 cv::merge(split_image, new_image);
65 }
66 }
67
68 } // namespace
69
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)70 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
71 // Prepares a backup image we will use if we cannot successfully get an image
72 // by decoding the string.
73 std::vector<uint8_t> image_data = {data, data + size};
74 cv::Mat backup_image =
75 cv::Mat(1, image_data.size(), CV_8UC1, image_data.data());
76
77 FuzzedDataProvider fuzzed_data_provider(data, size);
78 const int max_pixels = fuzzed_data_provider.ConsumeIntegral<int>();
79 const std::string image_string =
80 fuzzed_data_provider.ConsumeRemainingBytesAsString();
81 cv::Mat original_image;
82 // Tests the clone method.
83 cv::Mat cloned_image = GetCVImage(image_string, max_pixels, &original_image)
84 ? original_image.clone()
85 : backup_image.clone();
86
87 // TODO: enabling the following crashes right away.
88 // TestExternalMethods(cloned_image);
89 TestInternalMethods(cloned_image);
90 TestSplitAndMerge(cloned_image);
91 return 0;
92 }
93