Remove undefined behavior from <ctype.h> calls:

For the functions defined in <ctype.h> the C standard requires
that the value of the int argument be in the range of an
unsigned char, or be EOF.  Violation of this requirement
results in undefined behavior.
This commit is contained in:
Howard Hinnant
2018-03-21 16:25:14 -04:00
committed by Nikolaos D. Bougalis
parent 02c487348a
commit b4e1b3c1b1
17 changed files with 49 additions and 74 deletions

View File

@@ -24,6 +24,7 @@
#include <ripple/basics/Blob.h> #include <ripple/basics/Blob.h>
#include <ripple/basics/strHex.h> #include <ripple/basics/strHex.h>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/optional.hpp>
#include <sstream> #include <sstream>
#include <string> #include <string>
@@ -95,6 +96,8 @@ bool parseUrl (parsedURL& pUrl, std::string const& strUrl);
std::string trim_whitespace (std::string str); std::string trim_whitespace (std::string str);
boost::optional<std::uint64_t> to_uint64(std::string const& s);
} // ripple } // ripple
#endif #endif

View File

@@ -354,19 +354,19 @@ public:
*/ */
bool SetHex (const char* psz, bool bStrict = false) bool SetHex (const char* psz, bool bStrict = false)
{ {
// Find beginning.
auto pBegin = reinterpret_cast<const unsigned char*>(psz);
// skip leading spaces // skip leading spaces
if (!bStrict) if (!bStrict)
while (isspace (*psz)) while (isspace(*pBegin))
psz++; pBegin++;
// skip 0x // skip 0x
if (!bStrict && psz[0] == '0' && tolower (psz[1]) == 'x') if (!bStrict && pBegin[0] == '0' && tolower(pBegin[1]) == 'x')
psz += 2; pBegin += 2;
const unsigned char* pEnd = reinterpret_cast<const unsigned char*> (psz);
const unsigned char* pBegin = pEnd;
// Find end. // Find end.
auto pEnd = pBegin;
while (charUnHex(*pEnd) != -1) while (charUnHex(*pEnd) != -1)
pEnd++; pEnd++;

View File

@@ -279,7 +279,7 @@ public:
// Attempt to find the first and last valid port separators // Attempt to find the first and last valid port separators
auto const find_port_separator = [](char const c) -> bool auto const find_port_separator = [](char const c) -> bool
{ {
if (std::isspace (c)) if (std::isspace (static_cast<unsigned char>(c)))
return true; return true;
if (c == ':') if (c == ':')

View File

@@ -123,4 +123,13 @@ std::string trim_whitespace (std::string str)
return str; return str;
} }
boost::optional<std::uint64_t>
to_uint64(std::string const& s)
{
std::uint64_t result;
if (beast::lexicalCastChecked (result, s))
return result;
return boost::none;
}
} // ripple } // ripple

View File

@@ -184,7 +184,11 @@ struct LexicalCast <Out, std::string>
operator () (bool& out, std::string in) const operator () (bool& out, std::string in) const
{ {
// Convert the input to lowercase // Convert the input to lowercase
std::transform(in.begin (), in.end (), in.begin (), ::tolower); std::transform(in.begin (), in.end (), in.begin (),
[](auto c)
{
return ::tolower(static_cast<unsigned char>(c));
});
if (in == "1" || in == "true") if (in == "1" || in == "true")
{ {

View File

@@ -42,7 +42,7 @@ namespace
// in the range [0-127] is the identity. We are more // in the range [0-127] is the identity. We are more
// strict and require only printable characters. // strict and require only printable characters.
for (auto const& c : s) for (auto const& c : s)
assert (isprint(c)); assert (isprint(static_cast<unsigned char>(c)));
#endif #endif
return [NSString stringWithUTF8String: s.c_str()]; return [NSString stringWithUTF8String: s.c_str()];

View File

@@ -49,7 +49,7 @@ template <typename InputStream>
bool expect_whitespace (InputStream& is) bool expect_whitespace (InputStream& is)
{ {
char c; char c;
if (is.get(c) && isspace(c)) if (is.get(c) && isspace(static_cast<unsigned char>(c)))
return true; return true;
is.unget(); is.unget();
is.setstate (std::ios_base::failbit); is.setstate (std::ios_base::failbit);

View File

@@ -86,7 +86,7 @@ Endpoint Endpoint::from_string_altform (std::string const& s)
{ {
char c; char c;
is.get(c); is.get(c);
if (!isspace (c)) if (!isspace (static_cast<unsigned char>(c)))
{ {
is.unget(); is.unget();
break; break;

View File

@@ -49,7 +49,8 @@ struct ci_equal_pred
bool operator()(char c1, char c2) bool operator()(char c1, char c2)
{ {
// VFALCO TODO Use a table lookup here // VFALCO TODO Use a table lookup here
return std::tolower(c1) == std::tolower(c2); return std::tolower(static_cast<unsigned char>(c1)) ==
std::tolower(static_cast<unsigned char>(c2));
} }
}; };

View File

@@ -347,8 +347,8 @@ void RFC1751::standard (std::string& strWord)
{ {
for (auto& letter : strWord) for (auto& letter : strWord)
{ {
if (islower (letter)) if (islower (static_cast<unsigned char>(letter)))
letter = toupper (letter); letter = toupper (static_cast<unsigned char>(letter));
else if (letter == '1') else if (letter == '1')
letter = 'L'; letter = 'L';
else if (letter == '0') else if (letter == '0')

View File

@@ -392,7 +392,7 @@ Reader::readNumber ()
while ( current_ != end_ ) while ( current_ != end_ )
{ {
if (!std::isdigit (*current_)) if (!std::isdigit (static_cast<unsigned char>(*current_)))
{ {
auto ret = std::find (std::begin (extended_tokens), auto ret = std::find (std::begin (extended_tokens),
std::end (extended_tokens), *current_); std::end (extended_tokens), *current_);

View File

@@ -84,33 +84,6 @@ std::string createHTTPPost (
return s.str (); return s.str ();
} }
static
boost::optional<std::uint64_t>
to_uint64(std::string const& s)
{
if (s.empty())
return boost::none;
for (auto c : s)
{
if (!isdigit(c))
return boost::none;
}
try
{
std::size_t pos{};
auto const drops = std::stoul(s, &pos);
if (s.size() != pos)
return boost::none;
return drops;
}
catch (std::exception const&)
{
return boost::none;
}
}
class RPCParser class RPCParser
{ {
private: private:

View File

@@ -95,7 +95,11 @@ DatabaseShardImp::init()
if (!is_directory(d)) if (!is_directory(d))
continue; continue;
auto dirName = d.path().stem().string(); auto dirName = d.path().stem().string();
if (!std::all_of(dirName.begin(), dirName.end(), ::isdigit)) if (!std::all_of(dirName.begin(), dirName.end(),
[](auto c)
{
return ::isdigit(static_cast<unsigned char>(c));
}))
continue; continue;
auto const shardIndex {std::stoul(dirName)}; auto const shardIndex {std::stoul(dirName)};
if (shardIndex < earliestShardIndex()) if (shardIndex < earliestShardIndex())

View File

@@ -78,7 +78,11 @@ bool to_currency(Currency& currency, std::string const& code)
{ {
Blob codeBlob (CURRENCY_CODE_LENGTH); Blob codeBlob (CURRENCY_CODE_LENGTH);
std::transform (code.begin (), code.end (), codeBlob.begin (), ::toupper); std::transform (code.begin (), code.end (), codeBlob.begin (),
[](auto c)
{
return ::toupper(static_cast<unsigned char>(c));
});
Serializer s; Serializer s;

View File

@@ -35,33 +35,6 @@
namespace ripple { namespace ripple {
static
boost::optional<std::uint64_t>
to_uint64(std::string const& s)
{
if (s.empty())
return boost::none;
for (auto c : s)
{
if (!isdigit(c))
return boost::none;
}
try
{
std::size_t pos{};
auto const drops = std::stoul(s, &pos);
if (s.size() != pos)
return boost::none;
return drops;
}
catch (std::exception const&)
{
return boost::none;
}
}
// { // {
// secret_key: <signing_secret_key> // secret_key: <signing_secret_key>
// channel_id: 256-bit channel id // channel_id: 256-bit channel id

View File

@@ -45,7 +45,7 @@ isHexTxID (std::string const& txid)
auto const ret = std::find_if (txid.begin (), txid.end (), auto const ret = std::find_if (txid.begin (), txid.end (),
[](std::string::value_type c) [](std::string::value_type c)
{ {
return !std::isxdigit (c); return !std::isxdigit (static_cast<unsigned char>(c));
}); });
return (ret == txid.end ()); return (ret == txid.end ());

View File

@@ -267,7 +267,11 @@ build_map(beast::http::fields const& h)
{ {
auto key (e.name_string().to_string()); auto key (e.name_string().to_string());
// TODO Replace with safe C++14 version // TODO Replace with safe C++14 version
std::transform (key.begin(), key.end(), key.begin(), ::tolower); std::transform (key.begin(), key.end(), key.begin(),
[](auto c)
{
return ::tolower(static_cast<unsigned char>(c));
});
c [key] = e.value().to_string(); c [key] = e.value().to_string();
} }
return c; return c;