Bitcoin Core 28.99.0
P2P Digital Currency
strprintf.cpp
Go to the documentation of this file.
1// Copyright (c) 2020-2021 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
6#include <test/fuzz/fuzz.h>
7#include <test/fuzz/util.h>
8#include <tinyformat.h>
9#include <util/strencodings.h>
10#include <util/translation.h>
11
12#include <algorithm>
13#include <cstdint>
14#include <string>
15#include <vector>
16
17FUZZ_TARGET(str_printf)
18{
19 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
20 const std::string format_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
21 const bilingual_str bilingual_string{format_string, format_string};
22
23 const int digits_in_format_specifier = std::count_if(format_string.begin(), format_string.end(), IsDigit);
24
25 // Avoid triggering the following crash bug:
26 // * strprintf("%987654321000000:", 1);
27 //
28 // Avoid triggering the following OOM bug:
29 // * strprintf("%.222222200000000$", 1.1);
30 //
31 // Upstream bug report: https://github.com/c42f/tinyformat/issues/70
32 if (format_string.find('%') != std::string::npos && digits_in_format_specifier >= 7) {
33 return;
34 }
35
36 // Avoid triggering the following crash bug:
37 // * strprintf("%1$*1$*", -11111111);
38 //
39 // Upstream bug report: https://github.com/c42f/tinyformat/issues/70
40 if (format_string.find('%') != std::string::npos && format_string.find('$') != std::string::npos && format_string.find('*') != std::string::npos && digits_in_format_specifier > 0) {
41 return;
42 }
43
44 // Avoid triggering the following crash bug:
45 // * strprintf("%.1s", (char*)nullptr);
46 //
47 // (void)strprintf(format_string, (char*)nullptr);
48 //
49 // Upstream bug report: https://github.com/c42f/tinyformat/issues/70
50
51 try {
53 fuzzed_data_provider,
54 [&] {
55 (void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
56 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
57 },
58 [&] {
59 (void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
60 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
61 },
62 [&] {
63 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
64 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
65 },
66 [&] {
67 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
68 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
69 },
70 [&] {
71 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<char>());
72 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<char>());
73 },
74 [&] {
75 (void)strprintf(format_string, fuzzed_data_provider.ConsumeBool());
76 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeBool());
77 });
78 } catch (const tinyformat::format_error&) {
79 }
80
81 if (format_string.find('%') != std::string::npos && format_string.find('c') != std::string::npos) {
82 // Avoid triggering the following:
83 // * strprintf("%c", 1.31783e+38);
84 // tinyformat.h:244:36: runtime error: 1.31783e+38 is outside the range of representable values of type 'char'
85 return;
86 }
87
88 if (format_string.find('%') != std::string::npos && format_string.find('*') != std::string::npos) {
89 // Avoid triggering the following:
90 // * strprintf("%*", -2.33527e+38);
91 // tinyformat.h:283:65: runtime error: -2.33527e+38 is outside the range of representable values of type 'int'
92 // * strprintf("%*", -2147483648);
93 // tinyformat.h:763:25: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
94 return;
95 }
96
97 try {
99 fuzzed_data_provider,
100 [&] {
101 (void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
102 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
103 },
104 [&] {
105 (void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
106 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
107 },
108 [&] {
109 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
110 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
111 },
112 [&] {
113 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
114 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
115 },
116 [&] {
117 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
118 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
119 },
120 [&] {
121 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
122 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
123 },
124 [&] {
125 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
126 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
127 },
128 [&] {
129 (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
130 (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
131 });
132 } catch (const tinyformat::format_error&) {
133 }
134}
std::string ConsumeRandomLengthString(size_t max_length)
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1072
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:150
FUZZ_TARGET(str_printf)
Definition: strprintf.cpp:17
Bilingual messages:
Definition: translation.h:21
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
Definition: util.h:35
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1165