Coverage Report

Created: 2026-11-12 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/one-arg.cpp
Line
Count
Source
1
// Copyright (c) 2023, Paul Dreik
2
// Licensed under Boost software license 1.0
3
// SPDX-License-Identifier: BSL-1.0
4
5
#include <cstdint>
6
#include <cstring>
7
#include <exception>
8
#include <format>
9
#include <string_view>
10
#include <vector>
11
12
constexpr std::size_t fixed_size = 16;
13
14
struct LimitedIterator
15
{
16
  using iterator_category = std::random_access_iterator_tag;
17
  using difference_type = std::ptrdiff_t;
18
  using value_type = char;
19
  using pointer = char*;
20
  using reference = char&;
21
22
  explicit LimitedIterator(char* ptr, std::size_t N)
23
397
    : m_ptr(ptr)
24
397
    , m_N(N)
25
397
  {
26
397
  }
27
  // Prefix increment
28
  LimitedIterator& operator++()
29
195k
  {
30
195k
    if (m_N == 0)
31
64
      throw std::runtime_error("out of data");
32
195k
    ++m_ptr;
33
195k
    --m_N;
34
195k
    return *this;
35
195k
  }
36
  // Postfix increment
37
  LimitedIterator operator++(int)
38
0
  {
39
0
    if (m_N == 0)
40
0
      throw std::runtime_error("out of data");
41
0
    LimitedIterator tmp = *this;
42
0
    ++m_ptr;
43
0
    --m_N;
44
0
    return tmp;
45
0
  }
46
195k
  char& operator*() { return *m_ptr; }
47
  char* m_ptr{};
48
  std::size_t m_N;
49
};
50
51
template<typename T>
52
void
53
invoke_fmt(const uint8_t* data, size_t size)
54
493
{
55
493
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
493
  if (size <= fixed_size)
57
96
    return;
58
397
  T value{};
59
397
  if constexpr (std::is_same_v<bool, T>) {
60
36
    value = !!data[0];
61
361
  } else {
62
361
    std::memcpy(&value, data, sizeof(T));
63
361
  }
64
65
397
  data += fixed_size;
66
397
  size -= fixed_size;
67
68
397
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
397
  const std::string_view format_string{ chardata, size };
73
74
397
  try {
75
397
    std::vector<char> buf(2000);
76
397
    [[maybe_unused]] auto ignored =
77
397
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
397
                      format_string,
79
397
                      std::make_format_args(value));
80
397
  } catch (std::exception&) {
81
277
  }
82
397
}
void invoke_fmt<bool>(unsigned char const*, unsigned long)
Line
Count
Source
54
42
{
55
42
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
42
  if (size <= fixed_size)
57
6
    return;
58
36
  T value{};
59
36
  if constexpr (std::is_same_v<bool, T>) {
60
36
    value = !!data[0];
61
  } else {
62
    std::memcpy(&value, data, sizeof(T));
63
  }
64
65
36
  data += fixed_size;
66
36
  size -= fixed_size;
67
68
36
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
36
  const std::string_view format_string{ chardata, size };
73
74
36
  try {
75
36
    std::vector<char> buf(2000);
76
36
    [[maybe_unused]] auto ignored =
77
36
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
36
                      format_string,
79
36
                      std::make_format_args(value));
80
36
  } catch (std::exception&) {
81
18
  }
82
36
}
void invoke_fmt<char>(unsigned char const*, unsigned long)
Line
Count
Source
54
30
{
55
30
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
30
  if (size <= fixed_size)
57
6
    return;
58
24
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
24
  } else {
62
24
    std::memcpy(&value, data, sizeof(T));
63
24
  }
64
65
24
  data += fixed_size;
66
24
  size -= fixed_size;
67
68
24
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
24
  const std::string_view format_string{ chardata, size };
73
74
24
  try {
75
24
    std::vector<char> buf(2000);
76
24
    [[maybe_unused]] auto ignored =
77
24
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
24
                      format_string,
79
24
                      std::make_format_args(value));
80
24
  } catch (std::exception&) {
81
17
  }
