From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Jun 2020 17:46:14 +0000 (+0200) Subject: basic/set: add set_ensure_consume() X-Git-Tag: v246-rc1~105^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fcc1d0315d335ba31d85d6023c79d6404c62e167;p=thirdparty%2Fsystemd.git basic/set: add set_ensure_consume() This combines set_ensure_allocated() with set_consume(). The cool thing is that because we know the hash ops, we can correctly free the item if appropriate. Similarly to set_consume(), the goal is to simplify handling of the case where the item needs to be freed on error and if already present in the set. --- diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index c876662a0bf..ae3235d5185 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1257,6 +1257,20 @@ int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key H return set_put(*s, key); } +int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS) { + int r; + + r = _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_PASS_ARGS); + if (r <= 0) { + if (hash_ops && hash_ops->free_key) + hash_ops->free_key(key); + else + free(key); + } + + return r; +} + int hashmap_replace(Hashmap *h, const void *key, void *value) { struct swap_entries swap; struct plain_hashmap_entry *e; diff --git a/src/basic/set.h b/src/basic/set.h index cdc4abaa42f..3684a00f78c 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -123,6 +123,9 @@ static inline char **set_get_strv(Set *s) { int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS); #define set_ensure_put(s, hash_ops, key) _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS) +int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS); +#define set_ensure_consume(s, hash_ops, key) _set_ensure_consume(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS) + int set_consume(Set *s, void *value); int set_put_strdup(Set **s, const char *p); int set_put_strdupv(Set **s, char **l); diff --git a/src/test/test-set.c b/src/test/test-set.c index 7213abda01c..d3e6de79789 100644 --- a/src/test/test-set.c +++ b/src/test/test-set.c @@ -128,6 +128,28 @@ static void test_set_ensure_put(void) { assert_se(set_size(m) == 2); } +static void test_set_ensure_consume(void) { + _cleanup_set_free_ Set *m = NULL; + char *s, *t; + + assert_se(s = strdup("a")); + assert_se(set_ensure_consume(&m, &string_hash_ops_free, s) == 1); + + assert_se(t = strdup("a")); + assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0); + + assert_se(t = strdup("a")); + assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0); + + assert_se(t = strdup("b")); + assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 1); + + assert_se(t = strdup("b")); + assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0); + + assert_se(set_size(m) == 2); +} + int main(int argc, const char *argv[]) { test_set_steal_first(); test_set_free_with_destructor(); @@ -137,6 +159,7 @@ int main(int argc, const char *argv[]) { test_set_put_strdupv(); test_set_ensure_allocated(); test_set_ensure_put(); + test_set_ensure_consume(); return 0; } diff --git a/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network b/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network new file mode 100644 index 00000000000..ed7bdabfd18 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dns-trust-anchor-duplicate.network @@ -0,0 +1,2 @@ +[Network] +DNSSECNegativeTrustAnchors=i i \ No newline at end of file