Coverage Report

Created: 2025-07-02 07:27

/src/one-arg.cpp
Line
Count
Source (jump to first uncovered line)
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
7.85k
    : m_ptr(ptr)
24
7.85k
    , m_N(N)
25
7.85k
  {
26
7.85k
  }
27
  // Prefix increment
28
  LimitedIterator& operator++()
29
2.49M
  {
30
2.49M
    if (m_N == 0)
31
810
      throw std::runtime_error("out of data");
32
2.49M
    ++m_ptr;
33
2.49M
    --m_N;
34
2.49M
    return *this;
35
2.49M
  }
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
2.49M
  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
7.94k
{
55
7.94k
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
7.94k
  if (size <= fixed_size)
57
83
    return;
58
7.85k
  T value{};
59
7.85k
  if constexpr (std::is_same_v<bool, T>) {
60
261
    value = !!data[0];
61
7.59k
  } else {
62
7.59k
    std::memcpy(&value, data, sizeof(T));
63
7.59k
  }
64
65
7.85k
  data += fixed_size;
66
7.85k
  size -= fixed_size;
67
68
7.85k
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
7.85k
  const std::string_view format_string{ chardata, size };
73
74
7.85k
  try {
75
7.85k
    std::vector<char> buf(2000);
76
7.85k
    [[maybe_unused]] auto ignored =
77
7.85k
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
7.85k
                      format_string,
79
7.85k
                      std::make_format_args(value));
80
7.85k
  } catch (std::exception&) {
81
2.30k
  }
82
7.85k
}
void invoke_fmt<bool>(unsigned char const*, unsigned long)
Line
Count
Source
54
266
{
55
266
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
266
  if (size <= fixed_size)
57
5
    return;
58
261
  T value{};
59
261
  if constexpr (std::is_same_v<bool, T>) {
60
261
    value = !!data[0];
61
  } else {
62
    std::memcpy(&value, data, sizeof(T));
63
  }
64
65
261
  data += fixed_size;
66
261
  size -= fixed_size;
67
68
261
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
261
  const std::string_view format_string{ chardata, size };
73
74
261
  try {
75
261
    std::vector<char> buf(2000);
76
261
    [[maybe_unused]] auto ignored =
77
261
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
261
                      format_string,
79
261
                      std::make_format_args(value));
80
261
  } catch (std::exception&) {
81
103
  }
82
261
}
void invoke_fmt<char>(unsigned char const*, unsigned long)
Line
Count
Source
54
231
{
55
231
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
231
  if (size <= fixed_size)
57
6
    return;
58
225
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
225
  } else {
62
225
    std::memcpy(&value, data, sizeof(T));
63
225
  }
64
65
225
  data += fixed_size;
66
225
  size -= fixed_size;
67
68
225
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
225
  const std::string_view format_string{ chardata, size };
73
74
225
  try {
75
225
    std::vector<char> buf(2000);
76
225
    [[maybe_unused]] auto ignored =
77
225
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
225
                      format_string,
79
225
                      std::make_format_args(value));
80
225
  } catch (std::exception&) {
81
44
  }
82
225
}
void invoke_fmt<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
54
146
{
55
146
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
146
  if (size <= fixed_size)
57
2
    return;
58
144
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
144
  } else {
62
144
    std::memcpy(&value, data, sizeof(T));
63
144
  }
64
65
144
  data += fixed_size;
66
144
  size -= fixed_size;
67
68
144
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
144
  const std::string_view format_string{ chardata, size };
73
74
144
  try {
75
144
    std::vector<char> buf(2000);
76
144
    [[maybe_unused]] auto ignored =
77
144
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
144
                      format_string,
79
144
                      std::make_format_args(value));
80
144
  } catch (std::exception&) {
81
32
  }
82
144
}
void invoke_fmt<signed char>(unsigned char const*, unsigned long)
Line
Count
Source
54
170
{
55
170
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
170
  if (size <= fixed_size)
57
2
    return;
58
168
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
168
  } else {
62
168
    std::memcpy(&value, data, sizeof(T));
63
168
  }
