]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Only copy the name data after we know its actual length
authorMark Andrews <marka@isc.org>
Mon, 15 Jan 2024 00:47:13 +0000 (11:47 +1100)
committerOndřej Surý <ondrej@isc.org>
Wed, 17 Apr 2024 15:14:34 +0000 (17:14 +0200)
This prevents TSAN errors with the ncache code where the trust byte
access needs to be protected by a lock.  The old code copied the
entire region before determining where the name ended.  We now
determine where the name ends then copy just that data and in doing
so avoid reading the trust byte.

lib/dns/name.c

index ce3b78be9bd2f9ba32cb848eb5ca1a9d4c78f015..9bca9ed7a0aad745a726c2fc54469dbbbf111e6c 100644 (file)
@@ -716,7 +716,7 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
        unsigned char *offsets;
        dns_offsets_t odata;
        unsigned int len;
-       isc_region_t r2;
+       isc_region_t r2 = { .base = NULL, .length = 0 };
 
        /*
         * Make 'name' refer to region 'r'.
@@ -728,6 +728,7 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
 
        INIT_OFFSETS(name, offsets, odata);
 
+       name->ndata = r->base;
        if (name->buffer != NULL) {
                isc_buffer_clear(name->buffer);
                isc_buffer_availableregion(name->buffer, &r2);
@@ -735,13 +736,8 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
                if (len > DNS_NAME_MAXWIRE) {
                        len = DNS_NAME_MAXWIRE;
                }
-               if (len != 0) {
-                       memmove(r2.base, r->base, len);
-               }
-               name->ndata = r2.base;
                name->length = len;
        } else {
-               name->ndata = r->base;
                name->length = (r->length <= DNS_NAME_MAXWIRE)
                                       ? r->length
                                       : DNS_NAME_MAXWIRE;
@@ -755,6 +751,15 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
        }
 
        if (name->buffer != NULL) {
+               /*
+                * name->length has been updated by set_offsets to the actual
+                * length of the name data so we can now copy the actual name
+                * data and not anything after it.
+                */
+               if (name->length > 0) {
+                       memmove(r2.base, r->base, name->length);
+               }
+               name->ndata = r2.base;
                isc_buffer_add(name->buffer, name->length);
        }
 }