Line | Count | Source |
1 | | // Copyright 2026 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 | | #include <Eigen/Sparse> |
17 | | #include <Eigen/SparseLU> |
18 | | #include <Eigen/SparseQR> |
19 | | #include <vector> |
20 | | |
21 | | namespace { |
22 | | |
23 | | static constexpr Eigen::Index kEigenTestMaxSize = 16; |
24 | | |
25 | | template <typename Scalar> |
26 | 2.71k | void fuzzSparse(FuzzedDataProvider* stream) { |
27 | 2.71k | Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); |
28 | 2.71k | Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); |
29 | 2.71k | size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1); |
30 | | |
31 | 2.71k | typedef Eigen::Triplet<Scalar> T; |
32 | 2.71k | std::vector<T> triplets; |
33 | 41.2k | for (size_t i = 0; i < numTriplets; ++i) { |
34 | 38.5k | Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1); |
35 | 38.5k | Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1); |
36 | 38.5k | Scalar v; |
37 | | if constexpr (std::is_integral_v<Scalar>) { |
38 | | v = stream->ConsumeIntegral<Scalar>(); |
39 | 38.5k | } else { |
40 | 38.5k | v = stream->ConsumeFloatingPoint<Scalar>(); |
41 | 38.5k | } |
42 | 38.5k | triplets.push_back(T(r, c, v)); |
43 | 38.5k | } |
44 | | |
45 | 2.71k | Eigen::SparseMatrix<Scalar> mat(rows, cols); |
46 | 2.71k | mat.setFromTriplets(triplets.begin(), triplets.end()); |
47 | | |
48 | | // Basic operations |
49 | 2.71k | (void)mat.transpose(); |
50 | 2.71k | (void)mat.adjoint(); |
51 | 2.71k | (void)mat.norm(); |
52 | | |
53 | 2.71k | if (rows == cols) { |
54 | | // SparseLU |
55 | 2.27k | Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu; |
56 | 2.27k | lu.compute(mat); |
57 | 2.27k | if (lu.info() == Eigen::Success) { |
58 | 114 | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); |
59 | 114 | (void)lu.solve(b); |
60 | 114 | } |
61 | 2.27k | } |
62 | | |
63 | | // SparseQR |
64 | 2.71k | Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr; |
65 | 2.71k | qr.compute(mat); |
66 | 2.71k | if (qr.info() == Eigen::Success) { |
67 | 2.71k | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); |
68 | 2.71k | (void)qr.solve(b); |
69 | 2.71k | } |
70 | 2.71k | } sparse_fuzzer.cc:void (anonymous namespace)::fuzzSparse<float>(FuzzedDataProvider*) Line | Count | Source | 26 | 1.51k | void fuzzSparse(FuzzedDataProvider* stream) { | 27 | 1.51k | Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); | 28 | 1.51k | Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); | 29 | 1.51k | size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1); | 30 | | | 31 | 1.51k | typedef Eigen::Triplet<Scalar> T; | 32 | 1.51k | std::vector<T> triplets; | 33 | 23.3k | for (size_t i = 0; i < numTriplets; ++i) { | 34 | 21.8k | Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1); | 35 | 21.8k | Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1); | 36 | 21.8k | Scalar v; | 37 | | if constexpr (std::is_integral_v<Scalar>) { | 38 | | v = stream->ConsumeIntegral<Scalar>(); | 39 | 21.8k | } else { | 40 | 21.8k | v = stream->ConsumeFloatingPoint<Scalar>(); | 41 | 21.8k | } | 42 | 21.8k | triplets.push_back(T(r, c, v)); | 43 | 21.8k | } | 44 | | | 45 | 1.51k | Eigen::SparseMatrix<Scalar> mat(rows, cols); | 46 | 1.51k | mat.setFromTriplets(triplets.begin(), triplets.end()); | 47 | | | 48 | | // Basic operations | 49 | 1.51k | (void)mat.transpose(); | 50 | 1.51k | (void)mat.adjoint(); | 51 | 1.51k | (void)mat.norm(); | 52 | | | 53 | 1.51k | if (rows == cols) { | 54 | | // SparseLU | 55 | 1.24k | Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu; | 56 | 1.24k | lu.compute(mat); | 57 | 1.24k | if (lu.info() == Eigen::Success) { | 58 | 70 | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); | 59 | 70 | (void)lu.solve(b); | 60 | 70 | } | 61 | 1.24k | } | 62 | | | 63 | | // SparseQR | 64 | 1.51k | Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr; | 65 | 1.51k | qr.compute(mat); | 66 | 1.51k | if (qr.info() == Eigen::Success) { | 67 | 1.51k | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); | 68 | 1.51k | (void)qr.solve(b); | 69 | 1.51k | } | 70 | 1.51k | } |
sparse_fuzzer.cc:void (anonymous namespace)::fuzzSparse<double>(FuzzedDataProvider*) Line | Count | Source | 26 | 1.20k | void fuzzSparse(FuzzedDataProvider* stream) { | 27 | 1.20k | Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); | 28 | 1.20k | Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize); | 29 | 1.20k | size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1); | 30 | | | 31 | 1.20k | typedef Eigen::Triplet<Scalar> T; | 32 | 1.20k | std::vector<T> triplets; | 33 | 17.8k | for (size_t i = 0; i < numTriplets; ++i) { | 34 | 16.6k | Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1); | 35 | 16.6k | Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1); | 36 | 16.6k | Scalar v; | 37 | | if constexpr (std::is_integral_v<Scalar>) { | 38 | | v = stream->ConsumeIntegral<Scalar>(); | 39 | 16.6k | } else { | 40 | 16.6k | v = stream->ConsumeFloatingPoint<Scalar>(); | 41 | 16.6k | } | 42 | 16.6k | triplets.push_back(T(r, c, v)); | 43 | 16.6k | } | 44 | | | 45 | 1.20k | Eigen::SparseMatrix<Scalar> mat(rows, cols); | 46 | 1.20k | mat.setFromTriplets(triplets.begin(), triplets.end()); | 47 | | | 48 | | // Basic operations | 49 | 1.20k | (void)mat.transpose(); | 50 | 1.20k | (void)mat.adjoint(); | 51 | 1.20k | (void)mat.norm(); | 52 | | | 53 | 1.20k | if (rows == cols) { | 54 | | // SparseLU | 55 | 1.03k | Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu; | 56 | 1.03k | lu.compute(mat); | 57 | 1.03k | if (lu.info() == Eigen::Success) { | 58 | 44 | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); | 59 | 44 | (void)lu.solve(b); | 60 | 44 | } | 61 | 1.03k | } | 62 | | | 63 | | // SparseQR | 64 | 1.20k | Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr; | 65 | 1.20k | qr.compute(mat); | 66 | 1.20k | if (qr.info() == Eigen::Success) { | 67 | 1.20k | Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows); | 68 | 1.20k | (void)qr.solve(b); | 69 | 1.20k | } | 70 | 1.20k | } |
|
71 | | |
72 | | } // namespace |
73 | | |
74 | 3.05k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
75 | 3.05k | FuzzedDataProvider stream(data, size); |
76 | | |
77 | 3.05k | uint8_t type = stream.ConsumeIntegral<uint8_t>(); |
78 | 3.05k | switch (type % 2) { |
79 | 1.68k | case 0: |
80 | 1.68k | fuzzSparse<float>(&stream); |
81 | 1.68k | break; |
82 | 1.36k | case 1: |
83 | 1.36k | fuzzSparse<double>(&stream); |
84 | 1.36k | break; |
85 | 3.05k | } |
86 | | |
87 | 3.05k | return 0; |
88 | 3.05k | } |