yml: don’t crash when (trying to) merge anchors that aren’t dictionaries

Up until now, we only asserted the value being merged in was a
dictionary.

Now we do a proper check and return a real error message instead.

Closes #32
This commit is contained in:
Daniel Eklöf 2021-02-11 19:02:14 +01:00
parent 264c051232
commit 98a4789e26
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 44 additions and 9 deletions

View file

@ -13,6 +13,11 @@
### Deprecated
### Removed
### Fixed
* Crash when merging non-dictionary anchors in the YAML configuration
(https://codeberg.org/dnkl/yambar/issues/32).
### Security
### Contributors

48
yml.c
View file

@ -177,13 +177,14 @@ add_anchor(struct yml_node *root, const char *anchor,
root->root.anchor_count++;
}
static void
post_process(struct yml_node *node)
static bool
post_process(struct yml_node *node, char **error)
{
switch (node->type) {
case ROOT:
if (node->root.root != NULL)
post_process(node->root.root);
if (!post_process(node->root.root, error))
return false;
break;
case SCALAR:
@ -192,13 +193,17 @@ post_process(struct yml_node *node)
case LIST:
tll_foreach(node->list.values, it)
post_process(it->item);
if (!post_process(it->item, error))
return false;
break;
case DICT:
tll_foreach(node->dict.pairs, it) {
post_process(it->item.key);
post_process(it->item.value);
if (!post_process(it->item.key, error) ||
!post_process(it->item.value, error))
{
return false;
}
}
tll_foreach(node->dict.pairs, it) {
@ -214,7 +219,17 @@ post_process(struct yml_node *node)
* e.g. <<: [*foo, *bar]
*/
tll_foreach(it->item.value->list.values, v_it) {
assert(v_it->item->type == DICT);
if (v_it->item->type != DICT) {
int cnt = snprintf(
NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor",
v_it->item->line, v_it->item->column);
*error = malloc(cnt + 1);
snprintf(
*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor",
v_it->item->line, v_it->item->column);
return false;
}
tll_foreach(v_it->item->dict.pairs, vv_it) {
struct dict_pair p = {
.key = vv_it->item.key,
@ -240,7 +255,17 @@ post_process(struct yml_node *node)
* Merge value is a dictionary only
* e.g. <<: *foo
*/
assert(it->item.value->type == DICT);
if (it->item.value->type != DICT) {
int cnt = snprintf(
NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor",
it->item.value->line, it->item.value->column);
*error = malloc(cnt + 1);
snprintf(
*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor",
it->item.value->line, it->item.value->column);
return false;
}
tll_foreach(it->item.value->dict.pairs, v_it) {
struct dict_pair p = {
.key = v_it->item.key,
@ -269,6 +294,8 @@ post_process(struct yml_node *node)
}
break;
}
return true;
}
static const char *
@ -526,7 +553,10 @@ yml_load(FILE *yml, char **error)
yaml_parser_delete(&yaml);
post_process(root);
if (!post_process(root, error)) {
yml_destroy(root);
return NULL;
}
return root;
err: