Misc: Replace isspace() usage with StringUtil::IsWhitespace()

Avoids the UB if the character is negative (e.g. reading from a binary
file), as well as locale-specific rubbish.
This commit is contained in:
Stenzek 2025-01-19 20:52:37 +10:00
parent 21b167d382
commit c03b6f3d84
No known key found for this signature in database
8 changed files with 29 additions and 21 deletions

View File

@ -302,13 +302,13 @@ std::string StringUtil::EncodeBase64(const std::span<u8> data)
std::string_view StringUtil::StripWhitespace(const std::string_view str)
{
std::string_view::size_type start = 0;
while (start < str.size() && std::isspace(str[start]))
while (start < str.size() && StringUtil::IsWhitespace(str[start]))
start++;
if (start == str.size())
return {};
std::string_view::size_type end = str.size() - 1;
while (end > start && std::isspace(str[end]))
while (end > start && StringUtil::IsWhitespace(str[end]))
end--;
return str.substr(start, end - start + 1);
@ -319,7 +319,7 @@ void StringUtil::StripWhitespace(std::string* str)
{
const char* cstr = str->c_str();
std::string_view::size_type start = 0;
while (start < str->size() && std::isspace(cstr[start]))
while (start < str->size() && StringUtil::IsWhitespace(cstr[start]))
start++;
if (start != 0)
str->erase(0, start);
@ -328,7 +328,7 @@ void StringUtil::StripWhitespace(std::string* str)
{
const char* cstr = str->c_str();
std::string_view::size_type start = str->size();
while (start > 0 && std::isspace(cstr[start - 1]))
while (start > 0 && StringUtil::IsWhitespace(cstr[start - 1]))
start--;
if (start != str->size())
str->erase(start);

View File

@ -233,6 +233,13 @@ inline std::string ToChars(bool value, int base)
return std::string(value ? "true" : "false");
}
/// Returns true if the given character is whitespace.
static inline bool IsWhitespace(char ch)
{
return ((ch >= 0x09 && ch <= 0x0D) || // horizontal tab, line feed, vertical tab, form feed, carriage return
ch == 0x20); // space
}
/// Encode/decode hexadecimal byte buffers
u8 DecodeHexDigit(char ch);
std::optional<std::vector<u8>> DecodeHex(const std::string_view str);

View File

@ -605,7 +605,7 @@ std::string Cheats::FormatCodeForFile(const CodeInfo& code)
// remove trailing whitespace
std::string_view code_body = code.body;
while (!code_body.empty() && std::isspace(code_body.back()))
while (!code_body.empty() && StringUtil::IsWhitespace(code_body.back()))
code_body = code_body.substr(0, code_body.length() - 1);
if (!code_body.empty())
buf.append(code_body);
@ -657,7 +657,7 @@ bool Cheats::UpdateCodeInFile(const char* path, const std::string_view name, con
{
const std::string code_body = FormatCodeForFile(*code);
file_contents.reserve(file_contents.length() + 1 + code_body.length());
while (!file_contents.empty() && std::isspace(file_contents.back()))
while (!file_contents.empty() && StringUtil::IsWhitespace(file_contents.back()))
file_contents.pop_back();
if (!file_contents.empty())
file_contents.append("\n\n");
@ -715,7 +715,7 @@ bool Cheats::SaveCodesToFile(const char* path, const CodeInfoList& codes, Error*
{
const std::string code_body = FormatCodeForFile(code);
file_contents.reserve(file_contents.length() + 1 + code_body.length());
while (!file_contents.empty() && std::isspace(file_contents.back()))
while (!file_contents.empty() && StringUtil::IsWhitespace(file_contents.back()))
file_contents.pop_back();
if (!file_contents.empty())
file_contents.append("\n\n");

View File

@ -8,6 +8,7 @@
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
#include "common/string_util.h"
#include <algorithm>
#include <cerrno>
@ -81,7 +82,7 @@ bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error)
while (std::getline(ifs, line))
{
u32 start_offset = 0;
while (start_offset < line.size() && std::isspace(line[start_offset]))
while (start_offset < line.size() && StringUtil::IsWhitespace(line[start_offset]))
start_offset++;
// skip comments
@ -90,7 +91,7 @@ bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error)
// strip ending whitespace
u32 end_offset = static_cast<u32>(line.size()) - 1;
while (std::isspace(line[end_offset]) && end_offset > start_offset)
while (StringUtil::IsWhitespace(line[end_offset]) && end_offset > start_offset)
end_offset--;
// anything?

View File

@ -88,7 +88,7 @@ std::string_view CueParser::File::GetToken(const char*& line)
std::string_view ret;
const char* start = line;
while (std::isspace(*start) && *start != '\0')
while (StringUtil::IsWhitespace(*start) && *start != '\0')
start++;
if (*start == '\0')
@ -114,7 +114,7 @@ std::string_view CueParser::File::GetToken(const char*& line)
else
{
end = start;
while (!std::isspace(*end) && *end != '\0')
while (!StringUtil::IsWhitespace(*end) && *end != '\0')
end++;
ret = std::string_view(start, static_cast<size_t>(end - start));
@ -154,7 +154,7 @@ std::optional<CueParser::MSF> CueParser::File::GetMSF(std::string_view token)
if (part == 3)
break;
while (end < token.length() && std::isspace(token[end]))
while (end < token.length() && StringUtil::IsWhitespace(token[end]))
end++;
if (end == token.length() || token[end] != ':')
return std::nullopt;

View File

@ -653,7 +653,7 @@ bool GPUDevice::CreateResources(Error* error)
// Backend may initialize null texture itself if it needs it.
if (!m_empty_texture &&
!(m_empty_texture = CreateTexture(1, 1, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8,
GPUTexture::Flags::None, nullptr, 0, error)))
GPUTexture::Flags::None, nullptr, 0, error)))
{
Error::AddPrefix(error, "Failed to create null texture: ");
return false;
@ -918,7 +918,7 @@ std::optional<GPUDevice::ExclusiveFullscreenMode> GPUDevice::ExclusiveFullscreen
std::optional<u32> owidth = StringUtil::FromChars<u32>(str.substr(0, sep1));
sep1++;
while (sep1 < str.length() && std::isspace(str[sep1]))
while (sep1 < str.length() && StringUtil::IsWhitespace(str[sep1]))
sep1++;
if (owidth.has_value() && sep1 < str.length())
@ -929,7 +929,7 @@ std::optional<GPUDevice::ExclusiveFullscreenMode> GPUDevice::ExclusiveFullscreen
std::optional<u32> oheight = StringUtil::FromChars<u32>(str.substr(sep1, sep2 - sep1));
sep2++;
while (sep2 < str.length() && std::isspace(str[sep2]))
while (sep2 < str.length() && StringUtil::IsWhitespace(str[sep2]))
sep2++;
if (oheight.has_value() && sep2 < str.length())

View File

@ -52,7 +52,7 @@ u32 PostProcessing::ParseVector(std::string_view line, ShaderOption::ValueVector
size_t start = 0;
while (index < PostProcessing::ShaderOption::MAX_VECTOR_COMPONENTS)
{
while (start < line.size() && std::isspace(line[start]))
while (start < line.size() && StringUtil::IsWhitespace(line[start]))
start++;
if (start >= line.size())

View File

@ -16,29 +16,29 @@ LOG_CHANNEL(PostProcessing);
void PostProcessing::Shader::ParseKeyValue(std::string_view line, std::string_view* key, std::string_view* value)
{
size_t key_start = 0;
while (key_start < line.size() && std::isspace(line[key_start]))
while (key_start < line.size() && StringUtil::IsWhitespace(line[key_start]))
key_start++;
size_t key_end = key_start;
while (key_end < line.size() && (!std::isspace(line[key_end]) && line[key_end] != '='))
while (key_end < line.size() && (!StringUtil::IsWhitespace(line[key_end]) && line[key_end] != '='))
key_end++;
if (key_start == key_end || key_end == line.size())
return;
size_t value_start = key_end;
while (value_start < line.size() && std::isspace(line[value_start]))
while (value_start < line.size() && StringUtil::IsWhitespace(line[value_start]))
value_start++;
if (value_start == line.size() || line[value_start] != '=')
return;
value_start++;
while (value_start < line.size() && std::isspace(line[value_start]))
while (value_start < line.size() && StringUtil::IsWhitespace(line[value_start]))
value_start++;
size_t value_end = line.size();
while (value_end > value_start && std::isspace(line[value_end - 1]))
while (value_end > value_start && StringUtil::IsWhitespace(line[value_end - 1]))
value_end--;
if (value_start == value_end)