mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05: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;
|
||||
}
|
||||
|
||||
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 (unlikely(term->vt.params.idx >= max_params))
|
||||
goto excess_params;
|
||||
|
||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx++];
|
||||
param->value = 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
|
||||
? ¶m->sub.value[param->sub.idx - 1]
|
||||
: ¶m->value;
|
||||
/* New sub-parameter */
|
||||
else if (c == ':') {
|
||||
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 += 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue