1 // Copyright 2020 Google LLC
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 <fuzzer/FuzzedDataProvider.h>
16
17 #include "Eigen/Core"
18
19 namespace {
20
21 static constexpr Eigen::Index kEigenTestMaxSize = 64;
22 static constexpr Eigen::Index kEigenIndexOne = static_cast<Eigen::Index>(1);
23
24 template <typename T>
ConsumeValue(FuzzedDataProvider * stream)25 T ConsumeValue(FuzzedDataProvider* stream) {
26 return stream->ConsumeIntegral<T>();
27 }
28
29 template <>
ConsumeValue(FuzzedDataProvider * stream)30 float ConsumeValue(FuzzedDataProvider* stream) {
31 return stream->ConsumeFloatingPoint<float>();
32 }
33
34 template <>
ConsumeValue(FuzzedDataProvider * stream)35 double ConsumeValue(FuzzedDataProvider* stream) {
36 return stream->ConsumeFloatingPoint<double>();
37 }
38
39 template <>
ConsumeValue(FuzzedDataProvider * stream)40 long double ConsumeValue(FuzzedDataProvider* stream) {
41 return stream->ConsumeFloatingPoint<long double>();
42 }
43
44 template <>
ConsumeValue(FuzzedDataProvider * stream)45 std::complex<float> ConsumeValue(FuzzedDataProvider* stream) {
46 return std::complex<float>(stream->ConsumeFloatingPoint<float>(),
47 stream->ConsumeFloatingPoint<float>());
48 }
49
50 template <>
ConsumeValue(FuzzedDataProvider * stream)51 std::complex<double> ConsumeValue(FuzzedDataProvider* stream) {
52 return std::complex<float>(stream->ConsumeFloatingPoint<double>(),
53 stream->ConsumeFloatingPoint<double>());
54 }
55
56 template <typename MatrixType>
GenerateTestMatrix(size_t rows,size_t cols,FuzzedDataProvider * stream)57 MatrixType GenerateTestMatrix(size_t rows, size_t cols,
58 FuzzedDataProvider* stream) {
59 std::vector<typename MatrixType::value_type> test_data(rows * cols);
60 for (auto& value : test_data) {
61 value = ConsumeValue<typename MatrixType::value_type>(stream);
62 }
63 Eigen::Map<MatrixType> mapped_map(test_data.data(), rows, cols);
64 return MatrixType(mapped_map);
65 }
66
67 template <typename MatrixType>
basicStuff(const MatrixType & m,FuzzedDataProvider * stream)68 void basicStuff(const MatrixType& m, FuzzedDataProvider* stream) {
69 typedef typename MatrixType::Scalar Scalar;
70 typedef Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
71 typedef Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime,
72 MatrixType::RowsAtCompileTime>
73 SquareMatrixType;
74
75 Eigen::Index rows = m.rows();
76 Eigen::Index cols = m.cols();
77
78 MatrixType m1 = GenerateTestMatrix<MatrixType>(rows, cols, stream),
79 m2 = GenerateTestMatrix<MatrixType>(rows, cols, stream),
80 m3(rows, cols), mzero = MatrixType::Zero(rows, cols),
81 square = GenerateTestMatrix<
82 Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime,
83 MatrixType::RowsAtCompileTime>>(rows, rows,
84 stream);
85 VectorType v1 = GenerateTestMatrix<VectorType>(rows, 1, stream),
86 vzero = VectorType::Zero(rows);
87 SquareMatrixType sm1 = SquareMatrixType::Random(rows, rows), sm2(rows, rows);
88
89 Scalar x = ConsumeValue<typename MatrixType::Scalar>(stream);
90
91 Eigen::Index r = stream->ConsumeIntegralInRange(
92 std::min(kEigenIndexOne, rows - 1), rows - 1),
93 c = stream->ConsumeIntegralInRange(
94 std::min(kEigenIndexOne, cols - 1), cols - 1);
95
96 m1.coeffRef(r, c) = x;
97 m1(r, c) = x;
98 v1.coeffRef(r) = x;
99 v1(r) = x;
100 v1[r] = x;
101
102 Eigen::Index r1 = stream->ConsumeIntegralInRange(
103 static_cast<Eigen::Index>(0),
104 std::min(static_cast<Eigen::Index>(127), rows - 1));
105 x = v1(static_cast<char>(r1));
106 x = v1(static_cast<signed char>(r1));
107 x = v1(static_cast<unsigned char>(r1));
108 x = v1(static_cast<signed short>(r1));
109 x = v1(static_cast<unsigned short>(r1));
110 x = v1(static_cast<signed int>(r1));
111 x = v1(static_cast<unsigned int>(r1));
112 x = v1(static_cast<signed long>(r1));
113 x = v1(static_cast<unsigned long>(r1));
114 x = v1(static_cast<long long int>(r1));
115 x = v1(static_cast<unsigned long long int>(r1));
116
117 // now test copying a row-vector into a (column-)vector and conversely.
118 square.col(r) = square.row(r).eval();
119 Eigen::Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
120 Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
121 rv = square.row(r);
122 cv = square.col(r);
123
124 cv.transpose();
125
126 m3.real() = m1.real();
127 m1 = m2;
128
129 sm2.setZero();
130 for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i) = sm1.row(i);
131
132 sm2.setZero();
133 for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() = sm1.row(i);
134
135 sm2.setZero();
136 for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() += sm1.row(i);
137
138 sm2.setZero();
139 for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() -= sm1.row(i);
140 }
141
142 template <typename MatrixType>
basicStuffComplex(const MatrixType & m,FuzzedDataProvider * stream)143 void basicStuffComplex(const MatrixType& m, FuzzedDataProvider* stream) {
144 typedef typename MatrixType::Scalar Scalar;
145 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
146 typedef Eigen::Matrix<RealScalar, MatrixType::RowsAtCompileTime,
147 MatrixType::ColsAtCompileTime>
148 RealMatrixType;
149
150 Eigen::Index rows = m.rows();
151 Eigen::Index cols = m.cols();
152
153 RealMatrixType rm1 = GenerateTestMatrix<RealMatrixType>(rows, cols, stream),
154 rm2 = GenerateTestMatrix<RealMatrixType>(rows, cols, stream);
155 MatrixType cm(rows, cols);
156 cm.real() = rm1;
157 cm.imag() = rm2;
158 rm1.setZero();
159 rm2.setZero();
160 rm1 = cm.real();
161 rm2 = cm.imag();
162 cm.real().setZero();
163 }
164
165 } // namespace
166
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)167 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
168 FuzzedDataProvider stream(data, size);
169
170 basicStuff(
171 Eigen::MatrixXcf(
172 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
173 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
174 &stream);
175 basicStuff(
176 Eigen::MatrixXi(
177 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
178 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
179 &stream);
180 basicStuff(
181 Eigen::MatrixXcd(
182 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
183 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
184 &stream);
185 basicStuff(
186 Eigen::Matrix<long double, Eigen::Dynamic, Eigen::Dynamic>(
187 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
188 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
189 &stream);
190 basicStuffComplex(
191 Eigen::MatrixXcf(
192 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
193 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
194 &stream);
195 basicStuffComplex(
196 Eigen::MatrixXcd(
197 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize),
198 stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)),
199 &stream);
200
201 return 0;
202 }
203