| // Copyright 2020 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| |
| #include "Eigen/Core" |
| |
| namespace { |
| |
| static constexpr Eigen::Index kEigenTestMaxSize = 64; |
| static constexpr Eigen::Index kEigenIndexOne = static_cast<Eigen::Index>(1); |
| |
| template <typename T> |
| T ConsumeValue(FuzzedDataProvider* stream) { |
| return stream->ConsumeIntegral<T>(); |
| } |
| |
| template <> |
| float ConsumeValue(FuzzedDataProvider* stream) { |
| return stream->ConsumeFloatingPoint<float>(); |
| } |
| |
| template <> |
| double ConsumeValue(FuzzedDataProvider* stream) { |
| return stream->ConsumeFloatingPoint<double>(); |
| } |
| |
| template <> |
| long double ConsumeValue(FuzzedDataProvider* stream) { |
| return stream->ConsumeFloatingPoint<long double>(); |
| } |
| |
| template <> |
| std::complex<float> ConsumeValue(FuzzedDataProvider* stream) { |
| return std::complex<float>(stream->ConsumeFloatingPoint<float>(), |
| stream->ConsumeFloatingPoint<float>()); |
| } |
| |
| template <> |
| std::complex<double> ConsumeValue(FuzzedDataProvider* stream) { |
| return std::complex<float>(stream->ConsumeFloatingPoint<double>(), |
| stream->ConsumeFloatingPoint<double>()); |
| } |
| |
| template <typename MatrixType> |
| MatrixType GenerateTestMatrix(size_t rows, size_t cols, |
| FuzzedDataProvider* stream) { |
| std::vector<typename MatrixType::value_type> test_data(rows * cols); |
| for (auto& value : test_data) { |
| value = ConsumeValue<typename MatrixType::value_type>(stream); |
| } |
| Eigen::Map<MatrixType> mapped_map(test_data.data(), rows, cols); |
| return MatrixType(mapped_map); |
| } |
| |
| template <typename MatrixType> |
| void basicStuff(const MatrixType& m, FuzzedDataProvider* stream) { |
| typedef typename MatrixType::Scalar Scalar; |
| typedef Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; |
| typedef Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, |
| MatrixType::RowsAtCompileTime> |
| SquareMatrixType; |
| |
| Eigen::Index rows = m.rows(); |
| Eigen::Index cols = m.cols(); |
| |
| MatrixType m1 = GenerateTestMatrix<MatrixType>(rows, cols, stream), |
| m2 = GenerateTestMatrix<MatrixType>(rows, cols, stream), |
| m3(rows, cols), mzero = MatrixType::Zero(rows, cols), |
| square = GenerateTestMatrix< |
| Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, |
| MatrixType::RowsAtCompileTime>>(rows, rows, |
| stream); |
| VectorType v1 = GenerateTestMatrix<VectorType>(rows, 1, stream), |
| vzero = VectorType::Zero(rows); |
| SquareMatrixType sm1 = SquareMatrixType::Random(rows, rows), sm2(rows, rows); |
| |
| Scalar x = ConsumeValue<typename MatrixType::Scalar>(stream); |
| |
| Eigen::Index r = stream->ConsumeIntegralInRange( |
| std::min(kEigenIndexOne, rows - 1), rows - 1), |
| c = stream->ConsumeIntegralInRange( |
| std::min(kEigenIndexOne, cols - 1), cols - 1); |
| |
| m1.coeffRef(r, c) = x; |
| m1(r, c) = x; |
| v1.coeffRef(r) = x; |
| v1(r) = x; |
| v1[r] = x; |
| |
| Eigen::Index r1 = stream->ConsumeIntegralInRange( |
| static_cast<Eigen::Index>(0), |
| std::min(static_cast<Eigen::Index>(127), rows - 1)); |
| x = v1(static_cast<char>(r1)); |
| x = v1(static_cast<signed char>(r1)); |
| x = v1(static_cast<unsigned char>(r1)); |
| x = v1(static_cast<signed short>(r1)); |
| x = v1(static_cast<unsigned short>(r1)); |
| x = v1(static_cast<signed int>(r1)); |
| x = v1(static_cast<unsigned int>(r1)); |
| x = v1(static_cast<signed long>(r1)); |
| x = v1(static_cast<unsigned long>(r1)); |
| x = v1(static_cast<long long int>(r1)); |
| x = v1(static_cast<unsigned long long int>(r1)); |
| |
| // now test copying a row-vector into a (column-)vector and conversely. |
| square.col(r) = square.row(r).eval(); |
| Eigen::Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows); |
| Eigen::Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows); |
| rv = square.row(r); |
| cv = square.col(r); |
| |
| cv.transpose(); |
| |
| m3.real() = m1.real(); |
| m1 = m2; |
| |
| sm2.setZero(); |
| for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i) = sm1.row(i); |
| |
| sm2.setZero(); |
| for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() = sm1.row(i); |
| |
| sm2.setZero(); |
| for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() += sm1.row(i); |
| |
| sm2.setZero(); |
| for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() -= sm1.row(i); |
| } |
| |
| template <typename MatrixType> |
| void basicStuffComplex(const MatrixType& m, FuzzedDataProvider* stream) { |
| typedef typename MatrixType::Scalar Scalar; |
| typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; |
| typedef Eigen::Matrix<RealScalar, MatrixType::RowsAtCompileTime, |
| MatrixType::ColsAtCompileTime> |
| RealMatrixType; |
| |
| Eigen::Index rows = m.rows(); |
| Eigen::Index cols = m.cols(); |
| |
| RealMatrixType rm1 = GenerateTestMatrix<RealMatrixType>(rows, cols, stream), |
| rm2 = GenerateTestMatrix<RealMatrixType>(rows, cols, stream); |
| MatrixType cm(rows, cols); |
| cm.real() = rm1; |
| cm.imag() = rm2; |
| rm1.setZero(); |
| rm2.setZero(); |
| rm1 = cm.real(); |
| rm2 = cm.imag(); |
| cm.real().setZero(); |
| } |
| |
| } // namespace |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| FuzzedDataProvider stream(data, size); |
| |
| basicStuff( |
| Eigen::MatrixXcf( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| basicStuff( |
| Eigen::MatrixXi( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| basicStuff( |
| Eigen::MatrixXcd( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| basicStuff( |
| Eigen::Matrix<long double, Eigen::Dynamic, Eigen::Dynamic>( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| basicStuffComplex( |
| Eigen::MatrixXcf( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| basicStuffComplex( |
| Eigen::MatrixXcd( |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), |
| stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), |
| &stream); |
| |
| return 0; |
| } |