diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2016-09-21 14:56:04 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2016-09-21 15:18:27 +0200 |
commit | 8bf9763656c9209f74cda460225da5a9939494cc (patch) | |
tree | 0c98c1679755cb810cfddba91034335c88248c7f /src/libsystemd/sd-hwdb | |
parent | 21dc02277d6f0844c1f7ab7ccb543b69848fff32 (diff) |
sd-hwdb: fix child/value offset calculation
It is not legal to use hard-coded types to calculate offsets. We must
always use the offsets of the hwdb header to calculate those. Otherwise,
we will break horribly if run on hwdb files written by other
implementations or written with future extensions.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'src/libsystemd/sd-hwdb')
-rw-r--r-- | src/libsystemd/sd-hwdb/sd-hwdb.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 062fa97b17..fb9522959f 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -97,15 +97,20 @@ static void linebuf_rem_char(struct linebuf *buf) { linebuf_rem(buf, 1); } -static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) { - return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size)); +static const struct trie_child_entry_f *trie_node_child(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { + const char *base = (const char *)node; + + base += le64toh(hwdb->head->node_size); + base += idx * le64toh(hwdb->head->child_entry_size); + return (const struct trie_child_entry_f *)base; } -static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) { +static const struct trie_value_entry_f *trie_node_value(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { const char *base = (const char *)node; base += le64toh(hwdb->head->node_size); base += node->children_count * le64toh(hwdb->head->child_entry_size); + base += idx * le64toh(hwdb->head->value_entry_size); return (const struct trie_value_entry_f *)base; } @@ -129,7 +134,7 @@ static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_ struct trie_child_entry_f search; search.c = c; - child = bsearch(&search, trie_node_children(hwdb, node), node->children_count, + child = bsearch(&search, (const char *)node + le64toh(hwdb->head->node_size), node->children_count, le64toh(hwdb->head->child_entry_size), trie_children_cmp_f); if (child) return trie_node_from_off(hwdb, child->child_off); @@ -177,7 +182,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t linebuf_add(buf, prefix + p, len); for (i = 0; i < node->children_count; i++) { - const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i]; + const struct trie_child_entry_f *child = trie_node_child(hwdb, node, i); linebuf_add_char(buf, child->c); err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search); @@ -188,8 +193,8 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) for (i = 0; i < le64toh(node->values_count); i++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off), - trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off)); + err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, i)->key_off), + trie_string(hwdb, trie_node_value(hwdb, node, i)->value_off)); if (err < 0) return err; } @@ -254,8 +259,8 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) { size_t n; for (n = 0; n < le64toh(node->values_count); n++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off), - trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off)); + err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, n)->key_off), + trie_string(hwdb, trie_node_value(hwdb, node, n)->value_off)); if (err < 0) return err; } |