From f2f5958148016b8f92085d2e98fcf94efce508bf Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 16 Aug 2013 06:55:15 +0200 Subject: udev/udevadm-hwdb.c: remove usage of qsort_r while theoretically a nice interface, qsort_r on GLIBC was implemented with a prototype that shuffles the argument order around when compared to the traditional BSD implementations, yielding in 2 separate incompatible implementations. even worse, the arguments are all of pointer type so one would not even notice that the order is wrong and so this would yield in crashes or silent memory corruption. thus musl does not implement it, because configure scripts would check for its existance and use it unconditionally, even when assuming the BSD version. a more portable solution is to use TLS via __thread, which any modern GCC should provide. (even 3.4.6 on x86/x86_64 does so). Signed-off-by: Anthony G. Basile --- src/udev/udevadm-hwdb.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 65ea866f4d..1026a7a66d 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -123,14 +123,20 @@ static void trie_node_cleanup(struct trie_node *node) { free(node); } -static int trie_values_cmp(const void *v1, const void *v2, void *arg) { + +static __thread void* trie_values_cmp_param; +static int trie_values_cmp(const void *v1, const void *v2) { const struct trie_value_entry *val1 = v1; const struct trie_value_entry *val2 = v2; - struct trie *trie = arg; + struct trie *trie = trie_values_cmp_param; return strcmp(trie->strings->buf + val1->key_off, trie->strings->buf + val2->key_off); } +static int trie_values_cmp_r(const void *v1, const void *v2, void* arg) { + trie_values_cmp_param = arg; + return trie_values_cmp(v1, v2); +} static int trie_node_add_value(struct trie *trie, struct trie_node *node, const char *key, const char *value) { @@ -150,7 +156,7 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, .value_off = v, }; - val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); + val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp_r, trie); if (val) { /* replace existing earlier key with new value */ val->value_off = v; @@ -167,7 +173,8 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, node->values[node->values_count].key_off = k; node->values[node->values_count].value_off = v; node->values_count++; - qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); + trie_values_cmp_param = trie; + qsort(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp); return 0; } -- cgit v1.2.3-54-g00ecf