Coverage Report

Created: 2026-09-14 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.67k
void fuzzSparse(FuzzedDataProvider* stream) {
27
2.67k
  Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
28
2.67k
  Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
29
2.67k
  size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1);
30
31
2.67k
  typedef Eigen::Triplet<Scalar> T;
32
2.67k
  std::vector<T> triplets;
33
40.6k
  for (size_t i = 0; i < numTriplets; ++i) {
34
37.9k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
37.9k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
37.9k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
37.9k
    } else {
40
37.9k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
37.9k
    }
42
37.9k
    triplets.push_back(T(r, c, v));
43
37.9k
  }
44
45
2.67k
  Eigen::SparseMatrix<Scalar> mat(rows, cols);
46
2.67k
  mat.setFromTriplets(triplets.begin(), triplets.end());
47
48
  // Basic operations
49
2.67k
  (void)mat.transpose();
50
2.67k
  (void)mat.adjoint();
51
2.67k
  (void)mat.norm();
52
53
2.67k
  if (rows == cols) {
54
    // SparseLU
55
2.24k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
2.24k
    lu.compute(mat);
57
2.24k
    if (lu.info() == Eigen::Success) {
58
132
      Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
59
132
      (void)lu.solve(b);
60
132
    }
61
2.24k
  }
62
63
  // SparseQR
64
2.67k
  Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr;
65
2.67k
  qr.compute(mat);
66
2.67k
  if (qr.info() == Eigen::Success) {
67
2.67k
    Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
68
2.67k
    (void)qr.solve(b);
69
2.67k
  }
70
2.67k
}
sparse_fuzzer.cc:void (anonymous namespace)::fuzzSparse<float>(FuzzedDataProvider*)
Line
Count
Source
26
1.47k
void fuzzSparse(FuzzedDataProvider* stream) {
27
1.47k
  Eigen::Index rows = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
28
1.47k
  Eigen::Index cols = stream->ConsumeIntegralInRange<Eigen::Index>(1, kEigenTestMaxSize);
29
1.47k
  size_t numTriplets = stream->ConsumeIntegralInRange<size_t>(0, rows * cols / 10 + 1);
30
31
1.47k
  typedef Eigen::Triplet<Scalar> T;
32
1.47k
  std::vector<T> triplets;
33
22.8k
  for (size_t i = 0; i < numTriplets; ++i) {
34
21.4k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
21.4k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
21.4k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
21.4k
    } else {
40
21.4k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
21.4k
    }
42
21.4k
    triplets.push_back(T(r, c, v));
43
21.4k
  }
44
45
1.47k
  Eigen::SparseMatrix<Scalar> mat(rows, cols);
46
1.47k
  mat.setFromTriplets(triplets.begin(), triplets.end());
47
48
  // Basic operations
49
1.47k
  (void)mat.transpose();
50
1.47k
  (void)mat.adjoint();
51
1.47k
  (void)mat.norm();
52
53
1.47k
  if (rows == cols) {
54
    // SparseLU
55
1.19k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
1.19k
    lu.compute(mat);
57
1.19k
    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.19k
  }
62
63
  // SparseQR
64
1.47k
  Eigen::SparseQR<Eigen::SparseMatrix<Scalar>, Eigen::COLAMDOrdering<int>> qr;
65
1.47k
  qr.compute(mat);
66
1.47k
  if (qr.info() == Eigen::Success) {
67
1.47k
    Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
68
1.47k
    (void)qr.solve(b);
69
1.47k
  }
70
1.47k
}
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.7k
  for (size_t i = 0; i < numTriplets; ++i) {
34
16.5k
    Eigen::Index r = stream->ConsumeIntegralInRange<Eigen::Index>(0, rows - 1);
35
16.5k
    Eigen::Index c = stream->ConsumeIntegralInRange<Eigen::Index>(0, cols - 1);
36
16.5k
    Scalar v;
37
    if constexpr (std::is_integral_v<Scalar>) {
38
      v = stream->ConsumeIntegral<Scalar>();
39
16.5k
    } else {
40
16.5k
      v = stream->ConsumeFloatingPoint<Scalar>();
41
16.5k
    }
42
16.5k
    triplets.push_back(T(r, c, v));
43
16.5k
  }
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.04k
    Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> lu;
56
1.04k
    lu.compute(mat);
57
1.04k
    if (lu.info() == Eigen::Success) {
58
58
      Eigen::Matrix<Scalar, Eigen::Dynamic, 1> b = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>::Random(rows);
59
58
      (void)lu.solve(b);
60
58
    }
61
1.04k
  }
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.02k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
75
3.02k
  FuzzedDataProvider stream(data, size);
76
77
3.02k
  uint8_t type = stream.ConsumeIntegral<uint8_t>();
78
3.02k
  switch (type % 2) {
79
1.64k
    case 0:
80
1.64k
      fuzzSparse<float>(&stream);
81
1.64k
      break;
82
1.38k
    case 1:
83
1.38k
      fuzzSparse<double>(&stream);
84
1.38k
      break;
85
3.02k
  }
86
87
3.02k
  return 0;
88
3.02k
}