]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dns-domain: tweak hash table comparison function for DNS names
authorLennart Poettering <lennart@poettering.net>
Thu, 12 Sep 2024 15:00:04 +0000 (17:00 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 23 Oct 2024 08:22:28 +0000 (10:22 +0200)
Currently, when comparing two DNS names when storing them in a
hashtable, and the DNS names are not actually valid we'll compare the
error codes.

This is not very smart however, since this means two invalid DNS names
that happen to be equally "invalid" will be considered identical, even
if their strings are entirely different.

Let's find a better solution for this niche case: let's simple compare
the domains as strings.

This matters in case of DNS label compression: if we already added added
an invalid DNS name into the label compression hash table, and lookup
any other invalid DNS name, this lookup will likely return what the
earlier one already returned, and that's confusing.

src/shared/dns-domain.c

index c9963ade93087a351196769a5059d108e7b9985f..6dc45a3dd1122f5690f6e5e7a4cf697b8f65e65c 100644 (file)
@@ -480,17 +480,17 @@ finish:
         return 0;
 }
 
-void dns_name_hash_func(const char *p, struct siphash *state) {
+void dns_name_hash_func(const char *name, struct siphash *state) {
         int r;
 
-        assert(p);
+        assert(name);
 
-        for (;;) {
+        for (const char *p = name;;) {
                 char label[DNS_LABEL_MAX+1];
 
                 r = dns_label_unescape(&p, label, sizeof label, 0);
                 if (r < 0)
-                        break;
+                        return string_hash_func(p, state); /* fallback for invalid DNS names */
                 if (r == 0)
                         break;
 
@@ -516,13 +516,13 @@ int dns_name_compare_func(const char *a, const char *b) {
         for (;;) {
                 char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
 
-                if (x == NULL && y == NULL)
+                if (!x && !y)
                         return 0;
 
                 r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
                 q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
                 if (r < 0 || q < 0)
-                        return CMP(r, q);
+                        return strcmp(a, b); /* if not valid DNS labels, then let's compare the whole strings as is */
 
                 r = ascii_strcasecmp_nn(la, r, lb, q);
                 if (r != 0)