From 24ea1ab035aaa9186411baca5acd18bcc81986ce Mon Sep 17 00:00:00 2001 From: Nik Bougalis Date: Wed, 27 May 2015 11:22:29 -0700 Subject: [PATCH] Parse pathsets when accounts are specified in hex --- src/ripple/basics/base_uint.h | 44 +++++++++++++------- src/ripple/protocol/impl/STParsedJSON.cpp | 49 +++++++---------------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/src/ripple/basics/base_uint.h b/src/ripple/basics/base_uint.h index f0bdb981fb..bb6dcfaf13 100644 --- a/src/ripple/basics/base_uint.h +++ b/src/ripple/basics/base_uint.h @@ -306,31 +306,45 @@ public: h(a.pn, sizeof(a.pn)); } + /** Parse a hex string into a base_uint + The string must contain exactly bytes * 2 hex characters and must not + have any leading or trailing whitespace. + */ bool SetHexExact (const char* psz) { - // must be precisely the correct number of hex digits unsigned char* pOut = begin (); for (int i = 0; i < sizeof (pn); ++i) { - auto cHigh = charUnHex(*psz++); - auto cLow = charUnHex(*psz++); - - if (cHigh == -1 || cLow == -1) + auto hi = charUnHex(*psz++); + if (hi == -1) return false; - *pOut++ = (cHigh << 4) | cLow; + auto lo = charUnHex (*psz++); + if (lo == -1) + return false; + + *pOut++ = (hi << 4) | lo; } - assert (*psz == 0); - assert (pOut == end ()); - - return true; + // We've consumed exactly as many bytes as we needed at this point + // so we should be at the end of the string. + return (*psz == 0); } - // Allow leading whitespace. - // Allow leading "0x". - // To be valid must be '\0' terminated. + /** Parse a hex string into a base_uint + The input can be: + - shorter than the full hex representation by not including leading + zeroes. + - longer than the full hex representation in which case leading + bytes are discarded. + + When finished parsing, the string must be fully consumed with only a + null terminator remaining. + + When bStrict is false, the parsing is done in non-strict mode, and, if + present, leading whitespace and the 0x prefix will be skipped. + */ bool SetHex (const char* psz, bool bStrict = false) { // skip leading spaces @@ -381,9 +395,9 @@ public: return SetHex (str.c_str (), bStrict); } - void SetHexExact (std::string const& str) + bool SetHexExact (std::string const& str) { - SetHexExact (str.c_str ()); + return SetHexExact (str.c_str ()); } unsigned int size () const diff --git a/src/ripple/protocol/impl/STParsedJSON.cpp b/src/ripple/protocol/impl/STParsedJSON.cpp index a94b75497e..4d9f60eb5e 100644 --- a/src/ripple/protocol/impl/STParsedJSON.cpp +++ b/src/ripple/protocol/impl/STParsedJSON.cpp @@ -540,20 +540,16 @@ static boost::optional parseLeaf ( return ret; } - std::string const strValue (account.asString ()); - - if (value.size () == 40) // 160-bit hex account value - uAccount.SetHex (strValue); - + // If we have what looks like a 160-bit hex value, we + // set it, otherwise, we assume it's an AccountID + if (!uAccount.SetHexExact (account.asString ())) { RippleAddress a; - - if (! a.setAccountID (strValue)) + if (!a.setAccountID (account.asString ())) { error = invalid_data (element_name, "account"); return ret; } - uAccount = a.getAccountID (); } } @@ -569,14 +565,13 @@ static boost::optional parseLeaf ( hasCurrency = true; - if (currency.asString ().size () == 40) + if (!uCurrency.SetHexExact (currency.asString ())) { - uCurrency.SetHex (currency.asString ()); - } - else if (!to_currency (uCurrency, currency.asString ())) - { - error = invalid_data (element_name, "currency"); - return ret; + if (!to_currency (uCurrency, currency.asString ())) + { + error = invalid_data (element_name, "currency"); + return ret; + } } } @@ -589,20 +584,14 @@ static boost::optional parseLeaf ( return ret; } - if (issuer.asString ().size () == 40) - { - uIssuer.SetHex (issuer.asString ()); - } - else + if (!uIssuer.SetHexExact (issuer.asString ())) { RippleAddress a; - if (!a.setAccountID (issuer.asString ())) { error = invalid_data (element_name, "issuer"); return ret; } - uIssuer = a.getAccountID (); } } @@ -634,26 +623,18 @@ static boost::optional parseLeaf ( try { - if (value.size () == 40) // 160-bit hex account value + Account account; + if (!account.SetHexExact (strValue)) { - Account account; - account.SetHex (strValue); - ret = detail::make_stvar (field, account); - } - else - { - // ripple address RippleAddress a; - if (!a.setAccountID (strValue)) { error = invalid_data (json_name, fieldName); return ret; } - - ret = - detail::make_stvar (field, a.getAccountID ()); + account.copyFrom (a.getAccountID ()); } + ret = detail::make_stvar (field, account); } catch (...) {