1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,516 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/strings/string_number_conversions.h" 1.9 + 1.10 +#include <ctype.h> 1.11 +#include <errno.h> 1.12 +#include <stdlib.h> 1.13 +#include <wctype.h> 1.14 + 1.15 +#include <limits> 1.16 + 1.17 +#include "base/logging.h" 1.18 +#include "base/scoped_clear_errno.h" 1.19 +#include "base/strings/utf_string_conversions.h" 1.20 +#include "base/third_party/dmg_fp/dmg_fp.h" 1.21 + 1.22 +namespace base { 1.23 + 1.24 +namespace { 1.25 + 1.26 +template <typename STR, typename INT, typename UINT, bool NEG> 1.27 +struct IntToStringT { 1.28 + // This is to avoid a compiler warning about unary minus on unsigned type. 1.29 + // For example, say you had the following code: 1.30 + // template <typename INT> 1.31 + // INT abs(INT value) { return value < 0 ? -value : value; } 1.32 + // Even though if INT is unsigned, it's impossible for value < 0, so the 1.33 + // unary minus will never be taken, the compiler will still generate a 1.34 + // warning. We do a little specialization dance... 1.35 + template <typename INT2, typename UINT2, bool NEG2> 1.36 + struct ToUnsignedT {}; 1.37 + 1.38 + template <typename INT2, typename UINT2> 1.39 + struct ToUnsignedT<INT2, UINT2, false> { 1.40 + static UINT2 ToUnsigned(INT2 value) { 1.41 + return static_cast<UINT2>(value); 1.42 + } 1.43 + }; 1.44 + 1.45 + template <typename INT2, typename UINT2> 1.46 + struct ToUnsignedT<INT2, UINT2, true> { 1.47 + static UINT2 ToUnsigned(INT2 value) { 1.48 + return static_cast<UINT2>(value < 0 ? -value : value); 1.49 + } 1.50 + }; 1.51 + 1.52 + // This set of templates is very similar to the above templates, but 1.53 + // for testing whether an integer is negative. 1.54 + template <typename INT2, bool NEG2> 1.55 + struct TestNegT {}; 1.56 + template <typename INT2> 1.57 + struct TestNegT<INT2, false> { 1.58 + static bool TestNeg(INT2 value) { 1.59 + // value is unsigned, and can never be negative. 1.60 + return false; 1.61 + } 1.62 + }; 1.63 + template <typename INT2> 1.64 + struct TestNegT<INT2, true> { 1.65 + static bool TestNeg(INT2 value) { 1.66 + return value < 0; 1.67 + } 1.68 + }; 1.69 + 1.70 + static STR IntToString(INT value) { 1.71 + // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. 1.72 + // So round up to allocate 3 output characters per byte, plus 1 for '-'. 1.73 + const int kOutputBufSize = 3 * sizeof(INT) + 1; 1.74 + 1.75 + // Allocate the whole string right away, we will right back to front, and 1.76 + // then return the substr of what we ended up using. 1.77 + STR outbuf(kOutputBufSize, 0); 1.78 + 1.79 + bool is_neg = TestNegT<INT, NEG>::TestNeg(value); 1.80 + // Even though is_neg will never be true when INT is parameterized as 1.81 + // unsigned, even the presence of the unary operation causes a warning. 1.82 + UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); 1.83 + 1.84 + for (typename STR::iterator it = outbuf.end();;) { 1.85 + --it; 1.86 + DCHECK(it != outbuf.begin()); 1.87 + *it = static_cast<typename STR::value_type>((res % 10) + '0'); 1.88 + res /= 10; 1.89 + 1.90 + // We're done.. 1.91 + if (res == 0) { 1.92 + if (is_neg) { 1.93 + --it; 1.94 + DCHECK(it != outbuf.begin()); 1.95 + *it = static_cast<typename STR::value_type>('-'); 1.96 + } 1.97 + return STR(it, outbuf.end()); 1.98 + } 1.99 + } 1.100 + NOTREACHED(); 1.101 + return STR(); 1.102 + } 1.103 +}; 1.104 + 1.105 +// Utility to convert a character to a digit in a given base 1.106 +template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { 1.107 +}; 1.108 + 1.109 +// Faster specialization for bases <= 10 1.110 +template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { 1.111 + public: 1.112 + static bool Convert(CHAR c, uint8* digit) { 1.113 + if (c >= '0' && c < '0' + BASE) { 1.114 + *digit = c - '0'; 1.115 + return true; 1.116 + } 1.117 + return false; 1.118 + } 1.119 +}; 1.120 + 1.121 +// Specialization for bases where 10 < base <= 36 1.122 +template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { 1.123 + public: 1.124 + static bool Convert(CHAR c, uint8* digit) { 1.125 + if (c >= '0' && c <= '9') { 1.126 + *digit = c - '0'; 1.127 + } else if (c >= 'a' && c < 'a' + BASE - 10) { 1.128 + *digit = c - 'a' + 10; 1.129 + } else if (c >= 'A' && c < 'A' + BASE - 10) { 1.130 + *digit = c - 'A' + 10; 1.131 + } else { 1.132 + return false; 1.133 + } 1.134 + return true; 1.135 + } 1.136 +}; 1.137 + 1.138 +template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) { 1.139 + return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit); 1.140 +} 1.141 + 1.142 +// There is an IsWhitespace for wchars defined in string_util.h, but it is 1.143 +// locale independent, whereas the functions we are replacing were 1.144 +// locale-dependent. TBD what is desired, but for the moment let's not introduce 1.145 +// a change in behaviour. 1.146 +template<typename CHAR> class WhitespaceHelper { 1.147 +}; 1.148 + 1.149 +template<> class WhitespaceHelper<char> { 1.150 + public: 1.151 + static bool Invoke(char c) { 1.152 + return 0 != isspace(static_cast<unsigned char>(c)); 1.153 + } 1.154 +}; 1.155 + 1.156 +template<> class WhitespaceHelper<char16> { 1.157 + public: 1.158 + static bool Invoke(char16 c) { 1.159 + return 0 != iswspace(c); 1.160 + } 1.161 +}; 1.162 + 1.163 +template<typename CHAR> bool LocalIsWhitespace(CHAR c) { 1.164 + return WhitespaceHelper<CHAR>::Invoke(c); 1.165 +} 1.166 + 1.167 +// IteratorRangeToNumberTraits should provide: 1.168 +// - a typedef for iterator_type, the iterator type used as input. 1.169 +// - a typedef for value_type, the target numeric type. 1.170 +// - static functions min, max (returning the minimum and maximum permitted 1.171 +// values) 1.172 +// - constant kBase, the base in which to interpret the input 1.173 +template<typename IteratorRangeToNumberTraits> 1.174 +class IteratorRangeToNumber { 1.175 + public: 1.176 + typedef IteratorRangeToNumberTraits traits; 1.177 + typedef typename traits::iterator_type const_iterator; 1.178 + typedef typename traits::value_type value_type; 1.179 + 1.180 + // Generalized iterator-range-to-number conversion. 1.181 + // 1.182 + static bool Invoke(const_iterator begin, 1.183 + const_iterator end, 1.184 + value_type* output) { 1.185 + bool valid = true; 1.186 + 1.187 + while (begin != end && LocalIsWhitespace(*begin)) { 1.188 + valid = false; 1.189 + ++begin; 1.190 + } 1.191 + 1.192 + if (begin != end && *begin == '-') { 1.193 + if (!std::numeric_limits<value_type>::is_signed) { 1.194 + valid = false; 1.195 + } else if (!Negative::Invoke(begin + 1, end, output)) { 1.196 + valid = false; 1.197 + } 1.198 + } else { 1.199 + if (begin != end && *begin == '+') { 1.200 + ++begin; 1.201 + } 1.202 + if (!Positive::Invoke(begin, end, output)) { 1.203 + valid = false; 1.204 + } 1.205 + } 1.206 + 1.207 + return valid; 1.208 + } 1.209 + 1.210 + private: 1.211 + // Sign provides: 1.212 + // - a static function, CheckBounds, that determines whether the next digit 1.213 + // causes an overflow/underflow 1.214 + // - a static function, Increment, that appends the next digit appropriately 1.215 + // according to the sign of the number being parsed. 1.216 + template<typename Sign> 1.217 + class Base { 1.218 + public: 1.219 + static bool Invoke(const_iterator begin, const_iterator end, 1.220 + typename traits::value_type* output) { 1.221 + *output = 0; 1.222 + 1.223 + if (begin == end) { 1.224 + return false; 1.225 + } 1.226 + 1.227 + // Note: no performance difference was found when using template 1.228 + // specialization to remove this check in bases other than 16 1.229 + if (traits::kBase == 16 && end - begin > 2 && *begin == '0' && 1.230 + (*(begin + 1) == 'x' || *(begin + 1) == 'X')) { 1.231 + begin += 2; 1.232 + } 1.233 + 1.234 + for (const_iterator current = begin; current != end; ++current) { 1.235 + uint8 new_digit = 0; 1.236 + 1.237 + if (!CharToDigit<traits::kBase>(*current, &new_digit)) { 1.238 + return false; 1.239 + } 1.240 + 1.241 + if (current != begin) { 1.242 + if (!Sign::CheckBounds(output, new_digit)) { 1.243 + return false; 1.244 + } 1.245 + *output *= traits::kBase; 1.246 + } 1.247 + 1.248 + Sign::Increment(new_digit, output); 1.249 + } 1.250 + return true; 1.251 + } 1.252 + }; 1.253 + 1.254 + class Positive : public Base<Positive> { 1.255 + public: 1.256 + static bool CheckBounds(value_type* output, uint8 new_digit) { 1.257 + if (*output > static_cast<value_type>(traits::max() / traits::kBase) || 1.258 + (*output == static_cast<value_type>(traits::max() / traits::kBase) && 1.259 + new_digit > traits::max() % traits::kBase)) { 1.260 + *output = traits::max(); 1.261 + return false; 1.262 + } 1.263 + return true; 1.264 + } 1.265 + static void Increment(uint8 increment, value_type* output) { 1.266 + *output += increment; 1.267 + } 1.268 + }; 1.269 + 1.270 + class Negative : public Base<Negative> { 1.271 + public: 1.272 + static bool CheckBounds(value_type* output, uint8 new_digit) { 1.273 + if (*output < traits::min() / traits::kBase || 1.274 + (*output == traits::min() / traits::kBase && 1.275 + new_digit > 0 - traits::min() % traits::kBase)) { 1.276 + *output = traits::min(); 1.277 + return false; 1.278 + } 1.279 + return true; 1.280 + } 1.281 + static void Increment(uint8 increment, value_type* output) { 1.282 + *output -= increment; 1.283 + } 1.284 + }; 1.285 +}; 1.286 + 1.287 +template<typename ITERATOR, typename VALUE, int BASE> 1.288 +class BaseIteratorRangeToNumberTraits { 1.289 + public: 1.290 + typedef ITERATOR iterator_type; 1.291 + typedef VALUE value_type; 1.292 + static value_type min() { 1.293 + return std::numeric_limits<value_type>::min(); 1.294 + } 1.295 + static value_type max() { 1.296 + return std::numeric_limits<value_type>::max(); 1.297 + } 1.298 + static const int kBase = BASE; 1.299 +}; 1.300 + 1.301 +template<typename ITERATOR> 1.302 +class BaseHexIteratorRangeToIntTraits 1.303 + : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { 1.304 +}; 1.305 + 1.306 +template<typename ITERATOR> 1.307 +class BaseHexIteratorRangeToInt64Traits 1.308 + : public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> { 1.309 +}; 1.310 + 1.311 +template<typename ITERATOR> 1.312 +class BaseHexIteratorRangeToUInt64Traits 1.313 + : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> { 1.314 +}; 1.315 + 1.316 +typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> 1.317 + HexIteratorRangeToIntTraits; 1.318 + 1.319 +typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> 1.320 + HexIteratorRangeToInt64Traits; 1.321 + 1.322 +typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> 1.323 + HexIteratorRangeToUInt64Traits; 1.324 + 1.325 +template<typename STR> 1.326 +bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { 1.327 + DCHECK_EQ(output->size(), 0u); 1.328 + size_t count = input.size(); 1.329 + if (count == 0 || (count % 2) != 0) 1.330 + return false; 1.331 + for (uintptr_t i = 0; i < count / 2; ++i) { 1.332 + uint8 msb = 0; // most significant 4 bits 1.333 + uint8 lsb = 0; // least significant 4 bits 1.334 + if (!CharToDigit<16>(input[i * 2], &msb) || 1.335 + !CharToDigit<16>(input[i * 2 + 1], &lsb)) 1.336 + return false; 1.337 + output->push_back((msb << 4) | lsb); 1.338 + } 1.339 + return true; 1.340 +} 1.341 + 1.342 +template <typename VALUE, int BASE> 1.343 +class StringPieceToNumberTraits 1.344 + : public BaseIteratorRangeToNumberTraits<StringPiece::const_iterator, 1.345 + VALUE, 1.346 + BASE> { 1.347 +}; 1.348 + 1.349 +template <typename VALUE> 1.350 +bool StringToIntImpl(const StringPiece& input, VALUE* output) { 1.351 + return IteratorRangeToNumber<StringPieceToNumberTraits<VALUE, 10> >::Invoke( 1.352 + input.begin(), input.end(), output); 1.353 +} 1.354 + 1.355 +template <typename VALUE, int BASE> 1.356 +class StringPiece16ToNumberTraits 1.357 + : public BaseIteratorRangeToNumberTraits<StringPiece16::const_iterator, 1.358 + VALUE, 1.359 + BASE> { 1.360 +}; 1.361 + 1.362 +template <typename VALUE> 1.363 +bool String16ToIntImpl(const StringPiece16& input, VALUE* output) { 1.364 + return IteratorRangeToNumber<StringPiece16ToNumberTraits<VALUE, 10> >::Invoke( 1.365 + input.begin(), input.end(), output); 1.366 +} 1.367 + 1.368 +} // namespace 1.369 + 1.370 +std::string IntToString(int value) { 1.371 + return IntToStringT<std::string, int, unsigned int, true>:: 1.372 + IntToString(value); 1.373 +} 1.374 + 1.375 +string16 IntToString16(int value) { 1.376 + return IntToStringT<string16, int, unsigned int, true>:: 1.377 + IntToString(value); 1.378 +} 1.379 + 1.380 +std::string UintToString(unsigned int value) { 1.381 + return IntToStringT<std::string, unsigned int, unsigned int, false>:: 1.382 + IntToString(value); 1.383 +} 1.384 + 1.385 +string16 UintToString16(unsigned int value) { 1.386 + return IntToStringT<string16, unsigned int, unsigned int, false>:: 1.387 + IntToString(value); 1.388 +} 1.389 + 1.390 +std::string Int64ToString(int64 value) { 1.391 + return IntToStringT<std::string, int64, uint64, true>:: 1.392 + IntToString(value); 1.393 +} 1.394 + 1.395 +string16 Int64ToString16(int64 value) { 1.396 + return IntToStringT<string16, int64, uint64, true>::IntToString(value); 1.397 +} 1.398 + 1.399 +std::string Uint64ToString(uint64 value) { 1.400 + return IntToStringT<std::string, uint64, uint64, false>:: 1.401 + IntToString(value); 1.402 +} 1.403 + 1.404 +string16 Uint64ToString16(uint64 value) { 1.405 + return IntToStringT<string16, uint64, uint64, false>:: 1.406 + IntToString(value); 1.407 +} 1.408 + 1.409 +std::string DoubleToString(double value) { 1.410 + // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. 1.411 + char buffer[32]; 1.412 + dmg_fp::g_fmt(buffer, value); 1.413 + return std::string(buffer); 1.414 +} 1.415 + 1.416 +bool StringToInt(const StringPiece& input, int* output) { 1.417 + return StringToIntImpl(input, output); 1.418 +} 1.419 + 1.420 +bool StringToInt(const StringPiece16& input, int* output) { 1.421 + return String16ToIntImpl(input, output); 1.422 +} 1.423 + 1.424 +bool StringToUint(const StringPiece& input, unsigned* output) { 1.425 + return StringToIntImpl(input, output); 1.426 +} 1.427 + 1.428 +bool StringToUint(const StringPiece16& input, unsigned* output) { 1.429 + return String16ToIntImpl(input, output); 1.430 +} 1.431 + 1.432 +bool StringToInt64(const StringPiece& input, int64* output) { 1.433 + return StringToIntImpl(input, output); 1.434 +} 1.435 + 1.436 +bool StringToInt64(const StringPiece16& input, int64* output) { 1.437 + return String16ToIntImpl(input, output); 1.438 +} 1.439 + 1.440 +bool StringToUint64(const StringPiece& input, uint64* output) { 1.441 + return StringToIntImpl(input, output); 1.442 +} 1.443 + 1.444 +bool StringToUint64(const StringPiece16& input, uint64* output) { 1.445 + return String16ToIntImpl(input, output); 1.446 +} 1.447 + 1.448 +bool StringToSizeT(const StringPiece& input, size_t* output) { 1.449 + return StringToIntImpl(input, output); 1.450 +} 1.451 + 1.452 +bool StringToSizeT(const StringPiece16& input, size_t* output) { 1.453 + return String16ToIntImpl(input, output); 1.454 +} 1.455 + 1.456 +bool StringToDouble(const std::string& input, double* output) { 1.457 + // Thread-safe? It is on at least Mac, Linux, and Windows. 1.458 + ScopedClearErrno clear_errno; 1.459 + 1.460 + char* endptr = NULL; 1.461 + *output = dmg_fp::strtod(input.c_str(), &endptr); 1.462 + 1.463 + // Cases to return false: 1.464 + // - If errno is ERANGE, there was an overflow or underflow. 1.465 + // - If the input string is empty, there was nothing to parse. 1.466 + // - If endptr does not point to the end of the string, there are either 1.467 + // characters remaining in the string after a parsed number, or the string 1.468 + // does not begin with a parseable number. endptr is compared to the 1.469 + // expected end given the string's stated length to correctly catch cases 1.470 + // where the string contains embedded NUL characters. 1.471 + // - If the first character is a space, there was leading whitespace 1.472 + return errno == 0 && 1.473 + !input.empty() && 1.474 + input.c_str() + input.length() == endptr && 1.475 + !isspace(input[0]); 1.476 +} 1.477 + 1.478 +// Note: if you need to add String16ToDouble, first ask yourself if it's 1.479 +// really necessary. If it is, probably the best implementation here is to 1.480 +// convert to 8-bit and then use the 8-bit version. 1.481 + 1.482 +// Note: if you need to add an iterator range version of StringToDouble, first 1.483 +// ask yourself if it's really necessary. If it is, probably the best 1.484 +// implementation here is to instantiate a string and use the string version. 1.485 + 1.486 +std::string HexEncode(const void* bytes, size_t size) { 1.487 + static const char kHexChars[] = "0123456789ABCDEF"; 1.488 + 1.489 + // Each input byte creates two output hex characters. 1.490 + std::string ret(size * 2, '\0'); 1.491 + 1.492 + for (size_t i = 0; i < size; ++i) { 1.493 + char b = reinterpret_cast<const char*>(bytes)[i]; 1.494 + ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; 1.495 + ret[(i * 2) + 1] = kHexChars[b & 0xf]; 1.496 + } 1.497 + return ret; 1.498 +} 1.499 + 1.500 +bool HexStringToInt(const StringPiece& input, int* output) { 1.501 + return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( 1.502 + input.begin(), input.end(), output); 1.503 +} 1.504 + 1.505 +bool HexStringToInt64(const StringPiece& input, int64* output) { 1.506 + return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( 1.507 + input.begin(), input.end(), output); 1.508 +} 1.509 + 1.510 +bool HexStringToUInt64(const StringPiece& input, uint64* output) { 1.511 + return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( 1.512 + input.begin(), input.end(), output); 1.513 +} 1.514 + 1.515 +bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { 1.516 + return HexStringToBytesT(input, output); 1.517 +} 1.518 + 1.519 +} // namespace base