]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: fix virSocketAddrMask() when source and result are the same object
authorLaine Stump <laine@redhat.com>
Sun, 4 Aug 2024 04:35:52 +0000 (00:35 -0400)
committerLaine Stump <laine@redhat.com>
Sat, 21 Sep 2024 18:37:54 +0000 (14:37 -0400)
Many years ago (2011), virSocketAddrMask() had caused a bug by failing
to initialize an IPv6-specific field in the result virSocketAddr. This
was fixed by memset(0)ing the entire result (*network) at the
beginning of the function (thus making sure anything and everything
was initialized).

The problem is that virSocketAddrMask() has a comment above it that
says that the source (addr) and destination (network) arguments can
point to the same virSocketAddr. But in that case, the
memset(*network, 0) at the top of the function is actually doing a
memset(*addr, 0), and so there is nothing left for all the assignments
to copy except a giant field of 0's.

Fortunately in the 13 years since the memset was added, nobody has
ever called virSocketAddrMask() with addr and network being the same.

This patch makes the code agree with the comment by copying/masking
into a local virSocketAddr (which is initialized to all 0) and then
copying that to *network after it's finished assigning things from
addr.

Fixes: ba08c5932e556aa4f5101357127a6224c40e5ebe
Signed-off-by: Laine Stump <laine@redhat.com>
src/util/virsocketaddr.c

index 0a1ae1ac5fb556cb385e5beaa800cce5dba75a46..60d8071da7406b5c9e89485aa0b813619476fb0d 100644 (file)
@@ -685,31 +685,34 @@ virSocketAddrMask(const virSocketAddr *addr,
                   const virSocketAddr *netmask,
                   virSocketAddr *network)
 {
-    memset(network, 0, sizeof(*network));
+    virSocketAddr tmp = { 0 };
+
     if (addr->data.stor.ss_family != netmask->data.stor.ss_family) {
         network->data.stor.ss_family = AF_UNSPEC;
         return -1;
     }
 
     if (addr->data.stor.ss_family == AF_INET) {
-        network->data.inet4.sin_addr.s_addr
+        tmp.data.inet4.sin_addr.s_addr
             = (addr->data.inet4.sin_addr.s_addr
                & netmask->data.inet4.sin_addr.s_addr);
-        network->data.inet4.sin_port = 0;
-        network->data.stor.ss_family = AF_INET;
-        network->len = addr->len;
+        tmp.data.inet4.sin_port = 0;
+        tmp.data.stor.ss_family = AF_INET;
+        tmp.len = addr->len;
+        *network = tmp;
         return 0;
     }
     if (addr->data.stor.ss_family == AF_INET6) {
         size_t i;
         for (i = 0; i < 16; i++) {
-            network->data.inet6.sin6_addr.s6_addr[i]
+            tmp.data.inet6.sin6_addr.s6_addr[i]
                 = (addr->data.inet6.sin6_addr.s6_addr[i]
                    & netmask->data.inet6.sin6_addr.s6_addr[i]);
         }
-        network->data.inet6.sin6_port = 0;
-        network->data.stor.ss_family = AF_INET6;
-        network->len = addr->len;
+        tmp.data.inet6.sin6_port = 0;
+        tmp.data.stor.ss_family = AF_INET6;
+        tmp.len = addr->len;
+        *network = tmp;
         return 0;
     }
     network->data.stor.ss_family = AF_UNSPEC;