Fix -W parameter parsing

This commit is contained in:
Rangi42
2025-07-19 15:43:54 -04:00
parent 14f5e16ae8
commit 250e08043b
5 changed files with 32 additions and 32 deletions

View File

@@ -28,7 +28,7 @@ struct WarningState {
void update(WarningState other); void update(WarningState other);
}; };
std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::string &flag); std::pair<WarningState, std::optional<uint32_t>> getInitialWarningState(std::string &flag);
template<typename L> template<typename L>
struct WarningFlag { struct WarningFlag {
@@ -150,20 +150,17 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
if (!param.has_value() || *param == 0) { if (!param.has_value() || *param == 0) {
param = paramWarning.defaultLevel; param = paramWarning.defaultLevel;
} else if (*param > maxParam) { } else if (*param > maxParam) {
if (*param != 255) { // Don't warn if already capped warnx(
warnx( "Invalid warning flag parameter \"%s=%" PRIu32 "\"; capping at maximum %" PRIu8,
"Invalid parameter %" PRIu8 rootFlag.c_str(),
" for warning flag \"%s\"; capping at maximum %" PRIu8, *param,
*param, maxParam
rootFlag.c_str(), );
maxParam
);
}
*param = maxParam; *param = maxParam;
} }
// Set the first <param> to enabled/error, and disable the rest // Set the first <param> to enabled/error, and disable the rest
for (uint8_t ofs = 0; ofs < maxParam; ofs++) { for (uint32_t ofs = 0; ofs < maxParam; ofs++) {
if (WarningState &warning = state.flagStates[baseID + ofs]; ofs < *param) { if (WarningState &warning = state.flagStates[baseID + ofs]; ofs < *param) {
warning.update(flagState); warning.update(flagState);
} else { } else {
@@ -174,7 +171,7 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
} }
if (param.has_value()) { if (param.has_value()) {
warnx("Unknown warning flag parameter \"%s\"", rootFlag.c_str()); warnx("Unknown warning flag parameter \"%s=%" PRIu32 "\"", rootFlag.c_str(), *param);
return rootFlag; return rootFlag;
} }

View File

@@ -18,7 +18,7 @@ void WarningState::update(WarningState other) {
} }
} }
std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::string &flag) { std::pair<WarningState, std::optional<uint32_t>> getInitialWarningState(std::string &flag) {
// Check for prefixes that affect what the flag does // Check for prefixes that affect what the flag does
WarningState state; WarningState state;
if (flag.starts_with("error=")) { if (flag.starts_with("error=")) {
@@ -51,28 +51,22 @@ std::pair<WarningState, std::optional<uint8_t>> getInitialWarningState(std::stri
// Is the rest of the string a decimal number? // Is the rest of the string a decimal number?
// We want to avoid `strtoul`'s whitespace and sign, so we parse manually // We want to avoid `strtoul`'s whitespace and sign, so we parse manually
char const *ptr = flag.c_str() + equals + 1; char const *ptr = flag.c_str() + equals + 1;
uint8_t param = 0; uint32_t param = 0;
bool warned = false; bool overflowed = false;
// The `if`'s condition above ensures that this will run at least once for (; *ptr >= '0' && *ptr <= '9'; ++ptr) {
do { if (overflowed) {
// If we don't have a digit, bail
if (*ptr < '0' || *ptr > '9') {
break;
}
// Avoid overflowing!
if (param > UINT8_MAX - (*ptr - '0')) {
if (!warned) {
warnx("Invalid warning flag \"%s\": capping parameter at 255", flag.c_str());
}
warned = true; // Only warn once, cap always
param = 255;
continue; continue;
} }
param = param * 10 + (*ptr - '0');
++ptr; uint32_t c = *ptr - '0';
} while (*ptr); if (param > (UINT32_MAX - c) / 10) {
overflowed = true;
param = UINT32_MAX;
continue;
}
param = param * 10 + c;
}
// If we reached the end of the string, truncate it at the '=' // If we reached the end of the string, truncate it at the '='
if (*ptr == '\0') { if (*ptr == '\0') {

View File

@@ -0,0 +1,4 @@
opt Wtruncation=256
section "test", rom0
db 999
db -254

View File

@@ -0,0 +1,5 @@
warning: Invalid warning flag parameter "truncation=256"; capping at maximum 2
warning: diagnostic-parameter-cap.asm(3): [-Wtruncation]
Expression must be 8-bit; use LOW() to force 8-bit
warning: diagnostic-parameter-cap.asm(4): [-Wtruncation]
Expression must be 8-bit; use LOW() to force 8-bit

View File

@@ -1,4 +1,4 @@
warning: Invalid parameter 99 for warning flag "truncation"; capping at maximum 2 warning: Invalid warning flag parameter "truncation=99"; capping at maximum 2
warning: invalid-param.asm(2): [-Wtruncation] warning: invalid-param.asm(2): [-Wtruncation]
Expression must be 8-bit; use LOW() to force 8-bit Expression must be 8-bit; use LOW() to force 8-bit
warning: invalid-param.asm(3): [-Wtruncation] warning: invalid-param.asm(3): [-Wtruncation]