64
65
168
  data += fixed_size;
66
168
  size -= fixed_size;
67
68
168
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
168
  const std::string_view format_string{ chardata, size };
73
74
168
  try {
75
168
    std::vector<char> buf(2000);
76
168
    [[maybe_unused]] auto ignored =
77
168
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
168
                      format_string,
79
168
                      std::make_format_args(value));
80
168
  } catch (std::exception&) {
81
42
  }
82
168
}
void invoke_fmt<short>(unsigned char const*, unsigned long)
Line
Count
Source
54
208
{
55
208
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
208
  if (size <= fixed_size)
57
6
    return;
58
202
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
202
  } else {
62
202
    std::memcpy(&value, data, sizeof(T));
63
202
  }
64
65
202
  data += fixed_size;
66
202
  size -= fixed_size;
67
68
202
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
202
  const std::string_view format_string{ chardata, size };
73
74
202
  try {
75
202
    std::vector<char> buf(2000);
76
202
    [[maybe_unused]] auto ignored =
77
202
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
202
                      format_string,
79
202
                      std::make_format_args(value));
80
202
  } catch (std::exception&) {
81
63
  }
82
202
}
void invoke_fmt<unsigned short>(unsigned char const*, unsigned long)
Line
Count
Source
54
123
{
55
123
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
123
  if (size <= fixed_size)
57
6
    return;
58
117
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
117
  } else {
62
117
    std::memcpy(&value, data, sizeof(T));
63
117
  }
64
65
117
  data += fixed_size;
66
117
  size -= fixed_size;
67
68
117
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
117
  const std::string_view format_string{ chardata, size };
73
74
117
  try {
75
117
    std::vector<char> buf(2000);
76
117
    [[maybe_unused]] auto ignored =
77
117
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
117
                      format_string,
79
117
                      std::make_format_args(value));
80
117
  } catch (std::exception&) {
81
31
  }
82
117
}
void invoke_fmt<int>(unsigned char const*, unsigned long)
Line
Count
Source
54
471
{
55
471
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
471
  if (size <= fixed_size)
57
6
    return;
58
465
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
465
  } else {
62
465
    std::memcpy(&value, data, sizeof(T));
63
465
  }
64
65
465
  data += fixed_size;
66
465
  size -= fixed_size;
67
68
465
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
465
  const std::string_view format_string{ chardata, size };
73
74
465
  try {
75
465
    std::vector<char> buf(2000);
76
465
    [[maybe_unused]] auto ignored =
77
465
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
465
                      format_string,
79
465
                      std::make_format_args(value));
80
465
  } catch (std::exception&) {
81
128
  }
82
465
}
void invoke_fmt<unsigned int>(unsigned char const*, unsigned long)
Line
Count
Source
54
475
{
55
475
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
475
  if (size <= fixed_size)
57
5
    return;
58
470
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
470
  } else {
62
470
    std::memcpy(&value, data, sizeof(T));
63
470
  }
64
65
470
  data += fixed_size;
66
470
  size -= fixed_size;
67
68
470
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
470
  const std::string_view format_string{ chardata, size };
73
74
470
  try {
75
470
    std::vector<char> buf(2000);
76
470
    [[maybe_unused]] auto ignored =
77
470
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
470
                      format_string,
79
470
                      std::make_format_args(value));
80
470
  } catch (std::exception&) {
81
92
  }
82
470
}
void invoke_fmt<long>(unsigned char const*, unsigned long)
Line
Count
Source
54
1.19k
{
55
1.19k
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
1.19k
  if (size <= fixed_size)
57
6
    return;
58
1.18k
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
1.18k
  } else {
62
1.18k
    std::memcpy(&value, data, sizeof(T));
63
1.18k
  }
64
65
1.18k
  data += fixed_size;
66
1.18k
  size -= fixed_size;
67
68
1.18k
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
1.18k
  const std::string_view format_string{ chardata, size };
73
74
1.18k
  try {
75
1.18k
    std::vector<char> buf(2000);
76
1.18k
    [[maybe_unused]] auto ignored =
77
1.18k
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
1.18k
                      format_string,
79
1.18k
                      std::make_format_args(value));
80
1.18k
  } catch (std::exception&) {
81
351
  }
82
1.18k
}
void invoke_fmt<unsigned long>(unsigned char const*, unsigned long)
Line
Count
Source
54
1.29k
{
55
1.29k
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
1.29k
  if (size <= fixed_size)
57
5
    return;
58
1.28k
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
1.28k
  } else {
62
1.28k
    std::memcpy(&value, data, sizeof(T));
63
1.28k
  }
64
65
1.28k
  data += fixed_size;
66
1.28k
  size -= fixed_size;
67
68
1.28k
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
1.28k
  const std::string_view format_string{ chardata, size };
73
74
1.28k
  try {
75
1.28k
    std::vector<char> buf(2000);
76
1.28k
    [[maybe_unused]] auto ignored =
77
1.28k
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
1.28k
                      format_string,
79
1.28k
                      std::make_format_args(value));
80
1.28k
  } catch (std::exception&) {
81
456
  }
82
1.28k
}
void invoke_fmt<float>(unsigned char const*, unsigned long)
Line
Count
Source
54
634
{
55
634
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
634
  if (size <= fixed_size)
57
6
    return;
58
628
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
628
  } else {
62
628
    std::memcpy(&value, data, sizeof(T));
63
628
  }
64
65
628
  data += fixed_size;
66
628
  size -= fixed_size;
67
68
628
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
628
  const std::string_view format_string{ chardata, size };
73
74
628
  try {
75
628
    std::vector<char> buf(2000);
76
628
    [[maybe_unused]] auto ignored =
77
628
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
628
                      format_string,
79
628
                      std::make_format_args(value));
80
628
  } catch (std::exception&) {
81
190
  }
82
628
}
void invoke_fmt<double>(unsigned char const*, unsigned long)
Line
Count
Source
54
779
{
55
779
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
779
  if (size <= fixed_size)
57
5
    return;
58
774
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
774
  } else {
62
774
    std::memcpy(&value, data, sizeof(T));
63
774
  }
64
65
774
  data += fixed_size;
66
774
  size -= fixed_size;
67
68
774
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
774
  const std::string_view format_string{ chardata, size };
73
74
774
  try {
75
774
    std::vector<char> buf(2000);
76
774
    [[maybe_unused]] auto ignored =
77
774
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
774
                      format_string,
79
774
                      std::make_format_args(value));
80
774
  } catch (std::exception&) {
81
232
  }
82
774
}
void invoke_fmt<long double>(unsigned char const*, unsigned long)
Line
Count
Source
54
666
{
55
666
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
666
  if (size <= fixed_size)
57
6
    return;
58
660
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
660
  } else {
62
660
    std::memcpy(&value, data, sizeof(T));
63
660
  }
64
65
660
  data += fixed_size;
66
660
  size -= fixed_size;
67
68
660
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
660
  const std::string_view format_string{ chardata, size };
73
74
660
  try {
75
660
    std::vector<char> buf(2000);
76
660
    [[maybe_unused]] auto ignored =
77
660
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
660
                      format_string,
79
660
                      std::make_format_args(value));
80
660
  } catch (std::exception&) {
81
241
  }
82
660
}
void invoke_fmt<void*>(unsigned char const*, unsigned long)
Line
Count
Source
54
265
{
55
265
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
265
  if (size <= fixed_size)
57
5
    return;
58
260
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
260
  } else {
62
260
    std::memcpy(&value, data, sizeof(T));
63
260
  }
64
65
260
  data += fixed_size;
66
260
  size -= fixed_size;
67
68
260
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
260
  const std::string_view format_string{ chardata, size };
73
74
260
  try {
75
260
    std::vector<char> buf(2000);
76
260
    [[maybe_unused]] auto ignored =
77
260
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
260
                      format_string,
79
260
                      std::make_format_args(value));
80
260
  } catch (std::exception&) {
81
122
  }
82
260
}
void invoke_fmt<__int128>(unsigned char const*, unsigned long)
Line
Count
Source
54
454
{
55
454
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
454
  if (size <= fixed_size)
57
6
    return;
58
448
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
448
  } else {
62
448
    std::memcpy(&value, data, sizeof(T));
63
448
  }
64
65
448
  data += fixed_size;
66
448
  size -= fixed_size;
67
68
448
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
448
  const std::string_view format_string{ chardata, size };
73
74
448
  try {
75
448
    std::vector<char> buf(2000);
76
448
    [[maybe_unused]] auto ignored =
77
448
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
448
                      format_string,
79
448
                      std::make_format_args(value));
80
448
  } catch (std::exception&) {
81
77
  }
82
448
}
void invoke_fmt<unsigned __int128>(unsigned char const*, unsigned long)
Line
Count
Source
54
568
{
55
568
  static_assert(sizeof(T) <= fixed_size, "fixed_size is too small");
56
568
  if (size <= fixed_size)
57
6
    return;
58
562
  T value{};
59
  if constexpr (std::is_same_v<bool, T>) {
60
    value = !!data[0];
61
562
  } else {
62
562
    std::memcpy(&value, data, sizeof(T));
63
562
  }
64
65
562
  data += fixed_size;
66
562
  size -= fixed_size;
67
68
562
  const auto* chardata = reinterpret_cast<const char*>(data);
69
  //  std::string format_string{ chardata, chardata + size };
70
71
  //  format_string.append(10, '}');
72
562
  const std::string_view format_string{ chardata, size };
73
74
562
  try {
75
562
    std::vector<char> buf(2000);
76
562
    [[maybe_unused]] auto ignored =
77
562
      std::vformat_to(LimitedIterator(buf.data(), buf.size() - 2),
78
562
                      format_string,
79
562
                      std::make_format_args(value));
80
562
  } catch (std::exception&) {
81
96
  }
82
562
}
83
84
extern "C" int
85
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
86
7.94k
{
87
7.94k
  if (size <= 3)
88
2
    return 0;
89
90
7.94k
  try {
91
92
7.94k
    const auto first = data[0];
93
7.94k
    data++;
94
7.94k
    size--;
95
96
7.94k
    switch (first & 0xF) {
97
266
      case 0:
98
266
        invoke_fmt<bool>(data, size);
99
266
        break;
100
231
      case 1:
101
231
        invoke_fmt<char>(data, size);
102
231
        break;
103
146
      case 2:
104
146
        invoke_fmt<unsigned char>(data, size);
105
146
        break;
106
170
      case 3:
107
170
        invoke_fmt<signed char>(data, size);
108
170
        break;
109
208
      case 4:
110
208
        invoke_fmt<short>(data, size);
111
208
        break;
112
123
      case 5:
113
123
        invoke_fmt<unsigned short>(data, size);
114
123
        break;
115
471
      case 6:
116
471
        invoke_fmt<int>(data, size);
117
471
        break;
118
475
      case 7:
119
475
        invoke_fmt<unsigned int>(data, size);
120
475
        break;
121
1.19k
      case 8:
122
1.19k
        invoke_fmt<long>(data, size);
123
1.19k
        break;
124
1.29k
      case 9:
125
1.29k
        invoke_fmt<unsigned long>(data, size);
126
1.29k
        break;
127
128
634
      case 10:
129
634
        invoke_fmt<float>(data, size);
130
634
        break;
131
779
      case 11:
132
779
        invoke_fmt<double>(data, size);
133
779
        break;
134
666
      case 12:
135
666
        invoke_fmt<long double>(data, size);
136
666
        break;
137
265
      case 13:
138
265
        invoke_fmt<void*>(data, size);
139
265
        break;
140
454
      case 14:
141
454
        invoke_fmt<__int128_t>(data, size);
142
454
        break;
143
568
      case 15:
144
568
        invoke_fmt<__uint128_t>(data, size);
145
568
        break;
146
7.94k
    }
147
7.94k
  } catch (...) {
148
0
  }
149
7.94k
  return 0;
150
7.94k
}