diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index cf04a6d45c..9f9f746370 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -490,6 +490,10 @@ true true + + true + true + true true @@ -510,18 +514,10 @@ true true - - true - true - true true - - true - true - true @@ -1834,7 +1830,7 @@ - + @@ -2042,9 +2038,7 @@ - - @@ -2154,7 +2148,6 @@ - diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 28ca11e3c7..8c9fa9d1b3 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -1008,12 +1008,6 @@ [1] Ripple\sslutil\impl - - [1] Ripple\types\impl - - - [1] Ripple\types\impl - [1] Ripple\types\impl @@ -1743,6 +1737,9 @@ [1] Ripple\common\tests + + [1] Ripple\types\impl + @@ -2570,15 +2567,9 @@ [1] Ripple\sslutil\api - - [1] Ripple\types\api - [1] Ripple\types\api - - [1] Ripple\types\api - [1] Ripple\types\api @@ -3254,9 +3245,6 @@ [2] Old Ripple\ripple_app\transactors - - [2] Old Ripple\ripple_app\transactors - [2] Old Ripple\ripple_app\transactors @@ -3339,9 +3327,6 @@ [2] Old Ripple\ripple_overlay\api - - [1] Ripple\common - [2] Old Ripple\ripple_rpc\impl @@ -3378,6 +3363,9 @@ [1] Ripple\common + + [1] Ripple\common + diff --git a/src/beast/modules/beast_core/text/LexicalCast.cpp b/src/beast/modules/beast_core/text/LexicalCast.cpp index f3c2e723ef..09005298f9 100644 --- a/src/beast/modules/beast_core/text/LexicalCast.cpp +++ b/src/beast/modules/beast_core/text/LexicalCast.cpp @@ -21,43 +21,6 @@ namespace beast { -unsigned char const LexicalCastUtilities::s_digitTable [256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF - 0x07 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x08 - 0x0F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10 - 0x17 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x18 - 0x1F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x20 - 0x27 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x28 - 0x2F - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37 - 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x38 - 0x3F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x40 - 0x47 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x48 - 0x4F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x50 - 0x57 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x58 - 0x5F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x60 - 0x67 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x68 - 0x6F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x70 - 0x77 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x78 - 0x7F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x80 - 0x87 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x88 - 0x8F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x90 - 0x97 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x98 - 0x9F - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA0 - 0xA7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA8 - 0xAF - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB0 - 0xB7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB8 - 0xBF - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC0 - 0xC7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC8 - 0xCF - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD0 - 0xD7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD8 - 0xDF - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE0 - 0xE7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE8 - 0xEF - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xF0 - 0xF7 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 0xF8 - 0xFF -}; - -//------------------------------------------------------------------------------ - class LexicalCast_test : public unit_test::suite { public: @@ -70,7 +33,7 @@ public: template void testInteger (IntType in) { - String s; + std::string s; IntType out (in+1); expect (lexicalCastChecked (s, in)); @@ -105,6 +68,20 @@ public: } } + void testPathologies() + { + testcase("pathologies"); + try + { + lexicalCastThrow("\xef\xbc\x91\xef\xbc\x90"); // utf-8 encoded + fail("Should throw"); + } + catch(BadLexicalCast const&) + { + pass(); + } + } + void run() { std::int64_t const seedValue = 50; @@ -119,6 +96,8 @@ public: testIntegers (r); testIntegers (r); testIntegers (r); + + testPathologies(); } }; diff --git a/src/beast/modules/beast_core/text/LexicalCast.h b/src/beast/modules/beast_core/text/LexicalCast.h index 689db187bb..9315816cee 100644 --- a/src/beast/modules/beast_core/text/LexicalCast.h +++ b/src/beast/modules/beast_core/text/LexicalCast.h @@ -20,221 +20,144 @@ #ifndef BEAST_LEXICALCAST_H_INCLUDED #define BEAST_LEXICALCAST_H_INCLUDED -namespace beast +#include +#include "../../../beast/cxx14/type_traits.h" // + +#include +#include +#include +#include + +namespace beast { + +namespace detail { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4800) +#pragma warning(disable: 4804) +#endif + +template +bool +parseSigned (IntType& result, char const* begin, char const* end) { + static_assert(std::is_signed::value, ""); + char* ptr; + auto errno_save = errno; + errno = 0; + long long r = std::strtoll(begin, &ptr, 10); + std::swap(errno, errno_save); + errno_save = ptr != end; + if (errno_save == 0) + { + if (std::numeric_limits::min() <= r && + r <= std::numeric_limits::max()) + result = static_cast(r); + else + errno_save = 1; + } + return errno_save == 0; +} -// Base class with utility functions -struct LexicalCastUtilities +template +bool +parseUnsigned (UIntType& result, char const* begin, char const* end) { - static unsigned char const s_digitTable [256]; - - // strict string to integer parser - template - static inline bool parseSigned (IntType& result, InputIterator begin, InputIterator end) + static_assert(std::is_unsigned::value, ""); + char* ptr; + auto errno_save = errno; + errno = 0; + unsigned long long r = std::strtoull(begin, &ptr, 10); + std::swap(errno, errno_save); + errno_save = ptr != end; + if (errno_save == 0) { - if (0 == std::distance (begin, end)) - return false; - - std::uint64_t accum = 0; - InputIterator it = begin; - - // process sign - bool negative = false; - if ('+' == *it) - { - ++it; - } - else if ('-' == *it) - { - ++it; - negative = true; - } - if (end == it) - return false; - - // calc max of abs value - std::uint64_t max; - if (negative) - max = static_cast ( - -(static_cast (std::numeric_limits ::min ()))); + if (r <= std::numeric_limits::max()) + result = static_cast(r); else - max = std::numeric_limits ::max (); - - // process digits - while (end != it) - { - std::uint64_t const digit = static_cast ( - s_digitTable [static_cast (*it++)]); - - if (0xFF == digit) - return false; - - std::uint64_t const overflow = (max - digit) / 10; - - if (accum > overflow) - return false; - - accum = (10 * accum) + digit; - } - - if (negative) - { - result = -static_cast (accum); - } - else - { - result = static_cast (accum); - } - - return true; + errno_save = 1; } - - template - static inline bool parseUnsigned (IntType& result, InputIterator begin, InputIterator end) - { - if (0 == std::distance (begin, end)) - return false; - - std::uint64_t accum = 0; - InputIterator it = begin; - std::uint64_t const max = std::numeric_limits ::max (); - - // process digits - while (end != it) - { - std::uint64_t const digit = static_cast ( - s_digitTable [static_cast (*it++)]); - - if (0xFF == digit) - return false; - - std::uint64_t const overflow = (max - digit) / 10; - - if (accum > overflow) - return false; - - accum = (10 * accum) + digit; - } - - result = static_cast (accum); - - return true; - } -}; + return errno_save == 0; +} //------------------------------------------------------------------------------ -/** This is thrown when a conversion is not possible. - Only used in the throw variants of lexicalCast. -*/ -struct BadLexicalCast : public std::bad_cast -{ -}; - // These specializatons get called by the non-member functions to do the work template struct LexicalCast; -// conversion to String -template -struct LexicalCast -{ - bool operator() (String& out, int in) const { out = String (in); return true; } - bool operator() (String& out, unsigned int in) const { out = String (in); return true; } - bool operator() (String& out, short in) const { out = String (in); return true; } - bool operator() (String& out, unsigned short in) const { out = String (in); return true; } - bool operator() (String& out, std::int64_t in) const { out = String (in); return true; } - bool operator() (String& out, std::uint64_t in) const { out = String (in); return true; } - bool operator() (String& out, float in) const { out = String (in); return true; } - bool operator() (String& out, double in) const { out = String (in); return true; } -}; - -// Parse String to number -template -struct LexicalCast -{ - bool operator() (int& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseSigned (out, s.begin (), s.end ()); } - bool operator() (short& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseSigned (out, s.begin (), s.end ()); } - bool operator() (std::int64_t& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseSigned (out, s.begin (), s.end ()); } - bool operator() (unsigned int& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseUnsigned (out, s.begin (), s.end ()); } - bool operator() (unsigned short& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseUnsigned (out, s.begin (), s.end ()); } - bool operator() (std::uint64_t& out, String const& in) const { std::string const& s (in.toStdString ()); return LexicalCastUtilities::parseUnsigned (out, s.begin (), s.end ()); } - bool operator() (float& out, String const& in) const { bassertfalse; return false; /* UNIMPLEMENTED! */ } - bool operator() (double& out, String const& in) const { bassertfalse; return false; /* UNIMPLEMENTED! */ } - - bool operator () (bool& out, String const& in) const - { - // boost::lexical_cast is very strict, it - // throws on anything but "1" or "0" - // - if (in == "1") - { - out = true; - return true; - } - else if (in == "0") - { - out = false; - return true; - } - - return false; - } -}; - -//------------------------------------------------------------------------------ - -// Conversion to std::string +// conversion to std::string template struct LexicalCast { - bool operator() (std::string& out, In in) const - { - String s; - - if (LexicalCast () (s, in)) - { - out = s.toStdString (); - return true; - } - - return false; - } + bool operator() (std::string& out, short in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, int in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, long in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, long long in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, unsigned short in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, unsigned int in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, unsigned long in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, unsigned long long in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, float in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, double in) { out = std::to_string(in); return true; } + bool operator() (std::string& out, long double in) { out = std::to_string(in); return true; } }; -// Conversion from std::string +// Parse std::string to number template struct LexicalCast { - bool operator() (Out& out, std::string const& in) const - { - Out result; - - if (LexicalCast () (result, String (in.c_str ()))) - { - out = result; - return true; - } - - return false; - } + bool operator() (short& out, std::string const& in) const { return parseSigned (out, in.data(), in.data()+in.size()); } + bool operator() (int& out, std::string const& in) const { return parseSigned (out, in.data(), in.data()+in.size()); } + bool operator() (long& out, std::string const& in) const { return parseSigned (out, in.data(), in.data()+in.size()); } + bool operator() (long long& out, std::string const& in) const { return parseSigned (out, in.data(), in.data()+in.size()); } + bool operator() (unsigned short& out, std::string const& in) const { return parseUnsigned (out, in.data(), in.data()+in.size()); } + bool operator() (unsigned int& out, std::string const& in) const { return parseUnsigned (out, in.data(), in.data()+in.size()); } + bool operator() (unsigned long& out, std::string const& in) const { return parseUnsigned (out, in.data(), in.data()+in.size()); } + bool operator() (unsigned long long& out, std::string const& in) const { return parseUnsigned (out, in.data(), in.data()+in.size()); } + bool operator() (float& out, std::string const& in) const { bassertfalse; return false; /* UNIMPLEMENTED! */ } + bool operator() (double& out, std::string const& in) const { bassertfalse; return false; /* UNIMPLEMENTED! */ } + bool operator() (long double& out, std::string const& in) const { bassertfalse; return false; /* UNIMPLEMENTED! */ } +#if 0 + bool operator() (bool& out, std::string const& in) const; +#else + bool operator() (bool& out, std::string const& in) const { return parseUnsigned (out, in.data(), in.data()+in.size()); } +#endif }; +#if 0 +template +bool +LexicalCast ::operator() (bool& out, std::string const& in) const +{ + // boost::lexical_cast is very strict, it + // throws on anything but "1" or "0" + // + if (in == "1") + { + out = true; + return true; + } + else if (in == "0") + { + out = false; + return true; + } + + return false; +} +#endif + +//------------------------------------------------------------------------------ + // Conversion from null terminated char const* template struct LexicalCast { bool operator() (Out& out, char const* in) const { - Out result; - - if (LexicalCast () (result, String (in))) - { - out = result; - return true; - } - - return false; + return LexicalCast ()(out, in); } }; @@ -257,15 +180,28 @@ struct LexicalCast } }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +} // detail + //------------------------------------------------------------------------------ +/** Thrown when a conversion is not possible with LexicalCast. + Only used in the throw variants of lexicalCast. +*/ +struct BadLexicalCast : public std::bad_cast +{ +}; + /** Intelligently convert from one type to another. @return `false` if there was a parsing or range error */ template bool lexicalCastChecked (Out& out, In in) { - return LexicalCast () (out, in); + return detail::LexicalCast () (out, in); } /** Convert from one type to another, throw on error @@ -283,8 +219,6 @@ Out lexicalCastThrow (In in) return out; throw BadLexicalCast (); - - return Out (); } /** Convert from one type to another.