diff options
author | Ailin Nemui <ailin@linux.site> | 2015-02-17 09:46:52 +0100 |
---|---|---|
committer | Ailin Nemui <ailin@linux.site> | 2015-02-17 09:50:55 +0100 |
commit | fef25d6a35d23f885937b087ed7642b327279df5 (patch) | |
tree | d7f7d7070940f5a26b1798376668edb5cc347293 /src/lib-config | |
parent | 1e4f7e63249b0300cac27e725e14a0134260a387 (diff) | |
download | irssi-fef25d6a35d23f885937b087ed7642b327279df5.zip |
Make the config parser more robust
We add some additional checks into the config parser's
node_section_index, node_traverse and node_set_str functions. In
particular, we check if the requested node is of scalar or complex type
and whether this matches the value found in the config. If it does not
match, then a warning is issued appropriately and the config is
corrected.
Diffstat (limited to 'src/lib-config')
-rw-r--r-- | src/lib-config/get.c | 48 | ||||
-rw-r--r-- | src/lib-config/set.c | 6 |
2 files changed, 50 insertions, 4 deletions
diff --git a/src/lib-config/get.c b/src/lib-config/get.c index e0d988d0..53d744da 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -54,7 +54,6 @@ CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, con node = key == NULL ? NULL : config_node_find(parent, key); if (node != NULL) { - g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL); nindex = g_slist_index(parent->value, node); if (index >= 0 && nindex != index && nindex <= g_slist_length(parent->value)) { @@ -62,7 +61,25 @@ CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, con parent->value = g_slist_remove(parent->value, node); parent->value = g_slist_insert(parent->value, node, index); } - return node; + if (!is_node_list(node)) { + int show_error = 0; + + if (new_type != -1) { + config_node_remove(rec, parent, node); + node = NULL; + show_error = 1; + } else if (!g_hash_table_contains(rec->cache_nodes, node)) { + g_hash_table_insert(rec->cache_nodes, node, NULL); + show_error = 1; + } + if (show_error) + g_critical("Expected %s node at `..%s/%s' was of scalar type. Corrupt config?", + new_type == NODE_TYPE_LIST ? "list" : new_type == NODE_TYPE_BLOCK ? "block" : "section", + parent->key, key); + } else { + g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL); + return node; + } } if (new_type == -1) @@ -91,7 +108,21 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea /* check if it already exists in cache */ node = g_hash_table_lookup(rec->cache, section); - if (node != NULL) return node; + if (node != NULL) { + if (create) { + const char *path = strrchr(section, '/'); + if (path == NULL) path = section; + else path++; + new_type = *path == '(' ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + if (node->type != new_type) { + g_critical("Expected %s node at `%s' was of %s type. Corrupt config?", + new_type == NODE_TYPE_LIST ? "list" : "block", section, + node->type == NODE_TYPE_LIST ? "list" : "block"); + node->type = new_type; + } + } + return node; + } new_type = -1; @@ -99,7 +130,16 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea list = g_strsplit(section, "/", -1); for (tmp = list; *tmp != NULL; tmp++) { is_list = **tmp == '('; - if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + if (create) { + CONFIG_NODE *tmpnode; + + new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + tmpnode = config_node_find(node, *tmp + is_list); + if (tmpnode != NULL && tmpnode->type != new_type) { + g_critical("Expected %s node at `%s' was of scalar type. Corrupt config?", is_list ? "list" : "block", section); + config_node_remove(rec, node, tmpnode); + } + } node = config_node_section(rec, node, *tmp + is_list, new_type); if (node == NULL) { diff --git a/src/lib-config/set.c b/src/lib-config/set.c index 61a101fb..5c187035 100644 --- a/src/lib-config/set.c +++ b/src/lib-config/set.c @@ -104,6 +104,12 @@ void config_node_set_str(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, return; } + if (node != NULL && !has_node_value(node)) { + g_critical("Expected scalar node at `..%s/%s' was of complex type. Corrupt config?", + parent->key, key); + config_node_remove(rec, parent, node); + node = NULL; + } if (node != NULL) { if (strcmp(node->value, value) == 0) return; |