Skip to content

Commit 15db77f

Browse files
Don't rely on locale dependent functions in base_blob<BITS>::SetHex(...) (uint256), DecodeBase58(...), ParseMoney(...) and ParseHex(...)
1 parent f4e4ea1 commit 15db77f

File tree

6 files changed

+25
-13
lines changed

6 files changed

+25
-13
lines changed

src/base58.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <hash.h>
88
#include <uint256.h>
9+
#include <utilstrencodings.h>
910

1011
#include <assert.h>
1112
#include <string.h>
@@ -34,7 +35,7 @@ static const int8_t mapBase58[256] = {
3435
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
3536
{
3637
// Skip leading spaces.
37-
while (*psz && isspace(*psz))
38+
while (*psz && IsSpace(*psz))
3839
psz++;
3940
// Skip and count leading '1's.
4041
int zeroes = 0;
@@ -48,7 +49,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
4849
std::vector<unsigned char> b256(size);
4950
// Process the characters.
5051
static_assert(sizeof(mapBase58)/sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
51-
while (*psz && !isspace(*psz)) {
52+
while (*psz && !IsSpace(*psz)) {
5253
// Decode base58 character
5354
int carry = mapBase58[(uint8_t)*psz];
5455
if (carry == -1) // Invalid b58 character
@@ -64,7 +65,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
6465
psz++;
6566
}
6667
// Skip trailing spaces.
67-
while (isspace(*psz))
68+
while (IsSpace(*psz))
6869
psz++;
6970
if (*psz != 0)
7071
return false;

src/uint256.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ void base_blob<BITS>::SetHex(const char* psz)
2929
memset(data, 0, sizeof(data));
3030

3131
// skip leading spaces
32-
while (isspace(*psz))
32+
while (IsSpace(*psz))
3333
psz++;
3434

3535
// skip 0x

src/utilmoneystr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
4141
std::string strWhole;
4242
int64_t nUnits = 0;
4343
const char* p = pszIn;
44-
while (isspace(*p))
44+
while (IsSpace(*p))
4545
p++;
4646
for (; *p; p++)
4747
{
@@ -56,14 +56,14 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
5656
}
5757
break;
5858
}
59-
if (isspace(*p))
59+
if (IsSpace(*p))
6060
break;
6161
if (!isdigit(*p))
6262
return false;
6363
strWhole.insert(strWhole.end(), *p);
6464
}
6565
for (; *p; p++)
66-
if (!isspace(*p))
66+
if (!IsSpace(*p))
6767
return false;
6868
if (strWhole.size() > 10) // guard against 63 bit overflow
6969
return false;

src/utilstrencodings.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ std::vector<unsigned char> ParseHex(const char* psz)
8585
std::vector<unsigned char> vch;
8686
while (true)
8787
{
88-
while (isspace(*psz))
88+
while (IsSpace(*psz))
8989
psz++;
9090
signed char c = HexDigit(*psz++);
9191
if (c == (signed char)-1)
@@ -266,7 +266,7 @@ static bool ParsePrechecks(const std::string& str)
266266
{
267267
if (str.empty()) // No empty string allowed
268268
return false;
269-
if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
269+
if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
270270
return false;
271271
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
272272
return false;

src/utilstrencodings.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,21 @@ constexpr bool IsDigit(char c)
7171
return c >= '0' && c <= '9';
7272
}
7373

74+
/**
75+
* Tests if the given character is a whitespace character. The whitespace characters
76+
* are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
77+
* tab ('\t'), and vertical tab ('\v').
78+
*
79+
* This function is locale independent. Under the C locale this function gives the
80+
* same result as std::isspace.
81+
*
82+
* @param[in] c character to test
83+
* @return true if the argument is a whitespace character; otherwise false
84+
*/
85+
constexpr inline bool IsSpace(char c) noexcept {
86+
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
87+
}
88+
7489
/**
7590
* Convert string to signed 32-bit integer with strict parse error feedback.
7691
* @returns true if the entire string could be parsed as valid integer,

test/lint/lint-locale-dependence.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
export LC_ALL=C
44
KNOWN_VIOLATIONS=(
5-
"src/base58.cpp:.*isspace"
65
"src/bitcoin-tx.cpp.*stoul"
76
"src/bitcoin-tx.cpp.*trim_right"
87
"src/bitcoin-tx.cpp:.*atoi"
@@ -18,15 +17,12 @@ KNOWN_VIOLATIONS=(
1817
"src/test/getarg_tests.cpp.*split"
1918
"src/torcontrol.cpp:.*atoi"
2019
"src/torcontrol.cpp:.*strtol"
21-
"src/uint256.cpp:.*isspace"
2220
"src/uint256.cpp:.*tolower"
2321
"src/util.cpp:.*atoi"
2422
"src/util.cpp:.*fprintf"
2523
"src/util.cpp:.*tolower"
2624
"src/utilmoneystr.cpp:.*isdigit"
27-
"src/utilmoneystr.cpp:.*isspace"
2825
"src/utilstrencodings.cpp:.*atoi"
29-
"src/utilstrencodings.cpp:.*isspace"
3026
"src/utilstrencodings.cpp:.*strtol"
3127
"src/utilstrencodings.cpp:.*strtoll"
3228
"src/utilstrencodings.cpp:.*strtoul"

0 commit comments

Comments
 (0)