Coverage Report

Created: 2026-05-28 07:09

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