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

Side by Side Diff: third_party/WebKit/Source/wtf/text/StringToNumber.cpp

Issue 2563643002: StringToNumber: Fix integer overflow on parsing INT_MIN. (Closed)
Patch Set: Fix MSVC warning. Created 4 years 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "wtf/text/StringToNumber.h" 5 #include "wtf/text/StringToNumber.h"
6 6
7 #include "wtf/ASCIICType.h" 7 #include "wtf/ASCIICType.h"
8 #include "wtf/dtoa.h" 8 #include "wtf/dtoa.h"
9 #include "wtf/text/StringImpl.h" 9 #include "wtf/text/StringImpl.h"
10 #include <type_traits>
10 11
11 namespace WTF { 12 namespace WTF {
12 13
13 static bool isCharacterAllowedInBase(UChar c, int base) { 14 static bool isCharacterAllowedInBase(UChar c, int base) {
14 if (c > 0x7F) 15 if (c > 0x7F)
15 return false; 16 return false;
16 if (isASCIIDigit(c)) 17 if (isASCIIDigit(c))
17 return c - '0' < base; 18 return c - '0' < base;
18 if (isASCIIAlpha(c)) { 19 if (isASCIIAlpha(c)) {
19 if (base > 36) 20 if (base > 36)
20 base = 36; 21 base = 36;
21 return (c >= 'a' && c < 'a' + base - 10) || 22 return (c >= 'a' && c < 'a' + base - 10) ||
22 (c >= 'A' && c < 'A' + base - 10); 23 (c >= 'A' && c < 'A' + base - 10);
23 } 24 }
24 return false; 25 return false;
25 } 26 }
26 27
27 template <typename IntegralType, typename CharType> 28 template <typename IntegralType, typename CharType>
28 static inline IntegralType toIntegralType(const CharType* data, 29 static inline IntegralType toIntegralType(const CharType* data,
29 size_t length, 30 size_t length,
30 bool* ok, 31 bool* ok,
31 int base) { 32 int base) {
32 static const IntegralType integralMax = 33 static_assert(std::is_integral<IntegralType>::value,
34 "IntegralType must be an integral type.");
35 static constexpr IntegralType integralMax =
33 std::numeric_limits<IntegralType>::max(); 36 std::numeric_limits<IntegralType>::max();
34 static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; 37 static constexpr IntegralType integralMin =
35 const IntegralType maxMultiplier = integralMax / base; 38 std::numeric_limits<IntegralType>::min();
39 static constexpr bool isSigned = std::numeric_limits<IntegralType>::is_signed;
36 40
37 IntegralType value = 0; 41 IntegralType value = 0;
38 bool isOk = false; 42 bool isOk = false;
39 bool isNegative = false; 43 bool isNegative = false;
40 44
41 if (!data) 45 if (!data)
42 goto bye; 46 goto bye;
43 47
44 // skip leading whitespace 48 // skip leading whitespace
45 while (length && isSpaceOrNewline(*data)) { 49 while (length && isSpaceOrNewline(*data)) {
(...skipping 17 matching lines...) Expand all
63 --length; 67 --length;
64 IntegralType digitValue; 68 IntegralType digitValue;
65 CharType c = *data; 69 CharType c = *data;
66 if (isASCIIDigit(c)) 70 if (isASCIIDigit(c))
67 digitValue = c - '0'; 71 digitValue = c - '0';
68 else if (c >= 'a') 72 else if (c >= 'a')
69 digitValue = c - 'a' + 10; 73 digitValue = c - 'a' + 10;
70 else 74 else
71 digitValue = c - 'A' + 10; 75 digitValue = c - 'A' + 10;
72 76
73 if (value > maxMultiplier || 77 bool overflow;
74 (value == maxMultiplier && 78 if (isNegative) {
75 digitValue > (integralMax % base) + isNegative)) 79 // Overflow condition:
80 // value * base - digitValue < integralMin
81 // <=> value < (integralMin + digitValue) / base
82 // We must be careful of rounding errors here, but the default rounding
83 // mode (round to zero) works well, so we can use this formula as-is.
84 overflow = value < (integralMin + digitValue) / base;
85 } else {
86 // Overflow condition:
87 // value * base + digitValue > integralMax
88 // <=> value > (integralMax + digitValue) / base
89 // Ditto regarding rounding errors.
90 overflow = value > (integralMax - digitValue) / base;
91 }
92 if (overflow)
76 goto bye; 93 goto bye;
77 94
78 value = base * value + digitValue; 95 if (isNegative)
96 value = base * value - digitValue;
97 else
98 value = base * value + digitValue;
79 ++data; 99 ++data;
80 } 100 }
81 101
82 #if COMPILER(MSVC)
83 #pragma warning(push, 0)
84 #pragma warning(disable : 4146)
85 #endif
86
87 if (isNegative)
88 value = -value;
89
90 #if COMPILER(MSVC)
91 #pragma warning(pop)
92 #endif
93
94 // skip trailing space 102 // skip trailing space
95 while (length && isSpaceOrNewline(*data)) { 103 while (length && isSpaceOrNewline(*data)) {
96 --length; 104 --length;
97 ++data; 105 ++data;
98 } 106 }
99 107
100 if (!length) 108 if (!length)
101 isOk = true; 109 isOk = true;
102 bye: 110 bye:
103 if (ok) 111 if (ok)
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 float charactersToFloat(const UChar* data, 313 float charactersToFloat(const UChar* data,
306 size_t length, 314 size_t length,
307 size_t& parsedLength) { 315 size_t& parsedLength) {
308 // FIXME: This will return ok even when the string fits into a double but 316 // FIXME: This will return ok even when the string fits into a double but
309 // not a float. 317 // not a float.
310 return static_cast<float>( 318 return static_cast<float>(
311 toDoubleType<UChar, AllowTrailingJunk>(data, length, 0, parsedLength)); 319 toDoubleType<UChar, AllowTrailingJunk>(data, length, 0, parsedLength));
312 } 320 }
313 321
314 } // namespace WTF 322 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/BUILD.gn ('k') | third_party/WebKit/Source/wtf/text/StringToNumberTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698