1 // Copyright (c) 2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <memusage.h>
6 #include <test/fuzz/FuzzedDataProvider.h>
7 #include <test/fuzz/fuzz.h>
8 #include <test/fuzz/util.h>
9 #include <util/serfloat.h>
10 #include <version.h>
11 
12 #include <cassert>
13 #include <cmath>
14 #include <limits>
15 
FUZZ_TARGET(float)16 FUZZ_TARGET(float)
17 {
18     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19 
20     {
21         const double d{[&] {
22             double tmp;
23             CallOneOf(
24                 fuzzed_data_provider,
25                 // an actual number
26                 [&] { tmp = fuzzed_data_provider.ConsumeFloatingPoint<double>(); },
27                 // special numbers and NANs
28                 [&] { tmp = fuzzed_data_provider.PickValueInArray({
29                           std::numeric_limits<double>::infinity(),
30                           -std::numeric_limits<double>::infinity(),
31                           std::numeric_limits<double>::min(),
32                           -std::numeric_limits<double>::min(),
33                           std::numeric_limits<double>::max(),
34                           -std::numeric_limits<double>::max(),
35                           std::numeric_limits<double>::lowest(),
36                           -std::numeric_limits<double>::lowest(),
37                           std::numeric_limits<double>::quiet_NaN(),
38                           -std::numeric_limits<double>::quiet_NaN(),
39                           std::numeric_limits<double>::signaling_NaN(),
40                           -std::numeric_limits<double>::signaling_NaN(),
41                           std::numeric_limits<double>::denorm_min(),
42                           -std::numeric_limits<double>::denorm_min(),
43                       }); },
44                 // Anything from raw memory (also checks that DecodeDouble doesn't crash on any input)
45                 [&] { tmp = DecodeDouble(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); });
46             return tmp;
47         }()};
48         (void)memusage::DynamicUsage(d);
49 
50         uint64_t encoded = EncodeDouble(d);
51         if constexpr (std::numeric_limits<double>::is_iec559) {
52             if (!std::isnan(d)) {
53                 uint64_t encoded_in_memory;
54                 std::copy((const unsigned char*)&d, (const unsigned char*)(&d + 1), (unsigned char*)&encoded_in_memory);
55                 assert(encoded_in_memory == encoded);
56             }
57         }
58         double d_deserialized = DecodeDouble(encoded);
59         assert(std::isnan(d) == std::isnan(d_deserialized));
60         assert(std::isnan(d) || d == d_deserialized);
61     }
62 }
63