• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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