Replace all locale-dependent operations with locale-agnostic counterparts

This commit is contained in:
wechman 2022-03-04 10:15:57 +01:00
parent 198b705361
commit 52dfccca98
16 changed files with 106 additions and 52 deletions

View File

@ -200,9 +200,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
case Operation: case Operation:
{ {
assertThrow(isValidInstruction(instruction()), AssemblyException, "Invalid instruction."); assertThrow(isValidInstruction(instruction()), AssemblyException, "Invalid instruction.");
string name = instructionInfo(instruction()).name; text = util::toLower(instructionInfo(instruction()).name);
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
text = name;
break; break;
} }
case Push: case Push:

View File

@ -40,10 +40,13 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with solidity. If not, see <http://www.gnu.org/licenses/>. // along with solidity. If not, see <http://www.gnu.org/licenses/>.
#include <liblangutil/Token.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <liblangutil/Token.h>
#include <libsolutil/StringUtils.h>
#include <map> #include <map>
using namespace std; using namespace std;
namespace solidity::langutil namespace solidity::langutil
@ -180,11 +183,11 @@ tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _
return ret; return ret;
}; };
auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); auto positionM = find_if(_literal.begin(), _literal.end(), util::isDigit);
if (positionM != _literal.end()) if (positionM != _literal.end())
{ {
string baseType(_literal.begin(), positionM); string baseType(_literal.begin(), positionM);
auto positionX = find_if_not(positionM, _literal.end(), ::isdigit); auto positionX = find_if_not(positionM, _literal.end(), util::isDigit);
int m = parseSize(positionM, positionX); int m = parseSize(positionM, positionX);
Token keyword = keywordByName(baseType); Token keyword = keywordByName(baseType);
if (keyword == Token::Bytes) if (keyword == Token::Bytes)
@ -208,7 +211,7 @@ tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _
positionM < positionX && positionM < positionX &&
positionX < _literal.end() && positionX < _literal.end() &&
*positionX == 'x' && *positionX == 'x' &&
all_of(positionX + 1, _literal.end(), ::isdigit) all_of(positionX + 1, _literal.end(), util::isDigit)
) { ) {
int n = parseSize(positionX + 1, _literal.end()); int n = parseSize(positionX + 1, _literal.end());
if ( if (

View File

@ -33,6 +33,7 @@
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <libsolutil/FunctionSelector.h> #include <libsolutil/FunctionSelector.h>
#include <libsolutil/Keccak256.h> #include <libsolutil/Keccak256.h>
#include <libsolutil/StringUtils.h>
#include <libsolutil/UTF8.h> #include <libsolutil/UTF8.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -781,8 +782,8 @@ tuple<bool, rational> RationalNumberType::parseRational(string const& _value)
if (radixPoint != _value.end()) if (radixPoint != _value.end())
{ {
if ( if (
!all_of(radixPoint + 1, _value.end(), ::isdigit) || !all_of(radixPoint + 1, _value.end(), util::isDigit) ||
!all_of(_value.begin(), radixPoint, ::isdigit) !all_of(_value.begin(), radixPoint, util::isDigit)
) )
return make_tuple(false, rational(0)); return make_tuple(false, rational(0));

View File

@ -203,7 +203,7 @@ private:
else else
solAssert(false); solAssert(false);
if (isdigit(value.front())) if (isDigit(value.front()))
return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::YulString{value}, {}}; return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::YulString{value}, {}};
else else
return yul::Identifier{_identifier.debugData, yul::YulString{value}}; return yul::Identifier{_identifier.debugData, yul::YulString{value}};

View File

@ -33,6 +33,7 @@
#include <libsmtutil/CHCSmtLib2Interface.h> #include <libsmtutil/CHCSmtLib2Interface.h>
#include <liblangutil/CharStreamProvider.h> #include <liblangutil/CharStreamProvider.h>
#include <libsolutil/Algorithms.h> #include <libsolutil/Algorithms.h>
#include <libsolutil/StringUtils.h>
#ifdef HAVE_Z3_DLOPEN #ifdef HAVE_Z3_DLOPEN
#include <z3_version.h> #include <z3_version.h>
@ -1998,9 +1999,9 @@ map<unsigned, vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph c
// Predicates that do not have a CALLID have a predicate id at the end of <suffix>, // Predicates that do not have a CALLID have a predicate id at the end of <suffix>,
// so the assertion below should still hold. // so the assertion below should still hold.
auto beg = _s.data(); auto beg = _s.data();
while (beg != _s.data() + _s.size() && !isdigit(*beg)) ++beg; while (beg != _s.data() + _s.size() && !isDigit(*beg)) ++beg;
auto end = beg; auto end = beg;
while (end != _s.data() + _s.size() && isdigit(*end)) ++end; while (end != _s.data() + _s.size() && isDigit(*end)) ++end;
solAssert(beg != end, "Expected to find numerical call or predicate id."); solAssert(beg != end, "Expected to find numerical call or predicate id.");

View File

@ -20,11 +20,12 @@
* @date 2014 * @date 2014
*/ */
#include <libsolutil/Assertions.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/Exceptions.h> #include <libsolutil/Exceptions.h>
#include <libsolutil/Assertions.h>
#include <libsolutil/Keccak256.h>
#include <libsolutil/FixedHash.h> #include <libsolutil/FixedHash.h>
#include <libsolutil/Keccak256.h>
#include <libsolutil/StringUtils.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -154,9 +155,9 @@ string solidity::util::getChecksummedAddress(string const& _addr)
char addressCharacter = s[i]; char addressCharacter = s[i];
uint8_t nibble = hash[i / 2u] >> (4u * (1u - (i % 2u))) & 0xf; uint8_t nibble = hash[i / 2u] >> (4u * (1u - (i % 2u))) & 0xf;
if (nibble >= 8) if (nibble >= 8)
ret += static_cast<char>(toupper(addressCharacter)); ret += toUpper(addressCharacter);
else else
ret += static_cast<char>(tolower(addressCharacter)); ret += toLower(addressCharacter);
} }
return ret; return ret;
} }
@ -211,7 +212,7 @@ string solidity::util::escapeAndQuoteString(string const& _input)
out += "\\r"; out += "\\r";
else if (c == '\t') else if (c == '\t')
out += "\\t"; out += "\\t";
else if (!isprint(c, locale::classic())) else if (!isPrint(c))
{ {
ostringstream o; ostringstream o;
o << "\\x" << std::hex << setfill('0') << setw(2) << (unsigned)(unsigned char)(c); o << "\\x" << std::hex << setfill('0') << setw(2) << (unsigned)(unsigned char)(c);

View File

@ -27,7 +27,9 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/Numeric.h> #include <libsolutil/Numeric.h>
#include <algorithm>
#include <limits> #include <limits>
#include <locale>
#include <string> #include <string>
#include <vector> #include <vector>
@ -197,4 +199,47 @@ inline std::optional<unsigned> toUnsignedInt(std::string const& _value)
} }
} }
/// Converts parameter _c to its lowercase equivalent if c is an uppercase letter and has a lowercase equivalent. It uses the classic "C" locale semantics.
/// @param _c value to be converted
/// @return the converted value
inline char toLower(char _c)
{
return tolower(_c, std::locale::classic());
}
/// Converts parameter _c to its uppercase equivalent if c is an lowercase letter and has a uppercase equivalent. It uses the classic "C" locale semantics.
/// @param _c value to be converted
/// @return the converted value
inline char toUpper(char _c)
{
return toupper(_c, std::locale::classic());
}
/// Converts parameter _s to its lowercase equivalent. It uses the classic "C" locale semantics.
/// @param _s value to be converted
/// @return the converted value
inline std::string toLower(std::string _s)
{
std::transform(_s.begin(), _s.end(), _s.begin(), [](char _c) {
return toLower(_c);
});
return _s;
}
/// Checks whether _c is a decimal digit character. It uses the classic "C" locale semantics.
/// @param _c character to be checked
/// @return true if _c is a decimal digit character, false otherwise
inline bool isDigit(char _c)
{
return isdigit(_c, std::locale::classic());
}
// Checks if character is printable using classic "C" locale
/// @param _c character to be checked
/// @return true if _c is a printable character, false otherwise.
inline bool isPrint(char _c)
{
return isprint(_c, std::locale::classic());
}
} }

