config: value_to_*(): don't overwrite result variable on error

Some of the value_to_*() functions wrote directly to the output
variable, even when the value was invalid. This often resulted in the
an actual configuration option (i.e. a member in the config struct) to
be overwritten by an invalid value.

For example, -o initial-color-theme=0 would set
conf->initial_color_theme to -1, resulting in a crash later, when
initializing a terminal instance.
This commit is contained in:
Daniel Eklöf 2025-08-25 14:26:44 +02:00
parent 72d9a13c0c
commit ed7652db50
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 20 additions and 7 deletions

View file

@ -70,7 +70,7 @@
### Changed
* The label letters are no longer sorted before being assigned to URLs
([#2140]2140[]).
([#2140][2140]).
* Sending SIGUSR1/SIGUSR2 to a `foot --server` process now causes
newly spawned client instances to use the selected theme, instead of
the original one.
@ -83,6 +83,11 @@
### Deprecated
### Removed
### Fixed
* Invalid configuration values overriding valid ones in surprising
ways.
### Security
### Contributors

View file

@ -474,8 +474,12 @@ str_to_ulong(const char *s, int base, unsigned long *res)
errno = 0;
char *end = NULL;
*res = strtoul(s, &end, base);
return errno == 0 && *end == '\0';
unsigned long v = strtoul(s, &end, base);
if (!(errno == 0 && *end == '\0'))
return false;
*res = v;
return true;
}
static bool NOINLINE
@ -544,12 +548,13 @@ value_to_float(struct context *ctx, float *res)
errno = 0;
char *end = NULL;
*res = strtof(s, &end);
float v = strtof(s, &end);
if (!(errno == 0 && *end == '\0')) {
LOG_CONTEXTUAL_ERR("invalid decimal value");
return false;
}
*res = v;
return true;
}
@ -641,7 +646,6 @@ value_to_enum(struct context *ctx, const char **value_map, int *res)
valid_values[idx - 2] = '\0';
LOG_CONTEXTUAL_ERR("not one of %s", valid_values);
*res = -1;
return false;
}
@ -690,14 +694,18 @@ value_to_two_colors(struct context *ctx,
goto out;
}
uint32_t a, b;
ctx->value = first_as_str;
if (!value_to_color(ctx, first, allow_alpha))
if (!value_to_color(ctx, &a, allow_alpha))
goto out;
ctx->value = second_as_str;
if (!value_to_color(ctx, second, allow_alpha))
if (!value_to_color(ctx, &b, allow_alpha))
goto out;
*first = a;
*second = b;
ret = true;
out: