mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 15:41:44 +02:00
epee, common: pass unsigned char to <cctype> functions
The <cctype> functions require their argument to be representable as unsigned char or to equal EOF. char is signed on the platforms Monero targets, so every byte >= 0x80 reaches them negative, which is undefined behaviour. All six call sites take bytes that come from outside the process: hex_to_dec_2bytes() percent-escapes in a payment URI http_client.h the status line of an HTTP response updates.cpp the hash field of a DNS update record glibc and the macOS libc happen to tolerate -128..-1 because their tables carry padding below zero, so this is quiet in practice on those, but it is still out of contract and other libcs index without that cushion. Cast to unsigned char at each call. The conversion is behaviour-preserving for the ASCII these actually test: for a byte such as 0xC3, toupper() returns it unchanged in the C locale, it narrows back to char, memchr() misses it in the hex table, and hex_to_dec_2bytes() falls through to the existing literal "%XY" output exactly as before. epee::misc_utils::parse::isdigit/isalpha/isspace are separate char-taking helpers and are already well defined, so they are untouched, as is is_base64(), which already takes unsigned char.
This commit is contained in:
@@ -662,14 +662,14 @@ namespace net_utils
|
||||
ptr = end + 1;
|
||||
CHECK_AND_ASSERT_MES(epee::misc_utils::parse::isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
|
||||
ul = strtoul(ptr, &end, 10);
|
||||
CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
|
||||
CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(static_cast<unsigned char>(*end)), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr);
|
||||
m_response_info.m_http_ver_lo = ul;
|
||||
ptr = end + 1;
|
||||
while (isblank(*ptr))
|
||||
while (isblank(static_cast<unsigned char>(*ptr)))
|
||||
++ptr;
|
||||
CHECK_AND_ASSERT_MES(epee::misc_utils::parse::isdigit(*ptr), false, "Invalid first response line: " + m_header_cache);
|
||||
ul = strtoul(ptr, &end, 10);
|
||||
CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache);
|
||||
CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(static_cast<unsigned char>(*end)), false, "Invalid first response line: " + m_header_cache);
|
||||
m_response_info.m_response_code = ul;
|
||||
ptr = end;
|
||||
// ignore the optional text, till the end
|
||||
|
||||
@@ -65,8 +65,8 @@ namespace net_utils
|
||||
std::string hex_to_dec_2bytes(const char *s)
|
||||
{
|
||||
const char *hex = get_hex_vals();
|
||||
int i0 = get_index(hex, toupper(s[0]));
|
||||
int i1 = get_index(hex, toupper(s[1]));
|
||||
int i0 = get_index(hex, toupper(static_cast<unsigned char>(s[0])));
|
||||
int i1 = get_index(hex, toupper(static_cast<unsigned char>(s[1])));
|
||||
if (i0 < 0 || i1 < 0)
|
||||
return std::string("%") + std::string(1, s[0]) + std::string(1, s[1]);
|
||||
return std::string(1, i0 * 16 | i1);
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace tools
|
||||
|
||||
bool alnum = true;
|
||||
for (auto c: fields[3])
|
||||
if (!isalnum(c))
|
||||
if (!isalnum(static_cast<unsigned char>(c)))
|
||||
alnum = false;
|
||||
if (fields[3].size() != 64 && !alnum)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user