From 7e98a3c642222edc0813ced945d4b6e548cb8ca8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 4 Jun 2015 12:03:09 +0200 Subject: util: Add ParseInt64 and ParseDouble functions Strict parsing functions for other numeric types. - ParseInt64 analogous to ParseInt32, but for 64-bit values. - ParseDouble for doubles. - Make all three Parse* functions more strict (e.g. reject whitespace on the inside) Also add tests. --- src/utilstrencodings.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'src/utilstrencodings.cpp') diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index c15bddc6fb..b10f3c5903 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -416,12 +416,25 @@ string DecodeBase32(const string& str) return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size()); } +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 + return false; + if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed + return false; + return true; +} + bool ParseInt32(const std::string& str, int32_t *out) { + if (!ParsePrechecks(str)) + return false; char *endp = NULL; errno = 0; // strtol will not set errno if valid long int n = strtol(str.c_str(), &endp, 10); - if(out) *out = (int)n; + if(out) *out = (int32_t)n; // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit // platforms the size of these types may be different. @@ -430,6 +443,34 @@ bool ParseInt32(const std::string& str, int32_t *out) n <= std::numeric_limits::max(); } +bool ParseInt64(const std::string& str, int64_t *out) +{ + if (!ParsePrechecks(str)) + return false; + char *endp = NULL; + errno = 0; // strtoll will not set errno if valid + long long int n = strtoll(str.c_str(), &endp, 10); + if(out) *out = (int64_t)n; + // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow + // we still have to check that the returned value is within the range of an *int64_t*. + return endp && *endp == 0 && !errno && + n >= std::numeric_limits::min() && + n <= std::numeric_limits::max(); +} + +bool ParseDouble(const std::string& str, double *out) +{ + if (!ParsePrechecks(str)) + return false; + if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed + return false; + char *endp = NULL; + errno = 0; // strtod will not set errno if valid + double n = strtod(str.c_str(), &endp); + if(out) *out = n; + return endp && *endp == 0 && !errno; +} + std::string FormatParagraph(const std::string in, size_t width, size_t indent) { std::stringstream out; -- cgit v1.2.3