mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-02 12:32:03 +01:00
CmdLine: Take integer parameters in hex too, and refuse trailing junk
They were read with sscanf("%d"), which stops at the first character it
can't use, so --disable-hle=0x110 was accepted as 0 and quietly ran
everything on our HLE. Now decimal or 0x hex, optionally signed, and the
whole value has to parse. Up to 0xFFFFFFFF is taken, for full masks.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6c8c71a125
commit
ddfd3bcfb9
2 files changed
+57
-1
No files matched your search
+30
-1
@@ -1,5 +1,6 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@@ -51,6 +52,34 @@ enum class ParseParamResult {
|
||||
BadValue,
|
||||
};
|
||||
|
||||
// Decimal, or hex with 0x, optionally signed. Not base 0, which would read a leading 0 as octal.
|
||||
// Up to 0xFFFFFFFF is accepted so a full 32-bit mask can be given, and wraps into the int.
|
||||
static bool ParseIntParam(const std::string &value, int *out) {
|
||||
const char *p = value.c_str();
|
||||
bool negative = false;
|
||||
if (*p == '-' || *p == '+') {
|
||||
negative = *p == '-';
|
||||
p++;
|
||||
}
|
||||
int base = 10;
|
||||
if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
|
||||
base = 16;
|
||||
p += 2;
|
||||
}
|
||||
// strtoull would take another sign or leading spaces here.
|
||||
if (!isxdigit((unsigned char)*p)) {
|
||||
return false;
|
||||
}
|
||||
char *end = nullptr;
|
||||
errno = 0;
|
||||
const unsigned long long magnitude = strtoull(p, &end, base);
|
||||
if (*end != '\0' || errno == ERANGE || magnitude > (negative ? 0x80000000ULL : 0xFFFFFFFFULL)) {
|
||||
return false;
|
||||
}
|
||||
*out = negative ? (int)(0 - (uint32_t)magnitude) : (int)(uint32_t)magnitude;
|
||||
return true;
|
||||
}
|
||||
|
||||
ParseParamResult SetValue(CommandLineOptions *options, const CommandLineParam ¶m, const std::string &value) {
|
||||
uint8_t *optionsPtr = reinterpret_cast<uint8_t *>(options);
|
||||
switch (param.type) {
|
||||
@@ -77,7 +106,7 @@ ParseParamResult SetValue(CommandLineOptions *options, const CommandLineParam &p
|
||||
{
|
||||
// Not std::stoi - that throws on junk, which takes the process down with no diagnostic.
|
||||
int v;
|
||||
if (sscanf(value.c_str(), "%d", &v) != 1) {
|
||||
if (!ParseIntParam(value, &v)) {
|
||||
PRINT_STDERR("Error: Invalid value for integer parameter --%s: '%s'.\n", param.longName, value.c_str());
|
||||
return ParseParamResult::BadValue;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user