View File

@ -21,17 +21,17 @@
#include <libyul/backends/evm/EVMDialect.h> #include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmAnalysisInfo.h> #include <libevmasm/Instruction.h>
#include <libevmasm/SemanticInformation.h>
#include <liblangutil/Exceptions.h>
#include <libsolutil/StringUtils.h>
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libyul/Object.h> #include <libyul/AsmAnalysisInfo.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmParser.h> #include <libyul/AsmParser.h>
#include <libyul/Exceptions.h>
#include <libyul/Object.h>
#include <libyul/Utilities.h> #include <libyul/Utilities.h>
#include <libyul/backends/evm/AbstractAssembly.h> #include <libyul/backends/evm/AbstractAssembly.h>
#include <libevmasm/SemanticInformation.h>
#include <libevmasm/Instruction.h>
#include <liblangutil/Exceptions.h>
#include <range/v3/view/reverse.hpp> #include <range/v3/view/reverse.hpp>
#include <range/v3/view/tail.hpp> #include <range/v3/view/tail.hpp>
@ -121,8 +121,7 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
set<YulString> reserved; set<YulString> reserved;
for (auto const& instr: evmasm::c_instructions) for (auto const& instr: evmasm::c_instructions)
{ {
string name = instr.first; string name = toLower(instr.first);
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
if (!baseFeeException(instr.second)) if (!baseFeeException(instr.second))
reserved.emplace(name); reserved.emplace(name);
} }
@ -142,8 +141,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
map<YulString, BuiltinFunctionForEVM> builtins; map<YulString, BuiltinFunctionForEVM> builtins;
for (auto const& instr: evmasm::c_instructions) for (auto const& instr: evmasm::c_instructions)
{ {
string name = instr.first; string name = toLower(instr.first);
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
auto const opcode = instr.second; auto const opcode = instr.second;
if ( if (

View File

@ -21,15 +21,16 @@
#include <libyul/optimiser/SimplificationRules.h> #include <libyul/optimiser/SimplificationRules.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/SyntacticalEquality.h>
#include <libyul/optimiser/DataFlowAnalyzer.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libyul/Utilities.h> #include <libyul/Utilities.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/optimiser/DataFlowAnalyzer.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/SyntacticalEquality.h>
#include <libevmasm/RuleList.h> #include <libevmasm/RuleList.h>
#include <libsolutil/StringUtils.h>
using namespace std; using namespace std;
using namespace solidity; using namespace solidity;
@ -249,8 +250,7 @@ Expression Pattern::toExpression(shared_ptr<DebugData const> const& _debugData)
for (auto const& arg: m_arguments) for (auto const& arg: m_arguments)
arguments.emplace_back(arg.toExpression(_debugData)); arguments.emplace_back(arg.toExpression(_debugData));
string name = instructionInfo(m_instruction).name; string name = util::toLower(instructionInfo(m_instruction).name);
transform(begin(name), end(name), begin(name), [](auto _c) { return tolower(_c); });
return FunctionCall{_debugData, return FunctionCall{_debugData,
Identifier{_debugData, YulString{name}}, Identifier{_debugData, YulString{name}},

View File

@ -29,7 +29,6 @@
using namespace std; using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util;
using namespace solidity::util::formatting; using namespace solidity::util::formatting;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -43,10 +42,11 @@ namespace
int parseUnsignedInteger(string::iterator& _it, string::iterator _end) int parseUnsignedInteger(string::iterator& _it, string::iterator _end)
{ {
if (_it == _end || !isdigit(*_it)) auto isDigit = [](char _c) -> bool {return isdigit(_c, std::locale::classic());};
if (_it == _end || !isDigit(*_it))
BOOST_THROW_EXCEPTION(runtime_error("Invalid test expectation. Source location expected.")); BOOST_THROW_EXCEPTION(runtime_error("Invalid test expectation. Source location expected."));
int result = 0; int result = 0;
while (_it != _end && isdigit(*_it)) while (_it != _end && isDigit(*_it))
{ {
result *= 10; result *= 10;
result += *_it - '0'; result += *_it - '0';
@ -195,6 +195,7 @@ string CommonSyntaxTest::errorMessage(Exception const& _e)
vector<SyntaxTestError> CommonSyntaxTest::parseExpectations(istream& _stream) vector<SyntaxTestError> CommonSyntaxTest::parseExpectations(istream& _stream)
{ {
auto isDigit = [](char _c) -> bool {return isdigit(_c, std::locale::classic());};
vector<SyntaxTestError> expectations; vector<SyntaxTestError> expectations;
string line; string line;
while (getline(_stream, line)) while (getline(_stream, line))
@ -207,14 +208,14 @@ vector<SyntaxTestError> CommonSyntaxTest::parseExpectations(istream& _stream)
if (it == line.end()) continue; if (it == line.end()) continue;
auto typeBegin = it; auto typeBegin = it;
while (it != line.end() && isalpha(*it)) while (it != line.end() && isalpha(*it, locale::classic()))
++it; ++it;
string errorType(typeBegin, it); string errorType(typeBegin, it);
skipWhitespace(it, line.end()); skipWhitespace(it, line.end());
optional<ErrorId> errorId; optional<ErrorId> errorId;
if (it != line.end() && isdigit(*it)) if (it != line.end() && isDigit(*it))
errorId = ErrorId{static_cast<unsigned long long>(parseUnsignedInteger(it, line.end()))}; errorId = ErrorId{static_cast<unsigned long long>(parseUnsignedInteger(it, line.end()))};
expect(it, line.end(), ':'); expect(it, line.end(), ':');
@ -227,7 +228,7 @@ vector<SyntaxTestError> CommonSyntaxTest::parseExpectations(istream& _stream)
if (it != line.end() && *it == '(') if (it != line.end() && *it == '(')
{ {
++it; ++it;
if (it != line.end() && !isdigit(*it)) if (it != line.end() && !isDigit(*it))
{ {
auto sourceNameStart = it; auto sourceNameStart = it;
while (it != line.end() && *it != ':') while (it != line.end() && *it != ':')

View File

@ -118,7 +118,7 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(string const& _filena
string comparator; string comparator;
size_t versionBegin = 0; size_t versionBegin = 0;
for (auto character: versionString) for (auto character: versionString)
if (!isalpha(character)) if (!isalpha(character, locale::classic()))
{ {
comparator += character; comparator += character;
versionBegin++; versionBegin++;

View File

@ -90,7 +90,7 @@ protected:
template<typename IteratorType> template<typename IteratorType>
static void skipWhitespace(IteratorType& _it, IteratorType _end) static void skipWhitespace(IteratorType& _it, IteratorType _end)
{ {
while (_it != _end && isspace(*_it)) while (_it != _end && std::isspace<char>(*_it, std::locale::classic()))
++_it; ++_it;
} }

View File

@ -22,6 +22,7 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <libsolutil/StringUtils.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -216,7 +217,7 @@ string BytesUtils::formatString(bytes const& _bytes, size_t _cutOff)
os << "\\n"; os << "\\n";
break; break;
default: default:
if (isprint(v)) if (isPrint(static_cast<char>(v)))
os << v; os << v;
else else
os << "\\x" << toHex(v, HexCase::Lower); os << "\\x" << toHex(v, HexCase::Lower);

View File

@ -762,13 +762,16 @@ string TestFileParser::Scanner::scanString()
// TODO: use fromHex() from CommonData // TODO: use fromHex() from CommonData
char TestFileParser::Scanner::scanHexPart() char TestFileParser::Scanner::scanHexPart()
{ {
auto toLower = [](char _c) -> char { return tolower(_c, locale::classic()); };
auto isDigit = [](char _c) -> bool { return isdigit(_c, locale::classic()); };
advance(); // skip 'x' advance(); // skip 'x'
int value{}; int value{};
if (isdigit(current())) if (isDigit(current()))
value = current() - '0'; value = current() - '0';
else if (tolower(current()) >= 'a' && tolower(current()) <= 'f') else if (toLower(current()) >= 'a' && toLower(current()) <= 'f')
value = tolower(current()) - 'a' + 10; value = toLower(current()) - 'a' + 10;
else else
BOOST_THROW_EXCEPTION(TestParserError("\\x used with no following hex digits.")); BOOST_THROW_EXCEPTION(TestParserError("\\x used with no following hex digits."));
@ -777,10 +780,10 @@ char TestFileParser::Scanner::scanHexPart()
return static_cast<char>(value); return static_cast<char>(value);
value <<= 4; value <<= 4;
if (isdigit(current())) if (isDigit(current()))
value |= current() - '0'; value |= current() - '0';
else if (tolower(current()) >= 'a' && tolower(current()) <= 'f') else if (toLower(current()) >= 'a' && toLower(current()) <= 'f')
value |= tolower(current()) - 'a' + 10; value |= toLower(current()) - 'a' + 10;
advance(); advance();

View File

@ -28,6 +28,7 @@
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/StringUtils.h>
#include <test/tools/ossfuzz/yulFuzzerCommon.h> #include <test/tools/ossfuzz/yulFuzzerCommon.h>
@ -53,7 +54,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
string input(reinterpret_cast<char const*>(_data), _size); string input(reinterpret_cast<char const*>(_data), _size);
if (std::any_of(input.begin(), input.end(), [](char c) { if (std::any_of(input.begin(), input.end(), [](char c) {
return ((static_cast<unsigned char>(c) > 127) || !(std::isprint(c) || (c == '\n') || (c == '\t'))); return ((static_cast<unsigned char>(c) > 127) || !(isPrint(c) || (c == '\n') || (c == '\t')));
})) }))
return 0; return 0;

View File

@ -21,6 +21,7 @@
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <libsolutil/Exceptions.h> #include <libsolutil/Exceptions.h>
#include <libsolutil/StringUtils.h>
#include <liblangutil/ErrorReporter.h> #include <liblangutil/ErrorReporter.h>
#include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmAnalysisInfo.h>
@ -155,7 +156,7 @@ public:
return ( return (
!boost::algorithm::iequals(get<1>(_a), get<1>(_b)) ? !boost::algorithm::iequals(get<1>(_a), get<1>(_b)) ?
boost::algorithm::lexicographical_compare(get<1>(_a), get<1>(_b), boost::algorithm::is_iless()) : boost::algorithm::lexicographical_compare(get<1>(_a), get<1>(_b), boost::algorithm::is_iless()) :
tolower(get<0>(_a)) < tolower(get<0>(_b)) toLower(get<0>(_a)) < toLower(get<0>(_b))
); );
}); });