diff options
author | MarcoFalke <falke.marco@gmail.com> | 2018-10-28 06:48:46 -0400 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2018-10-28 06:49:07 -0400 |
commit | f1e2f2a85962c1664e4e55471061af0eaa798d40 (patch) | |
tree | 5d4c9a91453db71570998a96385b4e9090f1e14c | |
parent | 643b25d093a959b2176a7ace810a7d44267ca2e9 (diff) | |
parent | 15db77f4dd7f1a7963398f1576580b577a1697bc (diff) |
Merge #14585: refactor: remove usage of locale dependent std::isspace
15db77f4dd Don't rely on locale dependent functions in base_blob<BITS>::SetHex(...) (uint256), DecodeBase58(...), ParseMoney(...) and ParseHex(...) (practicalswift)
Pull request description:
Don't rely on locale dependent function `std::isspace` in `base_blob<BITS>::SetHex(...)` (uint256), `DecodeBase58(...)`, `ParseMoney(...)` and `ParseHex(...)`.
Rationale:
```
$ uname -s
Darwin
$ cat poc.cpp
#include <iostream>
#include <locale>
int main(void) {
setlocale(LC_ALL, "");
std::cout << std::isspace(133) << ' ' << std::isspace(154) << ' ' << std::isspace(160);
std::cout << '\n';
}
$ clang++ -o poc poc.cpp
$ ./poc
1 0 1
$ LC_ALL=en_US ./poc
1 0 1
$ LC_ALL=C ./poc
0 0 0
$ LC_ALL=ru_RU.KOI8-R ./poc # an "interesting" locale
0 1 0
```
Tree-SHA512: 4eafb267342b8a777da6cca07c353afd1f90f3fc1d91e01f526f1b384a2b97c1da25b7bd7dfc300655182a4eaec6a4bea855a45723ab53c750a734b60e1e3c9f
-rw-r--r-- | src/base58.cpp | 7 | ||||
-rw-r--r-- | src/uint256.cpp | 2 | ||||
-rw-r--r-- | src/utilmoneystr.cpp | 6 | ||||
-rw-r--r-- | src/utilstrencodings.cpp | 4 | ||||
-rw-r--r-- | src/utilstrencodings.h | 15 | ||||
-rwxr-xr-x | test/lint/lint-locale-dependence.sh | 4 |
6 files changed, 25 insertions, 13 deletions
diff --git a/src/base58.cpp b/src/base58.cpp index 7020c24055..eac763394b 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -6,6 +6,7 @@ #include <hash.h> #include <uint256.h> +#include <utilstrencodings.h> #include <assert.h> #include <string.h> @@ -34,7 +35,7 @@ static const int8_t mapBase58[256] = { bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) { // Skip leading spaces. - while (*psz && isspace(*psz)) + while (*psz && IsSpace(*psz)) psz++; // Skip and count leading '1's. int zeroes = 0; @@ -48,7 +49,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) std::vector<unsigned char> b256(size); // Process the characters. static_assert(sizeof(mapBase58)/sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of range - while (*psz && !isspace(*psz)) { + while (*psz && !IsSpace(*psz)) { // Decode base58 character int carry = mapBase58[(uint8_t)*psz]; if (carry == -1) // Invalid b58 character @@ -64,7 +65,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) psz++; } // Skip trailing spaces. - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; if (*psz != 0) return false; diff --git a/src/uint256.cpp b/src/uint256.cpp index e513dc1de7..e940f90cf0 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -29,7 +29,7 @@ void base_blob<BITS>::SetHex(const char* psz) memset(data, 0, sizeof(data)); // skip leading spaces - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; // skip 0x diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index 326ef9b27a..7bae161a1d 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -41,7 +41,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet) std::string strWhole; int64_t nUnits = 0; const char* p = pszIn; - while (isspace(*p)) + while (IsSpace(*p)) p++; for (; *p; p++) { @@ -56,14 +56,14 @@ bool ParseMoney(const char* pszIn, CAmount& nRet) } break; } - if (isspace(*p)) + if (IsSpace(*p)) break; if (!isdigit(*p)) return false; strWhole.insert(strWhole.end(), *p); } for (; *p; p++) - if (!isspace(*p)) + if (!IsSpace(*p)) return false; if (strWhole.size() > 10) // guard against 63 bit overflow return false; diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 4940267bae..a1700d2514 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -85,7 +85,7 @@ std::vector<unsigned char> ParseHex(const char* psz) std::vector<unsigned char> vch; while (true) { - while (isspace(*psz)) + while (IsSpace(*psz)) psz++; signed char c = HexDigit(*psz++); if (c == (signed char)-1) @@ -266,7 +266,7 @@ static bool ParsePrechecks(const std::string& str) { if (str.empty()) // No empty string allowed return false; - if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed + if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed return false; if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed return false; diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 846a3917a2..1610c8c268 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -72,6 +72,21 @@ constexpr bool IsDigit(char c) } /** + * Tests if the given character is a whitespace character. The whitespace characters + * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal + * tab ('\t'), and vertical tab ('\v'). + * + * This function is locale independent. Under the C locale this function gives the + * same result as std::isspace. + * + * @param[in] c character to test + * @return true if the argument is a whitespace character; otherwise false + */ +constexpr inline bool IsSpace(char c) noexcept { + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; +} + +/** * Convert string to signed 32-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh index cbee437c91..216cabbce9 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -2,7 +2,6 @@ export LC_ALL=C KNOWN_VIOLATIONS=( - "src/base58.cpp:.*isspace" "src/bitcoin-tx.cpp.*stoul" "src/bitcoin-tx.cpp.*trim_right" "src/bitcoin-tx.cpp:.*atoi" @@ -18,15 +17,12 @@ KNOWN_VIOLATIONS=( "src/test/getarg_tests.cpp.*split" "src/torcontrol.cpp:.*atoi" "src/torcontrol.cpp:.*strtol" - "src/uint256.cpp:.*isspace" "src/uint256.cpp:.*tolower" "src/util.cpp:.*atoi" "src/util.cpp:.*fprintf" "src/util.cpp:.*tolower" "src/utilmoneystr.cpp:.*isdigit" - "src/utilmoneystr.cpp:.*isspace" "src/utilstrencodings.cpp:.*atoi" - "src/utilstrencodings.cpp:.*isspace" "src/utilstrencodings.cpp:.*strtol" "src/utilstrencodings.cpp:.*strtoll" "src/utilstrencodings.cpp:.*strtoul" |