Coverage Report

Created: 2026-07-25 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sparse_fuzzer.cc
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
}