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:
parent
1e4f7e6324
commit
fef25d6a35
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user