82
24
}
void invoke_fmt<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
54
30
{
55
30
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
30
  if (size <= fixed_size)
57
6
    return;
58
24
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
24
  } else {
62
24
    std::memcpy(&value, data, sizeof(T));
63
24
  }
64
65
24
  data += fixed_size;
66
24
  size -= fixed_size;
67
68
24
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
24
  const std::string_view format_string{ chardata, size };
73
74
24
  try {
75
24
    std::vector<char> buf(2000);
76
24
    [[maybe_unused]] auto ignored =
77
24
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
24
                      format_string,
79
24
                      std::make_format_args(value));
80
24
  } catch (std::exception&) {
81
16
  }
82
24
}
void invoke_fmt<signed char>(unsigned char const*, unsigned long)
Line
Count
Source
54
32
{
55
32
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
32
  if (size <= fixed_size)
57
6
    return;
58
26
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
26
  } else {
62
26
    std::memcpy(&value, data, sizeof(T));
63
26
  }
64
65
26
  data += fixed_size;
66
26
  size -= fixed_size;
67
68
26
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
26
  const std::string_view format_string{ chardata, size };
73
74
26
  try {
75
26
    std::vector<char> buf(2000);
76
26
    [[maybe_unused]] auto ignored =
77
26
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
26
                      format_string,
79
26
                      std::make_format_args(value));
80
26
  } catch (std::exception&) {
81
17
  }
82
26
}
void invoke_fmt<short>(unsigned char const*, unsigned long)
Line
Count
Source
54
31
{
55
31
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
31
  if (size <= fixed_size)
57
6
    return;
58
25
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
25
  } else {
62
25
    std::memcpy(&value, data, sizeof(T));
63
25
  }
64
65
25
  data += fixed_size;
66
25
  size -= fixed_size;
67
68
25
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
25
  const std::string_view format_string{ chardata, size };
73
74
25
  try {
75
25
    std::vector<char> buf(2000);
76
25
    [[maybe_unused]] auto ignored =
77
25
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
25
                      format_string,
79
25
                      std::make_format_args(value));
80
25
  } catch (std::exception&) {
81
20
  }
82
25
}
void invoke_fmt<unsigned short>(unsigned char const*, unsigned long)
Line
Count
Source
54
29
{
55
29
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
29
  if (size <= fixed_size)
57
6
    return;
58
23
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
23
  } else {
62
23
    std::memcpy(&value, data, sizeof(T));
63
23
  }
64
65
23
  data += fixed_size;
66
23
  size -= fixed_size;
67
68
23
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
23
  const std::string_view format_string{ chardata, size };
73
74
23
  try {
75
23
    std::vector<char> buf(2000);
76
23
    [[maybe_unused]] auto ignored =
77
23
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
23
                      format_string,
79
23
                      std::make_format_args(value));
80
23
  } catch (std::exception&) {
81
16
  }
82
23
}
void invoke_fmt<int>(unsigned char const*, unsigned long)
Line
Count
Source
54
30
{
55
30
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
30
  if (size <= fixed_size)
57
6
    return;
58
24
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
24
  } else {
62
24
    std::memcpy(&value, data, sizeof(T));
63
24
  }
64
65
24
  data += fixed_size;
66
24
  size -= fixed_size;
67
68
24
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
24
  const std::string_view format_string{ chardata, size };
73
74
24
  try {
75
24
    std::vector<char> buf(2000);
76
24
    [[maybe_unused]] auto ignored =
77
24
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
24
                      format_string,
79
24
                      std::make_format_args(value));
80
24
  } catch (std::exception&) {
81
18
  }
82
24
}
void invoke_fmt<unsigned int>(unsigned char const*, unsigned long)
Line
Count
Source
54
29
{
55
29
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
29
  if (size <= fixed_size)
57
6
    return;
58
23
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
23
  } else {
62
23
    std::memcpy(&value, data, sizeof(T));
63
23
  }
64
65
23
  data += fixed_size;
66
23
  size -= fixed_size;
67
68
23
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
23
  const std::string_view format_string{ chardata, size };
