mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 01:07:43 +00:00
CStringExtras: Prevent potential out of bounds reads with CompareCaseInsensitive
The strcasecmp and _stricmp functions expect the passed in strings to be null-terminated, however we we're also exposing a std::string_view overload for that function. std::string_view instances aren't required to be null-terminated, so this makes the interface a little unsafe. We can use std::lexicographical_compare() to provide the same behavior and also properly handle the case of non-null-terminated strings.
This commit is contained in:
@@ -1,21 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
namespace urde {
|
||||
|
||||
class CStringExtras {
|
||||
public:
|
||||
static int CompareCaseInsensitive(const char* a, const char* b) {
|
||||
#if _WIN32
|
||||
return _stricmp(a, b);
|
||||
#else
|
||||
return strcasecmp(a, b);
|
||||
#endif
|
||||
}
|
||||
static int CompareCaseInsensitive(std::string_view a, std::string_view b) {
|
||||
return CompareCaseInsensitive(a.data(), b.data());
|
||||
// Checks if the provided views into string data can be considered equal or not based on
|
||||
// whether or not all their characters are lexicographically equal to one another in
|
||||
// a character insensitive manner.
|
||||
//
|
||||
// NOTE: This differs slightly from the actual version of this function within the game executable
|
||||
// in order to better accomodate string views and potentially non-null-terminated string data.
|
||||
//
|
||||
// In the game executable, the function essentially behaves like strcasecmp in that it returns
|
||||
// an int indicating whether or not the first argument is lexicographically less than, equal to,
|
||||
// or greater than the second argument. Given no usages in the code depend on the less than or
|
||||
// greater than cases, but rather just care about whether or not the strings are equal to one
|
||||
// another, this is a safe change to make.
|
||||
//
|
||||
static bool CompareCaseInsensitive(std::string_view a, std::string_view b) {
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char lhs, char rhs) {
|
||||
return std::tolower(static_cast<unsigned char>(lhs)) < std::tolower(static_cast<unsigned char>(rhs));
|
||||
});
|
||||
}
|
||||
|
||||
static int IndexOfSubstring(std::string_view haystack, std::string_view needle) {
|
||||
|
||||
Reference in New Issue
Block a user