/src/glaze/fuzzing/msgpack_roundtrip_floating.cpp
Line | Count | Source |
1 | | #include <cassert> |
2 | | #include <cmath> |
3 | | #include <cstddef> |
4 | | #include <cstdint> |
5 | | #include <cstring> |
6 | | #include <glaze/glaze.hpp> |
7 | | #include <glaze/msgpack.hpp> |
8 | | #include <vector> |
9 | | |
10 | | // must be outside test() to work in gcc<14 |
11 | | template <typename T> |
12 | | struct Value |
13 | | { |
14 | | T value{}; |
15 | | }; |
16 | | |
17 | | template <typename T> |
18 | | void test(const uint8_t* Data, size_t Size) |
19 | 213 | { |
20 | 213 | using S = Value<T>; |
21 | 213 | S s{}; |
22 | | |
23 | 213 | if (Size >= sizeof(T)) { |
24 | 206 | std::memcpy(&s.value, Data, sizeof(T)); |
25 | 206 | } |
26 | 7 | else { |
27 | 7 | return; |
28 | 7 | } |
29 | | // Only test finite values for equality (NaN != NaN by definition) |
30 | 206 | if (std::isfinite(s.value)) { |
31 | 190 | std::string buffer{}; |
32 | 190 | auto write_ec = glz::write_msgpack(s, buffer); |
33 | 190 | if (write_ec) { |
34 | 0 | return; |
35 | 0 | } |
36 | 190 | auto restored = glz::read_msgpack<S>(buffer); |
37 | 190 | assert(restored); |
38 | 190 | assert(restored.value().value == s.value); |
39 | 190 | } |
40 | 16 | else { |
41 | | // For non-finite values, just test that encoding/decoding doesn't crash |
42 | 16 | std::string buffer{}; |
43 | 16 | auto write_ec = glz::write_msgpack(s, buffer); |
44 | 16 | if (write_ec) { |
45 | 0 | return; |
46 | 0 | } |
47 | 16 | [[maybe_unused]] auto restored = glz::read_msgpack<S>(buffer); |
48 | 16 | } |
49 | 206 | } void test<float>(unsigned char const*, unsigned long) Line | Count | Source | 19 | 97 | { | 20 | 97 | using S = Value<T>; | 21 | 97 | S s{}; | 22 | | | 23 | 97 | if (Size >= sizeof(T)) { | 24 | 97 | std::memcpy(&s.value, Data, sizeof(T)); | 25 | 97 | } | 26 | 0 | else { | 27 | 0 | return; | 28 | 0 | } | 29 | | // Only test finite values for equality (NaN != NaN by definition) | 30 | 97 | if (std::isfinite(s.value)) { | 31 | 93 | std::string buffer{}; | 32 | 93 | auto write_ec = glz::write_msgpack(s, buffer); | 33 | 93 | if (write_ec) { | 34 | 0 | return; | 35 | 0 | } | 36 | 93 | auto restored = glz::read_msgpack<S>(buffer); | 37 | 93 | assert(restored); | 38 | 93 | assert(restored.value().value == s.value); | 39 | 93 | } | 40 | 4 | else { | 41 | | // For non-finite values, just test that encoding/decoding doesn't crash | 42 | 4 | std::string buffer{}; | 43 | 4 | auto write_ec = glz::write_msgpack(s, buffer); | 44 | 4 | if (write_ec) { | 45 | 0 | return; | 46 | 0 | } | 47 | 4 | [[maybe_unused]] auto restored = glz::read_msgpack<S>(buffer); | 48 | 4 | } | 49 | 97 | } |
void test<double>(unsigned char const*, unsigned long) Line | Count | Source | 19 | 116 | { | 20 | 116 | using S = Value<T>; | 21 | 116 | S s{}; | 22 | | | 23 | 116 | if (Size >= sizeof(T)) { | 24 | 109 | std::memcpy(&s.value, Data, sizeof(T)); | 25 | 109 | } | 26 | 7 | else { | 27 | 7 | return; | 28 | 7 | } | 29 | | // Only test finite values for equality (NaN != NaN by definition) | 30 | 109 | if (std::isfinite(s.value)) { | 31 | 97 | std::string buffer{}; | 32 | 97 | auto write_ec = glz::write_msgpack(s, buffer); | 33 | 97 | if (write_ec) { | 34 | 0 | return; | 35 | 0 | } | 36 | 97 | auto restored = glz::read_msgpack<S>(buffer); | 37 | 97 | assert(restored); | 38 | 97 | assert(restored.value().value == s.value); | 39 | 97 | } | 40 | 12 | else { | 41 | | // For non-finite values, just test that encoding/decoding doesn't crash | 42 | 12 | std::string buffer{}; | 43 | 12 | auto write_ec = glz::write_msgpack(s, buffer); | 44 | 12 | if (write_ec) { | 45 | 0 | return; | 46 | 0 | } | 47 | 12 | [[maybe_unused]] auto restored = glz::read_msgpack<S>(buffer); | 48 | 12 | } | 49 | 109 | } |
|
50 | | |
51 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) |
52 | 1.55k | { |
53 | 1.55k | if (Size < 1 + sizeof(float)) { |
54 | 12 | return 0; |
55 | 12 | } |
56 | 1.53k | const auto action = Data[0]; |
57 | 1.53k | ++Data; |
58 | 1.53k | --Size; |
59 | | |
60 | 1.53k | switch (action & 0b1) { |
61 | 602 | case 0: |
62 | 602 | test<float>(Data, Size); |
63 | 602 | break; |
64 | 937 | case 1: |
65 | 937 | test<double>(Data, Size); |
66 | 937 | break; |
67 | 1.53k | } |
68 | | |
69 | 1.53k | return 0; |
70 | 1.53k | } |