Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: net/base/parse_number.cc

Issue 1828103002: Extend net/base/parse_number.h for parsing of negative numbers, and determining if there was overflo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@proxy_num
Patch Set: Address remaining feedback Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/parse_number.cc
diff --git a/net/base/parse_number.cc b/net/base/parse_number.cc
index d315bec63a906dba00b5f27e56dd20161ace6266..907878f62b86c6f1cac16b13cc624f4169eee40a 100644
--- a/net/base/parse_number.cc
+++ b/net/base/parse_number.cc
@@ -4,20 +4,131 @@
#include "net/base/parse_number.h"
+#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
namespace net {
-bool ParseNonNegativeDecimalInt(const base::StringPiece& input, int* output) {
- if (input.empty() || input[0] > '9' || input[0] < '0')
- return false;
+namespace {
+
+// The string to number conversion functions in //base include the type in the
+// name (like StringToInt64()). The following wrapper methods create a
+// consistent interface to StringToXXX() that calls the appropriate //base
+// version. This simplifies writing generic code with a template.
+
+bool StringToNumber(const base::StringPiece& input, int32_t* output) {
+ // This assumes ints are 32-bits (will fail compile if that ever changes).
+ return base::StringToInt(input, output);
+}
+
+bool StringToNumber(const base::StringPiece& input, uint32_t* output) {
+ // This assumes ints are 32-bits (will fail compile if that ever changes).
+ return base::StringToUint(input, output);
+}
+
+bool StringToNumber(const base::StringPiece& input, int64_t* output) {
+ return base::StringToInt64(input, output);
+}
+
+bool StringToNumber(const base::StringPiece& input, uint64_t* output) {
+ return base::StringToUint64(input, output);
+}
+
+bool SetError(ParseIntegerError error, ParseIntegerError* optional_error) {
+ if (optional_error)
+ *optional_error = error;
+ return false;
+}
+
+template <typename T>
+bool ParseIntegerBase10Helper(const base::StringPiece& input,
+ ParseInteger policy,
+ T* output,
+ ParseIntegerError* optional_error) {
+ if (input.empty())
+ return SetError(ParseIntegerError::FAILED_PARSE, optional_error);
+
+ bool starts_with_negative = input[0] == '-';
+ bool starts_with_digit = input[0] >= '0' && input[0] <= '9';
- int result;
- if (!base::StringToInt(input, &result))
+ // Numbers must start with either a digit or a negative sign
mmenke 2016/03/25 22:10:56 nit: +.
+ //
+ // Reject everything else to prevent the permissive behavior of
+ // StringToIntXXX() when it comes to accepting a leading '+'.
+ if (!starts_with_digit) {
+ if (policy == ParseInteger::DISALLOW_NEGATIVE || !starts_with_negative)
+ return SetError(ParseIntegerError::FAILED_PARSE, optional_error);
+ }
+
+ // Dispatch to the appropriate flavor of base::StringToXXX() by calling one of
+ // the type-specific overloads.
+ T result;
+ if (StringToNumber(input, &result)) {
+ *output = result;
+ return true;
+ }
+
+ // Set an error that distinguishes between parsing/underflow/overflow errors.
+ //
+ // Note that base::StringToXXX() functions have a magical API that modify the
+ // output on failure to indicate whether underflow/overflow happened.
+ //
+ // You would think these can be used here, but unfortunately they return those
+ // magic values in multiple cases making it impossible to distinguish
+ // underflow/overflow from failed parsing due to leading/trailing whitespace.
+ //
+ // So instead look at the number to see if it was valid.
+
+ // Optimization: If the error is not going to be inspected, don't bother
+ // refining it.
+ if (!optional_error)
return false;
- *output = result;
- return true;
+ // Strip any leading negative sign off the number.
+ base::StringPiece numeric_portion =
+ starts_with_negative ? input.substr(1) : input;
+
+ // Test if |numeric_portion| is a valid non-negative integer.
+ if (!numeric_portion.empty() &&
+ numeric_portion.find_first_not_of("0123456789") == std::string::npos) {
+ // If it was, the failure must have been due to underflow/overflow.
+ return SetError(starts_with_negative ? ParseIntegerError::FAILED_UNDERFLOW
+ : ParseIntegerError::FAILED_OVERFLOW,
+ optional_error);
+ }
+
+ // Otherwise it was a mundane parsing error.
+ return SetError(ParseIntegerError::FAILED_PARSE, optional_error);
+}
+
+} // namespace
+
+bool ParseIntegerBase10(const base::StringPiece& input,
+ ParseInteger policy,
+ int32_t* output,
+ ParseIntegerError* optional_error) {
+ return ParseIntegerBase10Helper(input, policy, output, optional_error);
+}
+
+bool ParseIntegerBase10(const base::StringPiece& input,
+ ParseInteger policy,
+ int64_t* output,
+ ParseIntegerError* optional_error) {
+ return ParseIntegerBase10Helper(input, policy, output, optional_error);
+}
+
+bool ParseUnsignedIntegerBase10(const base::StringPiece& input,
+ uint32_t* output,
+ ParseIntegerError* optional_error) {
+ return ParseIntegerBase10Helper(input, ParseInteger::DISALLOW_NEGATIVE,
+ output, optional_error);
+}
+
+bool ParseUnsignedIntegerBase10(const base::StringPiece& input,
+ uint64_t* output,
+ ParseIntegerError* optional_error) {
+ return ParseIntegerBase10Helper(input, ParseInteger::DISALLOW_NEGATIVE,
+ output, optional_error);
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698