mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 13:05:53 +00:00
Fix strUnHex parsing of odd-length strings and add unit tests
This commit is contained in:
@@ -60,64 +60,82 @@ std::string strprintf (const char* format, ...)
|
|||||||
|
|
||||||
int charUnHex (char cDigit)
|
int charUnHex (char cDigit)
|
||||||
{
|
{
|
||||||
return cDigit >= '0' && cDigit <= '9'
|
struct HexTab
|
||||||
? cDigit - '0'
|
{
|
||||||
: cDigit >= 'A' && cDigit <= 'F'
|
int hex[256];
|
||||||
? cDigit - 'A' + 10
|
|
||||||
: cDigit >= 'a' && cDigit <= 'f'
|
HexTab ()
|
||||||
? cDigit - 'a' + 10
|
{
|
||||||
: -1;
|
std::fill (std::begin (hex), std::end (hex), -1);
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
hex ['0'+i] = i;
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
hex ['A'+i] = 10 + i;
|
||||||
|
hex ['a'+i] = 10 + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int operator[] (int i) const
|
||||||
|
{
|
||||||
|
return hex[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static HexTab xtab;
|
||||||
|
|
||||||
|
return xtab[cDigit];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NIKB NOTE: This function is only used by strUnHex (const std::string& strSrc)
|
||||||
|
// which results in a pointless copy from std::string into std::vector. Should
|
||||||
|
// we just scrap this function altogether?
|
||||||
int strUnHex (std::string& strDst, const std::string& strSrc)
|
int strUnHex (std::string& strDst, const std::string& strSrc)
|
||||||
{
|
{
|
||||||
int iBytes = (strSrc.size () + 1) / 2;
|
std::string tmp;
|
||||||
|
|
||||||
strDst.resize (iBytes);
|
tmp.reserve ((strSrc.size () + 1) / 2);
|
||||||
|
|
||||||
const char* pSrc = &strSrc[0];
|
auto iter = strSrc.cbegin ();
|
||||||
char* pDst = &strDst[0];
|
|
||||||
|
|
||||||
if (strSrc.size () & 1)
|
if (strSrc.size () & 1)
|
||||||
{
|
{
|
||||||
int c = charUnHex (*pSrc++);
|
int c = charUnHex (*iter);
|
||||||
|
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
{
|
return -1;
|
||||||
iBytes = -1;
|
|
||||||
}
|
tmp.push_back(c);
|
||||||
else
|
++iter;
|
||||||
{
|
|
||||||
*pDst++ = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; iBytes >= 0 && i != iBytes; i++)
|
while (iter != strSrc.cend ())
|
||||||
{
|
{
|
||||||
int cHigh = charUnHex (*pSrc++);
|
int cHigh = charUnHex (*iter);
|
||||||
int cLow = charUnHex (*pSrc++);
|
++iter;
|
||||||
|
|
||||||
if (cHigh < 0 || cLow < 0)
|
if (cHigh < 0)
|
||||||
{
|
return -1;
|
||||||
iBytes = -1;
|
|
||||||
}
|
int cLow = charUnHex (*iter);
|
||||||
else
|
++iter;
|
||||||
{
|
|
||||||
strDst[i] = (cHigh << 4) | cLow;
|
if (cLow < 0)
|
||||||
}
|
return -1;
|
||||||
|
|
||||||
|
tmp.push_back (static_cast<char>((cHigh << 4) | cLow));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iBytes < 0)
|
strDst = std::move(tmp);
|
||||||
strDst.clear ();
|
|
||||||
|
|
||||||
return iBytes;
|
return strDst.size ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Blob strUnHex (const std::string& strSrc)
|
Blob strUnHex (const std::string& strSrc)
|
||||||
{
|
{
|
||||||
std::string strTmp;
|
std::string strTmp;
|
||||||
|
|
||||||
strUnHex (strTmp, strSrc);
|
if (strUnHex (strTmp, strSrc) == -1)
|
||||||
|
return Blob ();
|
||||||
|
|
||||||
return strCopy (strTmp);
|
return strCopy (strTmp);
|
||||||
}
|
}
|
||||||
@@ -315,11 +333,47 @@ StringPairArray parseDelimitedKeyValueString (String parameters, beast_wchar del
|
|||||||
class StringUtilitiesTests : public UnitTest
|
class StringUtilitiesTests : public UnitTest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StringUtilitiesTests () : UnitTest ("StringUtilities", "ripple")
|
void testUnHexSuccess (std::string strIn, std::string strExpected)
|
||||||
{
|
{
|
||||||
|
std::string strOut;
|
||||||
|
|
||||||
|
expect (strUnHex (strOut, strIn) == strExpected.length (),
|
||||||
|
"strUnHex: parsing correct input failed");
|
||||||
|
|
||||||
|
expect (strOut == strExpected,
|
||||||
|
"strUnHex: parsing doesn't produce expected result");
|
||||||
}
|
}
|
||||||
|
|
||||||
void runTest ()
|
void testUnHexFailure (std::string strIn)
|
||||||
|
{
|
||||||
|
std::string strOut;
|
||||||
|
|
||||||
|
expect (strUnHex (strOut, strIn) == -1,
|
||||||
|
"strUnHex: parsing incorrect input succeeded");
|
||||||
|
|
||||||
|
expect (strOut.empty (),
|
||||||
|
"strUnHex: parsing incorrect input returned data");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testUnHex ()
|
||||||
|
{
|
||||||
|
beginTestCase ("strUnHex");
|
||||||
|
|
||||||
|
testUnHexSuccess ("526970706c6544", "RippleD");
|
||||||
|
testUnHexSuccess ("A", "\n");
|
||||||
|
testUnHexSuccess ("0A", "\n");
|
||||||
|
testUnHexSuccess ("D0A", "\r\n");
|
||||||
|
testUnHexSuccess ("0D0A", "\r\n");
|
||||||
|
testUnHexSuccess ("200D0A", " \r\n");
|
||||||
|
testUnHexSuccess ("282A2B2C2D2E2F29", "(*+,-./)");
|
||||||
|
|
||||||
|
// Check for things which contain some or only invalid characters
|
||||||
|
testUnHexFailure ("123X");
|
||||||
|
testUnHexFailure ("V");
|
||||||
|
testUnHexFailure ("XRP");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testParseUrl ()
|
||||||
{
|
{
|
||||||
beginTestCase ("parseUrl");
|
beginTestCase ("parseUrl");
|
||||||
|
|
||||||
@@ -364,6 +418,17 @@ public:
|
|||||||
unexpected (strPath != "/path",
|
unexpected (strPath != "/path",
|
||||||
"parseUrl: Mixed://domain/path path failed");
|
"parseUrl: Mixed://domain/path path failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runTest ()
|
||||||
|
{
|
||||||
|
testParseUrl ();
|
||||||
|
|
||||||
|
testUnHex ();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringUtilitiesTests () : UnitTest ("StringUtilities", "ripple")
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static StringUtilitiesTests stringUtilitiesTests;
|
static StringUtilitiesTests stringUtilitiesTests;
|
||||||
|
|||||||
Reference in New Issue
Block a user