Coverage Report

Created: 2025-04-22 06:24

/src/pffft/pffft_fuzzer.cc
Line
Count
Source
1
// Copyright 2018 Google Inc.
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
///////////////////////////////////////////////////////////////////////////
16
17
#include <algorithm>
18
#include <array>
19
#include <cassert>
20
#include <cstring>
21
22
#include "pffft.h"
23
24
namespace {
25
26
#if defined(TRANSFORM_REAL)
27
// Real FFT.
28
constexpr pffft_transform_t kTransform = PFFFT_REAL;
29
constexpr size_t kSizeOfOneSample = sizeof(float);
30
#elif defined(TRANSFORM_COMPLEX)
31
// Complex FFT.
32
constexpr pffft_transform_t kTransform = PFFFT_COMPLEX;
33
constexpr size_t kSizeOfOneSample = 2 * sizeof(float);  // Real plus imaginary.
34
#else
35
#error FFT transform type not defined.
36
#endif
37
38
340
bool IsValidSize(size_t n) {
39
340
  if (n == 0) { return false; }
40
  // PFFFT only supports transforms for inputs of length N of the form
41
  // N = (2^a)*(3^b)*(5^c) where a >= 5, b >=0, c >= 0.
42
334
  constexpr std::array<int, 3> kFactors = {2, 3, 5};
43
334
  std::array<int, kFactors.size()> factorization{};
44
1.33k
  for (size_t i = 0; i < kFactors.size(); ++i) {
45
1.00k
    const int factor = kFactors[i];
46
4.40k
    while (n % factor == 0) {
47
3.40k
      n /= factor;
48
3.40k
      factorization[i]++;
49
3.40k
    }
50
1.00k
  }
51
334
  return factorization[0] >= 5 && n == 1;
52
340
}
53
54
522
float* AllocatePffftBuffer(size_t number_of_bytes) {
55
522
  return static_cast<float*>(pffft_aligned_malloc(number_of_bytes));
56
522
}
57
58
}  // namespace
59
60
// Entry point for LibFuzzer.
61
340
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
62
  // Set the number of FFT points to use |data| as input vector.
63
  // The latter is truncated if the number of bytes is not an integer
64
  // multiple of the size of one sample (which is either a real or a complex
65
  // floating point number).
66
340
  const size_t fft_size = size / kSizeOfOneSample;
67
340
  if (!IsValidSize(fft_size)) {
68
79
    return 0;
69
79
  }
70
71
261
  const size_t number_of_bytes = fft_size * kSizeOfOneSample;
72
261
  assert(number_of_bytes <= size);
73
74
  // Allocate input and output buffers.
75
261
  float* in = AllocatePffftBuffer(number_of_bytes);
76
261
  float* out = AllocatePffftBuffer(number_of_bytes);
77
78
  // Copy input data.
79
261
  std::memcpy(in, reinterpret_cast<const float*>(data), number_of_bytes);
80
81
  // Setup FFT.
82
261
  PFFFT_Setup* pffft_setup = pffft_new_setup(fft_size, kTransform);
83
84
  // Call different PFFFT functions to maximize the coverage.
85
261
  pffft_transform(pffft_setup, in, out, nullptr, PFFFT_FORWARD);
86
261
  pffft_zconvolve_accumulate(pffft_setup, out, out, out, 1.f);
87
261
  pffft_transform_ordered(pffft_setup, in, out, nullptr, PFFFT_BACKWARD);
88
89
  // Release memory.
90
261
  pffft_aligned_free(in);
91
261
  pffft_aligned_free(out);
92
261
  pffft_destroy_setup(pffft_setup);
93
94
261
  return 0;
95
261
}