mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-16 05:34:00 -04:00
vt: ensure we never step outside our parameter and sub-parameter arrays
We only support 16 parameters, and for each parameter, 16 sub-parameters. If we ever hit that limit (or rather, if the client writes 17 (sub) parameters), log this and stop incrementing the parameter index variable. For performance reason, we implement the following behavior: * We never increment the parameter index past the supported number. This ensures all code *accessing* the parameter list can do so without verifying the validity of the index. * The *first* time we see too many parameters, and the first time we see too many sub parameters, log this. Then *never* log again. Even if we see too many parameters in a completely different escape. This is so that we don't have to keep a "have warned" boolean in the terminal struct, but can use a simple function local static variable.
This commit is contained in:
parent
cc5d596cd9
commit
8c32e3ccf0
1 changed files with 73 additions and 9 deletions
82
vt.c
82
vt.c
|
|
@ -236,24 +236,88 @@ action_param(struct terminal *term, uint8_t c)
|
||||||
term->vt.params.idx = 1;
|
term->vt.params.idx = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(term->vt.params.idx > 0);
|
||||||
|
|
||||||
|
const size_t max_params
|
||||||
|
= sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]);
|
||||||
|
const size_t max_sub_params
|
||||||
|
= sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]);
|
||||||
|
|
||||||
|
/* New parameter */
|
||||||
if (c == ';') {
|
if (c == ';') {
|
||||||
|
if (unlikely(term->vt.params.idx >= max_params))
|
||||||
|
goto excess_params;
|
||||||
|
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx++];
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx++];
|
||||||
param->value = 0;
|
param->value = 0;
|
||||||
param->sub.idx = 0;
|
param->sub.idx = 0;
|
||||||
} else if (c == ':') {
|
}
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
||||||
param->sub.value[param->sub.idx++] = 0;
|
|
||||||
} else {
|
|
||||||
assert(term->vt.params.idx >= 0);
|
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
||||||
|
|
||||||
unsigned *value = param->sub.idx > 0
|
/* New sub-parameter */
|
||||||
? ¶m->sub.value[param->sub.idx - 1]
|
else if (c == ':') {
|
||||||
: ¶m->value;
|
if (unlikely(term->vt.params.idx - 1 >= max_params))
|
||||||
|
goto excess_params;
|
||||||
|
|
||||||
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
||||||
|
if (unlikely(param->sub.idx >= max_sub_params))
|
||||||
|
goto excess_sub_params;
|
||||||
|
|
||||||
|
param->sub.value[param->sub.idx++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New digit for current parameter/sub-parameter */
|
||||||
|
else {
|
||||||
|
if (unlikely(term->vt.params.idx - 1 >= max_params))
|
||||||
|
goto excess_params;
|
||||||
|
|
||||||
|
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
||||||
|
unsigned *value;
|
||||||
|
|
||||||
|
if (param->sub.idx > 0) {
|
||||||
|
if (unlikely(param->sub.idx - 1 >= max_sub_params))
|
||||||
|
goto excess_sub_params;
|
||||||
|
value = ¶m->sub.value[param->sub.idx - 1];
|
||||||
|
} else
|
||||||
|
value = ¶m->value;
|
||||||
|
|
||||||
*value *= 10;
|
*value *= 10;
|
||||||
*value += c - '0';
|
*value += c - '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
/* The rest of the code assumes 'idx' *never* points outside the array */
|
||||||
|
assert(term->vt.params.idx <= max_params);
|
||||||
|
for (size_t i = 0; i < term->vt.params.idx; i++)
|
||||||
|
assert(term->vt.params.v[i].sub.idx <= max_sub_params);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
excess_params:
|
||||||
|
{
|
||||||
|
static bool have_warned = false;
|
||||||
|
if (!have_warned) {
|
||||||
|
have_warned = true;
|
||||||
|
LOG_WARN(
|
||||||
|
"unsupported: escape with more than %zu parameters "
|
||||||
|
"(will not warn again)",
|
||||||
|
sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
excess_sub_params:
|
||||||
|
{
|
||||||
|
static bool have_warned = false;
|
||||||
|
if (!have_warned) {
|
||||||
|
have_warned = true;
|
||||||
|
LOG_WARN(
|
||||||
|
"unsupported: escape with more than %zu sub-parameters "
|
||||||
|
"(will not warn again)",
|
||||||
|
sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue