/src/fmt/test/fuzzing/float.cc
Line | Count | Source |
1 | | // A fuzzer for floating-point formatter. |
2 | | // For the license information refer to format.h. |
3 | | |
4 | | #include <fmt/format.h> |
5 | | |
6 | | #include <cstdint> |
7 | | #include <cstdlib> |
8 | | #include <limits> |
9 | | #include <stdexcept> |
10 | | |
11 | | #include "fuzzer-common.h" |
12 | | |
13 | 2.05k | void check_round_trip(fmt::string_view format_str, double value) { |
14 | 2.05k | auto buffer = fmt::memory_buffer(); |
15 | 2.05k | fmt::format_to(std::back_inserter(buffer), format_str, value); |
16 | | |
17 | 2.05k | if (std::isnan(value)) { |
18 | 184 | auto nan = std::signbit(value) ? "-nan" : "nan"; |
19 | 184 | if (fmt::string_view(buffer.data(), buffer.size()) != nan) |
20 | 0 | throw std::runtime_error("round trip failure"); |
21 | 184 | return; |
22 | 184 | } |
23 | | |
24 | 1.87k | buffer.push_back('\0'); |
25 | 1.87k | char* ptr = nullptr; |
26 | 1.87k | if (std::strtod(buffer.data(), &ptr) != value) |
27 | 0 | throw std::runtime_error("round trip failure"); |
28 | 1.87k | if (ptr + 1 != buffer.end()) throw std::runtime_error("unparsed output"); |
29 | 1.87k | } |
30 | | |
31 | 1.03k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
32 | 1.03k | if (size <= sizeof(double) || !std::numeric_limits<double>::is_iec559) |
33 | 5 | return 0; |
34 | 1.02k | check_round_trip("{}", assign_from_buf<double>(data)); |
35 | | // A larger than necessary precision is used to trigger the fallback |
36 | | // formatter. |
37 | 1.02k | check_round_trip("{:.50g}", assign_from_buf<double>(data)); |
38 | 1.02k | return 0; |
39 | 1.03k | } |