Coverage Report

Created: 2026-10-05 07:13

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.72k
void fuzzSparse(FuzzedDataProvider* stream) {
27
2.72k
  Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
28
2.72k
  Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
29
2.72k
  size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1);
30
31
2.72k
  typedef Eigen::Triplet<Scalar> T;
32
2.72k
  std::vector<T> triplets;
33
41.0k
  for (size_t i = 0; i < numTriplets; ++i) {
34
38.3k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
38.3k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
38.3k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
38.3k
    } else {
40
38.3k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
38.3k
    }
42
38.3k
    triplets.push_back(T(r, c, v));
43
38.3k
  }
44
45
2.72k
  Eigen::SparseMatrix<Scalar> mat(rows, cols);
46
2.72k
  mat.setFromTriplets(triplets.begin(), triplets.end());
47
48
  // Basic operations
49
2.72k
  (void)mat.transpose();
50
2.72k
  (void)mat.adjoint();
51
2.72k
  (void)mat.norm();
52
53
2.72k
  if (rows == cols) {
54
    // SparseLU
55
2.28k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
2.28k
    lu.compute(mat);
57
2.28k
    if (lu.info() == Eigen::Success) {
58
131
      Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
59
131
      (void)lu.solve(b);
60
131
    }
61
2.28k
  }
62
63
  // SparseQR
64
2.72k
  Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr;
65
2.72k
  qr.compute(mat);
66
2.72k
  if (qr.info() == Eigen::Success) {
67
2.72k
    Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
68
2.72k
    (void)qr.solve(b);
69
2.72k
  }
70
2.72k
}
sparse_fuzzer.cc:void (anonymous namespace)::fuzzSparse<float>(FuzzedDataProvider*)
Line
Count
Source
26
1.50k
void fuzzSparse(FuzzedDataProvider* stream) {
27
1.50k
  Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
28
1.50k
  Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
29
1.50k
  size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1);
30
31
1.50k
  typedef Eigen::Triplet<Scalar> T;
32
1.50k
  std::vector<T> triplets;
33
23.0k
  for (size_t i = 0; i < numTriplets; ++i) {
34
21.5k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
21.5k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
21.5k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
21.5k
    } else {
40
21.5k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
21.5k
    }
42
21.5k
    triplets.push_back(T(r, c, v));
43
21.5k
  }
44
45
1.50k
  Eigen::SparseMatrix<Scalar> mat(rows, cols);
46
1.50k
  mat.setFromTriplets(triplets.begin(), triplets.end());
47
48
  // Basic operations
49
1.50k
  (void)mat.transpose();
50
1.50k
  (void)mat.adjoint();
51
1.50k
  (void)mat.norm();
52
53
1.50k
  if (rows == cols) {
54
    // SparseLU
55
1.23k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
1.23k
    lu.compute(mat);
57
1.23k
    if (lu.info() == Eigen::Success) {
58
74
      Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
59
74
      (void)lu.solve(b);
60
74
    }
61
1.23k
  }
62
63
  // SparseQR
64
1.50k
  Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr;
65
1.50k
  qr.compute(mat);
66
1.50k
  if (qr.info() == Eigen::Success) {
67
1.50k
    Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
68
1.50k
    (void)qr.solve(b);
69
1.50k
  }
70
1.50k
}
sparse_fuzzer.cc:void (anonymous namespace)::fuzzSparse<double>(FuzzedDataProvider*)
Line
Count
Source
26
1.22k
void fuzzSparse(FuzzedDataProvider* stream) {
27
1.22k
  Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
28
1.22k
  Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
29
1.22k
  size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1);
30
31
1.22k
  typedef Eigen::Triplet<Scalar> T;
32
1.22k
  std::vector<T> triplets;
33
18.0k
  for (size_t i = 0; i < numTriplets; ++i) {
34
16.8k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
16.8k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
16.8k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
16.8k
    } else {
40
16.8k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
16.8k
    }
42
16.8k
    triplets.push_back(T(r, c, v));
43
16.8k
  }
44
45
1.22k
  Eigen::SparseMatrix<Scalar> mat(rows, cols);
46
1.22k
  mat.setFromTriplets(triplets.begin(), triplets.end());
47
48
  // Basic operations
49
1.22k
  (void)mat.transpose();
50
1.22k
  (void)mat.adjoint();
51
1.22k
  (void)mat.norm();
52
53
1.22k
  if (rows == cols) {
54
    // SparseLU
55
1.05k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
1.05k
    lu.compute(mat);
57
1.05k
    if (lu.info() == Eigen::Success) {
58
57
      Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
59
57
      (void)lu.solve(b);
60
57
    }
61
1.05k
  }
62
63
  // SparseQR
64
1.22k
  Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr;
65
1.22k
  qr.compute(mat);
66
1.22k
  if (qr.info() == Eigen::Success) {
67
1.22k
    Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
68
1.22k
    (void)qr.solve(b);
69
1.22k
  }
70
1.22k
}
71
72
} // namespace
73
74
3.06k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
75
3.06k
  FuzzedDataProvider stream(data, size);
76
77
3.06k
  uint8_t type = stream.ConsumeIntegral<uint8_t>();
78
3.06k
  switch (type % 2) {
79
1.67k
    case 0:
80
1.67k
      fuzzSparse<float>(&stream);
81
1.67k
      break;
82
1.39k
    case 1:
83
1.39k
      fuzzSparse<double>(&stream);
84
1.39k
      break;
85
3.06k
  }
86
87
3.06k
  return 0;
88
3.06k
}