@@ -79,6 +79,12 @@ class StringTests
79
79
// clang++ -fsanitize=address,undefined,fuzzer -std=c++17 file.cpp
80
80
// and was run for 20min across 16 jobs in parallel.
81
81
#if 0
82
+ template<typename T, typename Traits>
83
+ std::optional<uint64_t> parse_u64(const std::basic_string_view<T, Traits>& str, int base = 0) noexcept
84
+ {
85
+ // ... implementation ...
86
+ }
87
+
82
88
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
83
89
{
84
90
while (size > 0 && (isspace(*data) || *data == '+' || *data == '-'))
@@ -93,27 +99,17 @@ class StringTests
93
99
}
94
100
95
101
char narrow_buffer[128];
96
- wchar_t wide_buffer[128];
97
-
98
102
memcpy(narrow_buffer, data, size);
99
- for (size_t i = 0; i < size; ++i)
100
- {
101
- wide_buffer[i] = data[i];
102
- }
103
-
104
103
// strtoul requires a null terminator
105
104
narrow_buffer[size] = 0;
106
- wide_buffer[size] = 0;
107
105
108
106
char* end;
109
- const auto expected = strtoul(narrow_buffer, &end, 0);
110
- if (end != narrow_buffer + size || expected >= ULONG_MAX / 16)
111
- {
112
- return 0;
113
- }
107
+ const auto val = strtoull(narrow_buffer, &end, 0);
108
+ const auto bad = end != narrow_buffer + size || val == ULLONG_MAX;
109
+ const auto expected = bad ? std::nullopt : std::optional{ val };
114
110
115
- const auto actual = parse_u64({ wide_buffer , size });
116
- if (expected != actual)
111
+ const auto actual = parse_u64(std::string_view{ narrow_buffer , size });
112
+ if (expected != actual && actual.value_or(0) != ULLONG_MAX )
117
113
{
118
114
__builtin_trap();
119
115
}
@@ -122,6 +118,64 @@ class StringTests
122
118
}
123
119
#endif
124
120
121
+ TEST_METHOD (parse_u64_overflow)
122
+ {
123
+ VERIFY_ARE_EQUAL (UINT64_C (18446744073709551614 ), til::details::parse_u64 (std::string_view{ " 18446744073709551614" }));
124
+ VERIFY_ARE_EQUAL (UINT64_C (18446744073709551615 ), til::details::parse_u64 (std::string_view{ " 18446744073709551615" }));
125
+ VERIFY_ARE_EQUAL (std::nullopt, til::details::parse_u64 (std::string_view{ " 18446744073709551616" }));
126
+ VERIFY_ARE_EQUAL (std::nullopt, til::details::parse_u64 (std::string_view{ " 18446744073709551617" }));
127
+ VERIFY_ARE_EQUAL (std::nullopt, til::details::parse_u64 (std::string_view{ " 88888888888888888888" }));
128
+ }
129
+
130
+ TEST_METHOD (parse_unsigned)
131
+ {
132
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" " ));
133
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 0x" ));
134
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" Z" ));
135
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 0xZ" ));
136
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 0Z" ));
137
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 123abc" ));
138
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 0123abc" ));
139
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_unsigned<uint32_t >(" 0x100000000" ));
140
+ VERIFY_ARE_EQUAL (0u , til::parse_unsigned<uint32_t >(" 0" ));
141
+ VERIFY_ARE_EQUAL (0u , til::parse_unsigned<uint32_t >(" 0x0" ));
142
+ VERIFY_ARE_EQUAL (0123u , til::parse_unsigned<uint32_t >(" 0123" ));
143
+ VERIFY_ARE_EQUAL (123u , til::parse_unsigned<uint32_t >(" 123" ));
144
+ VERIFY_ARE_EQUAL (0x123u , til::parse_unsigned<uint32_t >(" 0x123" ));
145
+ VERIFY_ARE_EQUAL (0x123abcu , til::parse_unsigned<uint32_t >(" 0x123abc" ));
146
+ VERIFY_ARE_EQUAL (0X123ABCu , til::parse_unsigned<uint32_t >(" 0X123ABC" ));
147
+ VERIFY_ARE_EQUAL (UINT32_MAX, til::parse_unsigned<uint32_t >(" 0xffffffff" ));
148
+ VERIFY_ARE_EQUAL (UINT32_MAX, til::parse_unsigned<uint32_t >(" 4294967295" ));
149
+ }
150
+
151
+ TEST_METHOD (parse_signed)
152
+ {
153
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" " ));
154
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" -" ));
155
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" --" ));
156
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" --0" ));
157
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" -0Z" ));
158
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" -123abc" ));
159
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" -0123abc" ));
160
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" 0x80000000" ));
161
+ VERIFY_ARE_EQUAL (std::nullopt, til::parse_signed<int32_t >(" -0x80000001" ));
162
+ VERIFY_ARE_EQUAL (0 , til::parse_signed<int32_t >(" 0" ));
163
+ VERIFY_ARE_EQUAL (0 , til::parse_signed<int32_t >(" -0" ));
164
+ VERIFY_ARE_EQUAL (0 , til::parse_signed<int32_t >(" -0x0" ));
165
+ VERIFY_ARE_EQUAL (0123 , til::parse_signed<int32_t >(" 0123" ));
166
+ VERIFY_ARE_EQUAL (123 , til::parse_signed<int32_t >(" 123" ));
167
+ VERIFY_ARE_EQUAL (0x123 , til::parse_signed<int32_t >(" 0x123" ));
168
+ VERIFY_ARE_EQUAL (-0123 , til::parse_signed<int32_t >(" -0123" ));
169
+ VERIFY_ARE_EQUAL (-123 , til::parse_signed<int32_t >(" -123" ));
170
+ VERIFY_ARE_EQUAL (-0x123 , til::parse_signed<int32_t >(" -0x123" ));
171
+ VERIFY_ARE_EQUAL (-0x123abc , til::parse_signed<int32_t >(" -0x123abc" ));
172
+ VERIFY_ARE_EQUAL (-0X123ABC , til::parse_signed<int32_t >(" -0X123ABC" ));
173
+ VERIFY_ARE_EQUAL (INT32_MIN, til::parse_signed<int32_t >(" -0x80000000" ));
174
+ VERIFY_ARE_EQUAL (INT32_MIN, til::parse_signed<int32_t >(" -2147483648" ));
175
+ VERIFY_ARE_EQUAL (INT32_MAX, til::parse_signed<int32_t >(" 0x7fffffff" ));
176
+ VERIFY_ARE_EQUAL (INT32_MAX, til::parse_signed<int32_t >(" 2147483647" ));
177
+ }
178
+
125
179
TEST_METHOD (tolower_ascii)
126
180
{
127
181
for (wchar_t ch = 0 ; ch < 128 ; ++ch)
0 commit comments