From 971361b046eeb78aa8a7028802e2bf95f4edf107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 9 Apr 2023 09:27:31 +0200 Subject: [PATCH] yaml: keep original value when anchor and target node both defines the same key When merging an anchor into a target yaml node, and both the target node and the anchor defines the same key(s), keep the value from the target node. Closes #286 --- CHANGELOG.md | 3 +++ yml.c | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 762c37b..48373d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,12 +50,15 @@ * i3/sway: regression; persistent workspaces shown twice ([#253][253]). * pipewire: use roundf instead of ceilf for more accuracy ([#262][262]) +* Crash when a yaml anchor has a value to already exists in the target + yaml node ([#286][286]). [239]: https://codeberg.org/dnkl/yambar/issues/239 [241]: https://codeberg.org/dnkl/yambar/issues/241 [251]: https://codeberg.org/dnkl/yambar/pulls/251 [253]: https://codeberg.org/dnkl/yambar/issues/253 [262]: https://codeberg.org/dnkl/yambar/issues/262 +[286]: https://codeberg.org/dnkl/yambar/issues/286 ### Security diff --git a/yml.c b/yml.c index b3f3d42..a81bdad 100644 --- a/yml.c +++ b/yml.c @@ -237,12 +237,15 @@ post_process(struct yml_node *node, char **error) .key = vv_it->item.key, .value = vv_it->item.value, }; - /* TODO: handle this. Is it an error? Or - * should we replace the existing key/value - * pair */ - assert(!dict_has_key(node, vv_it->item.key)); - tll_push_back(node->dict.pairs, p); + if (dict_has_key(node, vv_it->item.key)) { + /* Prefer value in target dictionary, over the + * value from the anchor */ + yml_destroy(vv_it->item.key); + yml_destroy(vv_it->item.value); + } else { + tll_push_back(node->dict.pairs, p); + } } /* Destroy list, but don't free (since its nodes @@ -274,11 +277,14 @@ post_process(struct yml_node *node, char **error) .value = v_it->item.value, }; - /* TODO: handle this. Is it an error? Or should we - * replace the existing key/value pair */ - assert(!dict_has_key(node, v_it->item.key)); - - tll_push_back(node->dict.pairs, p); + if (dict_has_key(node, v_it->item.key)) { + /* Prefer value in target dictionary, over the + * value from the anchor */ + yml_destroy(v_it->item.key); + yml_destroy(v_it->item.value); + } else { + tll_push_back(node->dict.pairs, p); + } } /* Destroy list here, *without* freeing nodes (since