73
74
23
  try {
75
23
    std::vector<char> buf(2000);
76
23
    [[maybe_unused]] auto ignored =
77
23
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
23
                      format_string,
79
23
                      std::make_format_args(value));
80
23
  } catch (std::exception&) {
81
19
  }
82
23
}
void invoke_fmt<long>(unsigned char const*, unsigned long)
Line
Count
Source
54
28
{
55
28
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
28
  if (size <= fixed_size)
57
6
    return;
58
22
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
22
  } else {
62
22
    std::memcpy(&value, data, sizeof(T));
63
22
  }
64
65
22
  data += fixed_size;
66
22
  size -= fixed_size;
67
68
22
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
22
  const std::string_view format_string{ chardata, size };
73
74
22
  try {
75
22
    std::vector<char> buf(2000);
76
22
    [[maybe_unused]] auto ignored =
77
22
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
22
                      format_string,
79
22
                      std::make_format_args(value));
80
22
  } catch (std::exception&) {
81
18
  }
82
22
}
void invoke_fmt<unsigned long>(unsigned char const*, unsigned long)
Line
Count
Source
54
30
{
55
30
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
30
  if (size <= fixed_size)
57
6
    return;
58
24
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
24
  } else {
62
24
    std::memcpy(&value, data, sizeof(T));
63
24
  }
64
65
24
  data += fixed_size;
66
24
  size -= fixed_size;
67
68
24
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
24
  const std::string_view format_string{ chardata, size };
73
74
24
  try {
75
24
    std::vector<char> buf(2000);
76
24
    [[maybe_unused]] auto ignored =
77
24
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
24
                      format_string,
79
24
                      std::make_format_args(value));
80
24
  } catch (std::exception&) {
81
18
  }
82
24
}
void invoke_fmt<float>(unsigned char const*, unsigned long)
Line
Count
Source
54
29
{
55
29
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
29
  if (size <= fixed_size)
57
6
    return;
58
23
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
23
  } else {
62
23
    std::memcpy(&value, data, sizeof(T));
63
23
  }
64
65
23
  data += fixed_size;
66
23
  size -= fixed_size;
67
68
23
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
23
  const std::string_view format_string{ chardata, size };
73
74
23
  try {
75
23
    std::vector<char> buf(2000);
76
23
    [[maybe_unused]] auto ignored =
77
23
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
23
                      format_string,
79
23
                      std::make_format_args(value));
80
23
  } catch (std::exception&) {
81
17
  }
82
23
}
void invoke_fmt<double>(unsigned char const*, unsigned long)
Line
Count
Source
54
32
{
55
32
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
32
  if (size <= fixed_size)
57
6
    return;
58
26
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
26
  } else {
62
26
    std::memcpy(&value, data, sizeof(T));
63
26
  }
64
65
26
  data += fixed_size;
66
26
  size -= fixed_size;
67
68
26
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
26
  const std::string_view format_string{ chardata, size };
73
74
26
  try {
75
26
    std::vector<char> buf(2000);
76
26
    [[maybe_unused]] auto ignored =
77
26
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
26
                      format_string,
79
26
                      std::make_format_args(value));
80
26
  } catch (std::exception&) {
81
20
  }
82
26
}
void invoke_fmt<long double>(unsigned char const*, unsigned long)
Line
Count
Source
54
33
{
55
33
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
33
  if (size <= fixed_size)
57
6
    return;
58
27
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
27
  } else {
62
27
    std::memcpy(&value, data, sizeof(T));
63
27
  }
64
65
27
  data += fixed_size;
66
27
  size -= fixed_size;
67
68
27
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
27
  const std::string_view format_string{ chardata, size };
73
74
27
  try {
75
27
    std::vector<char> buf(2000);
76
27
    [[maybe_unused]] auto ignored =
77
27
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
27
                      format_string,
79
27
                      std::make_format_args(value));
80
27
  } catch (std::exception&) {
81
16
  }
82
27
}
void invoke_fmt<void*>(unsigned char const*, unsigned long)
Line
Count
Source
54
27
{
55
27
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
27
  if (size <= fixed_size)
57
6
    return;
58
21
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
21
  } else {
62
21
    std::memcpy(&value, data, sizeof(T));
63
21
  }
64
65
21
  data += fixed_size;
66
21
  size -= fixed_size;
67
68
21
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
21
  const std::string_view format_string{ chardata, size };
73
74
21
  try {
75
21
    std::vector<char> buf(2000);
76
21
    [[maybe_unused]] auto ignored =
77
21
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
21
                      format_string,
79
21
                      std::make_format_args(value));
80
21
  } catch (std::exception&) {
81
16
  }
82
21
}
void invoke_fmt<__int128>(unsigned char const*, unsigned long)
Line
Count
Source
54
29
{
55
29
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
29
  if (size <= fixed_size)
57
6
    return;
58
23
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
23
  } else {
62
23
    std::memcpy(&value, data, sizeof(T));
63
23
  }
64
65
23
  data += fixed_size;
66
23
  size -= fixed_size;
67
68
23
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
23
  const std::string_view format_string{ chardata, size };
73
74
23
  try {
75
23
    std::vector<char> buf(2000);
76
23
    [[maybe_unused]] auto ignored =
77
23
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
23
                      format_string,
79
23
                      std::make_format_args(value));
80
23
  } catch (std::exception&) {
81
16
  }
82
23
}
void invoke_fmt<unsigned __int128>(unsigned char const*, unsigned long)
Line
Count
Source
54
32
{
55
32
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
32
  if (size <= fixed_size)
57
6
    return;
58
26
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
26
  } else {
62
26
    std::memcpy(&value, data, sizeof(T));
63
26
  }
64
65
26
  data += fixed_size;
66
26
  size -= fixed_size;
67
68
26
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
26
  const std::string_view format_string{ chardata, size };
73
74
26
  try {
75
26
    std::vector<char> buf(2000);
76
26
    [[maybe_unused]] auto ignored =
77
26
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
26
                      format_string,
79
26
                      std::make_format_args(value));
80
26
  } catch (std::exception&) {
81
15
  }
82
26
}
83
84
extern "C" int
85
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
86
495
{
87
495
  if (size <= 3)
88
2
    return 0;
89
90
493
  try {
91
92
493
    const auto first = data[0];
93
493
    data++;
94
493
    size--;
95
96
493
    switch (first & 0xF) {
97
42
      case 0:
98
42
        invoke_fmt<bool>(data, size);
99
42
        break;
100
30
      case 1:
101
30
        invoke_fmt<char>(data, size);
102
30
        break;
103
30
      case 2:
104
30
        invoke_fmt<unsigned char>(data, size);
105
30
        break;
106
32
      case 3:
107
32
        invoke_fmt<signed char>(data, size);
108
32
        break;
109
31
      case 4:
110
31
        invoke_fmt<short>(data, size);
111
31
        break;
112
29
      case 5:
113
29
        invoke_fmt<unsigned short>(data, size);
114
29
        break;
115
30
      case 6:
116
30
        invoke_fmt<int>(data, size);
117
30
        break;
118
29
      case 7:
119
29
        invoke_fmt<unsigned int>(data, size);
120
29
        break;
121
28
      case 8:
122
28
        invoke_fmt<long>(data, size);
123
28
        break;
124
30
      case 9:
125
30
        invoke_fmt<unsigned long>(data, size);
126
30
        break;
127
128
29
      case 10:
129
29
        invoke_fmt<float>(data, size);
130
29
        break;
131
32
      case 11:
132
32
        invoke_fmt<double>(data, size);
133
32
        break;
134
33
      case 12:
135
33
        invoke_fmt<long double>(data, size);
136
33
        break;
137
27
      case 13:
138
27
        invoke_fmt<void*>(data, size);
139
27
        break;
140
29
      case 14:
141
29
        invoke_fmt<__int128_t>(data, size);
142
29
        break;
143
32
      case 15:
144
32
        invoke_fmt<__uint128_t>(data, size);
145
32
        break;
146
493
    }
147
493
  } catch (...) {
148
0
  }
149
493
  return 0;
150
493
}