1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

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.
This commit is contained in:
Ailin Nemui 2015-02-17 09:46:52 +01:00
parent 1e4f7e6324
commit fef25d6a35
2 changed files with 50 additions and 4 deletions

View File

@ -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); node = key == NULL ? NULL : config_node_find(parent, key);
if (node != NULL) { if (node != NULL) {
g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL);
nindex = g_slist_index(parent->value, node); nindex = g_slist_index(parent->value, node);
if (index >= 0 && nindex != index && if (index >= 0 && nindex != index &&
nindex <= g_slist_length(parent->value)) { nindex <= g_slist_length(parent->value)) {
@ -62,8 +61,26 @@ 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_remove(parent->value, node);
parent->value = g_slist_insert(parent->value, node, index); parent->value = g_slist_insert(parent->value, node, index);
} }
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; return node;
} }
}
if (new_type == -1) if (new_type == -1)
return NULL; return NULL;
@ -91,7 +108,21 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea
/* check if it already exists in cache */ /* check if it already exists in cache */
node = g_hash_table_lookup(rec->cache, section); 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; 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); list = g_strsplit(section, "/", -1);
for (tmp = list; *tmp != NULL; tmp++) { for (tmp = list; *tmp != NULL; tmp++) {
is_list = **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); node = config_node_section(rec, node, *tmp + is_list, new_type);
if (node == NULL) { if (node == NULL) {

View File

@ -104,6 +104,12 @@ void config_node_set_str(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key,
return; 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 (node != NULL) {
if (strcmp(node->value, value) == 0) if (strcmp(node->value, value) == 0)
return; return;