Branch data Line data Source code
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 : :
5 : : #include <test/fuzz/FuzzedDataProvider.h>
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 : :
17 [ + - + - ]: 1137 : FUZZ_TARGET(str_printf)
18 : : {
19 : 1134 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
20 : 1134 : const std::string format_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
21 [ + - + - ]: 1134 : const bilingual_str bilingual_string{format_string, format_string};
22 : :
23 [ + - ]: 1134 : 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 [ + + + + ]: 1134 : if (format_string.find('%') != std::string::npos && digits_in_format_specifier >= 7) {
33 : 2 : 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 [ + + + + : 1132 : 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 : 2 : 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 {
52 [ + + ]: 1130 : CallOneOf(
53 : : fuzzed_data_provider,
54 : 1585 : [&] {
55 [ + + ]: 455 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
56 [ + - ]: 359 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
57 : 455 : },
58 : 1230 : [&] {
59 [ + + ]: 100 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
60 [ + - ]: 69 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
61 : 100 : },
62 : 1275 : [&] {
63 : 145 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
64 : 145 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
65 : 145 : },
66 : 1313 : [&] {
67 : 183 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
68 : 183 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
69 : 183 : },
70 : 1268 : [&] {
71 : 138 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<char>());
72 : 138 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<char>());
73 : 138 : },
74 : 1239 : [&] {
75 : 109 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeBool());
76 : 109 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeBool());
77 : 109 : });
78 [ - + ]: 1130 : } catch (const tinyformat::format_error&) {
79 [ + - ]: 295 : }
80 : :
81 [ + + + + ]: 1130 : 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 : 59 : return;
86 : : }
87 : :
88 [ + + + + ]: 1071 : 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 : 68 : return;
95 : : }
96 : :
97 : : try {
98 [ + + ]: 1003 : CallOneOf(
99 : : fuzzed_data_provider,
100 : 1545 : [&] {
101 : 542 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
102 : 542 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
103 : 542 : },
104 : 1059 : [&] {
105 : 56 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
106 : 56 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
107 : 56 : },
108 : 1059 : [&] {
109 : 56 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
110 : 56 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
111 : 56 : },
112 : 1064 : [&] {
113 : 61 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
114 : 61 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
115 : 61 : },
116 : 1060 : [&] {
117 : 57 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
118 : 57 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
119 : 57 : },
120 : 1075 : [&] {
121 : 72 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
122 : 72 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
123 : 72 : },
124 : 1087 : [&] {
125 : 84 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
126 : 84 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
127 : 84 : },
128 : 1078 : [&] {
129 : 75 : (void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
130 : 75 : (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
131 : 75 : });
132 [ - + ]: 1003 : } catch (const tinyformat::format_error&) {
133 [ + - ]: 223 : }
134 [ - + ]: 1652 : }
|