1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/parse_number.h"
6
7 #include <limits>
8 #include <sstream>
9
10 #include "base/strings/string_number_conversions.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace net {
14 namespace {
15
16 // Returns a decimal string that is one larger than the maximum value that type
17 // T can represent.
18 template <typename T>
CreateOverflowString()19 std::string CreateOverflowString() {
20 const T value = std::numeric_limits<T>::max();
21 std::string result = base::NumberToString(value);
22 EXPECT_NE('9', result.back());
23 result.back()++;
24 return result;
25 }
26
27 // Returns a decimal string that is one less than the minimum value that
28 // (signed) type T can represent.
29 template <typename T>
CreateUnderflowString()30 std::string CreateUnderflowString() {
31 EXPECT_TRUE(std::numeric_limits<T>::is_signed);
32 const T value = std::numeric_limits<T>::min();
33 std::string result = base::NumberToString(value);
34 EXPECT_EQ('-', result.front());
35 EXPECT_NE('9', result.back());
36 result.back()++;
37 return result;
38 }
39
40 // These are potentially valid inputs, along with whether they're non-negative
41 // or "strict" (minimal representations).
42 const struct {
43 const char* input;
44 int expected_output;
45 bool is_non_negative;
46 bool is_strict;
47 } kAnnotatedTests[] = {
48 {"0", 0, /*is_non_negative=*/true, /*is_strict=*/true},
49 {"10", 10, /*is_non_negative=*/true, /*is_strict=*/true},
50 {"1234566", 1234566, /*is_non_negative=*/true, /*is_strict=*/true},
51 {"00", 0, /*is_non_negative=*/true, /*is_strict=*/false},
52 {"010", 10, /*is_non_negative=*/true, /*is_strict=*/false},
53 {"0010", 10, /*is_non_negative=*/true, /*is_strict=*/false},
54 {"-10", -10, /*is_non_negative=*/false, /*is_strict=*/true},
55 {"-1234566", -1234566, /*is_non_negative=*/false, /*is_strict=*/true},
56 {"-0", 0, /*is_non_negative=*/false, /*is_strict=*/false},
57 {"-00", 0, /*is_non_negative=*/false, /*is_strict=*/false},
58 {"-010", -10, /*is_non_negative=*/false, /*is_strict=*/false},
59 {"-0000000000000000000000000000000000001234566", -1234566,
60 /*is_non_negative=*/false, /*is_strict=*/false},
61 };
62
63 // These are invalid inputs that can not be parsed regardless of the format
64 // used (they are neither valid negative or non-negative values).
65 const char* kInvalidParseTests[] = {
66 "", "-", "--", "23-", "134-34", "- ", " ", "+42",
67 " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
68 "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
69 "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
70 };
71
72 // This wrapper calls func() and expects the result to match |expected_output|.
73 template <typename OutputType, typename ParseFunc, typename ExpectationType>
ExpectParseIntSuccess(ParseFunc func,std::string_view input,ParseIntFormat format,ExpectationType expected_output)74 void ExpectParseIntSuccess(ParseFunc func,
75 std::string_view input,
76 ParseIntFormat format,
77 ExpectationType expected_output) {
78 // Try parsing without specifying an error output - expecting success.
79 OutputType parsed_number1;
80 EXPECT_TRUE(func(input, format, &parsed_number1, nullptr))
81 << "Failed to parse: " << input;
82 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
83
84 // Try parsing with an error output - expecting success.
85 ParseIntError kBogusError = static_cast<ParseIntError>(19);
86 ParseIntError error = kBogusError;
87 OutputType parsed_number2;
88 EXPECT_TRUE(func(input, format, &parsed_number2, &error))
89 << "Failed to parse: " << input;
90 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
91 // Check that the error output was not written to.
92 EXPECT_EQ(kBogusError, error);
93 }
94
95 // This wrapper calls func() and expects the failure to match |expected_error|.
96 template <typename OutputType, typename ParseFunc>
ExpectParseIntFailure(ParseFunc func,std::string_view input,ParseIntFormat format,ParseIntError expected_error)97 void ExpectParseIntFailure(ParseFunc func,
98 std::string_view input,
99 ParseIntFormat format,
100 ParseIntError expected_error) {
101 const OutputType kBogusOutput(23614);
102
103 // Try parsing without specifying an error output - expecting failure.
104 OutputType parsed_number1 = kBogusOutput;
105 EXPECT_FALSE(func(input, format, &parsed_number1, nullptr))
106 << "Succeded parsing: " << input;
107 EXPECT_EQ(kBogusOutput, parsed_number1)
108 << "Modified output when failed parsing";
109
110 // Try parsing with an error output - expecting failure.
111 OutputType parsed_number2 = kBogusOutput;
112 ParseIntError error;
113 EXPECT_FALSE(func(input, format, &parsed_number2, &error))
114 << "Succeded parsing: " << input;
115 EXPECT_EQ(kBogusOutput, parsed_number2)
116 << "Modified output when failed parsing";
117 EXPECT_EQ(expected_error, error);
118 }
119
120 // Common tests for both ParseInt*() and ParseUint*()
121 //
122 // When testing ParseUint*() the |format| parameter is not applicable and
123 // should be passed as NON_NEGATIVE.
124 template <typename T, typename ParseFunc>
TestParseIntUsingFormat(ParseFunc func,ParseIntFormat format)125 void TestParseIntUsingFormat(ParseFunc func, ParseIntFormat format) {
126 bool is_format_non_negative = format == ParseIntFormat::NON_NEGATIVE ||
127 format == ParseIntFormat::STRICT_NON_NEGATIVE;
128 bool is_format_strict = format == ParseIntFormat::STRICT_NON_NEGATIVE ||
129 format == ParseIntFormat::STRICT_OPTIONALLY_NEGATIVE;
130 // Test annotated inputs, some of which may not be valid inputs when parsed
131 // using `format`.
132 for (const auto& test : kAnnotatedTests) {
133 SCOPED_TRACE(test.input);
134 if ((test.is_non_negative || !is_format_non_negative) &&
135 (test.is_strict || !is_format_strict)) {
136 ExpectParseIntSuccess<T>(func, test.input, format, test.expected_output);
137 } else {
138 ExpectParseIntFailure<T>(func, test.input, format,
139 ParseIntError::FAILED_PARSE);
140 }
141 }
142
143 // Test invalid inputs (invalid regardless of parsing format)
144 for (auto* input : kInvalidParseTests) {
145 ExpectParseIntFailure<T>(func, input, format, ParseIntError::FAILED_PARSE);
146 }
147
148 // Test parsing the largest possible value for output type.
149 {
150 const T value = std::numeric_limits<T>::max();
151 ExpectParseIntSuccess<T>(func, base::NumberToString(value), format, value);
152 }
153
154 // Test parsing a number one larger than the output type can accomodate
155 // (overflow).
156 ExpectParseIntFailure<T>(func, CreateOverflowString<T>(), format,
157 ParseIntError::FAILED_OVERFLOW);
158
159 // Test parsing a number at least as large as the output allows AND contains
160 // garbage at the end. This exercises an interesting internal quirk of
161 // base::StringToInt*(), in that its result cannot distinguish this case
162 // from overflow.
163 ExpectParseIntFailure<T>(
164 func, base::NumberToString(std::numeric_limits<T>::max()) + " ", format,
165 ParseIntError::FAILED_PARSE);
166
167 ExpectParseIntFailure<T>(func, CreateOverflowString<T>() + " ", format,
168 ParseIntError::FAILED_PARSE);
169
170 // Test parsing the smallest possible value for output type. Don't do the
171 // test for unsigned types since the smallest number 0 is tested elsewhere.
172 if (std::numeric_limits<T>::is_signed) {
173 const T value = std::numeric_limits<T>::min();
174 std::string str_value = base::NumberToString(value);
175
176 // The minimal value is necessarily negative, since this function is
177 // testing only signed output types.
178 if (is_format_non_negative) {
179 ExpectParseIntFailure<T>(func, str_value, format,
180 ParseIntError::FAILED_PARSE);
181 } else {
182 ExpectParseIntSuccess<T>(func, str_value, format, value);
183 }
184 }
185
186 // Test parsing a number one less than the output type can accomodate
187 // (underflow).
188 if (!is_format_non_negative) {
189 ExpectParseIntFailure<T>(func, CreateUnderflowString<T>(), format,
190 ParseIntError::FAILED_UNDERFLOW);
191 }
192
193 // Test parsing a string that contains a valid number followed by a NUL
194 // character.
195 ExpectParseIntFailure<T>(func, std::string_view("123\0", 4), format,
196 ParseIntError::FAILED_PARSE);
197 }
198
199 // Common tests to run for each of the versions of ParseInt*().
200 //
201 // The `func` parameter should be a function pointer to the particular
202 // ParseInt*() function to test.
203 template <typename T, typename ParseFunc>
TestParseInt(ParseFunc func)204 void TestParseInt(ParseFunc func) {
205 // Test using each of the possible formats.
206 ParseIntFormat kFormats[] = {ParseIntFormat::NON_NEGATIVE,
207 ParseIntFormat::OPTIONALLY_NEGATIVE,
208 ParseIntFormat::STRICT_NON_NEGATIVE,
209 ParseIntFormat::STRICT_OPTIONALLY_NEGATIVE};
210
211 for (const auto& format : kFormats) {
212 TestParseIntUsingFormat<T>(func, format);
213 }
214 }
215
216 // Common tests to run for each of the versions of ParseUint*().
217 //
218 // The `func` parameter should be a function pointer to the particular
219 // ParseUint*() function to test.
220 template <typename T, typename ParseFunc>
TestParseUint(ParseFunc func)221 void TestParseUint(ParseFunc func) {
222 // Test using each of the possible formats.
223 ParseIntFormat kFormats[] = {
224 ParseIntFormat::NON_NEGATIVE,
225 ParseIntFormat::STRICT_NON_NEGATIVE,
226 };
227
228 for (const auto& format : kFormats) {
229 TestParseIntUsingFormat<T>(func, format);
230 }
231 }
232
TEST(ParseNumberTest,ParseInt32)233 TEST(ParseNumberTest, ParseInt32) {
234 TestParseInt<int32_t>(ParseInt32);
235 }
236
TEST(ParseNumberTest,ParseInt64)237 TEST(ParseNumberTest, ParseInt64) {
238 TestParseInt<int64_t>(ParseInt64);
239 }
240
TEST(ParseNumberTest,ParseUint32)241 TEST(ParseNumberTest, ParseUint32) {
242 TestParseUint<uint32_t>(ParseUint32);
243 }
244
TEST(ParseNumberTest,ParseUint64)245 TEST(ParseNumberTest, ParseUint64) {
246 TestParseUint<uint64_t>(ParseUint64);
247 }
248
249 } // namespace
250 } // namespace net
251