On Thu, Jan 14, 2021 at 09:34:49AM -0500, Brad House wrote:
> While working on debugging an issue reported in c-ares, I noticed some test
> case failures in inet_net_pton().  I haven't evaluated most of them, however
> one stood out:
> 
> ../test/ares-test-internal.cc:150: Failure
>       Expected: -1
> To be equal to: inet_net_pton(24,"12:34::ff",&a6,sizeof(a6) - 1)
>       Which is: 128
> 
> This test expects inet_net_pton() to fail because the buffer provided was of
> insufficient size.
> 
> I'm not all that familiar with OpenBSD itself, a quick google search turned
> up this as the possible source:
> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/net/inet_net_pton.c
> 
> The 'size' parameter to inet_net_pton_ipv6() is *never* used:
> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/net/inet_net_pton.c#L206
> 
> I believe this failure ends up later causing other test failures due to
> memory corruption in the c-ares test cases.
> 
> 

Thanks for the report, this is a potential fix:

diff --git lib/libc/net/inet_net_pton.c lib/libc/net/inet_net_pton.c
index 2aaeac4048a..d7cc75e0092 100644
--- lib/libc/net/inet_net_pton.c
+++ lib/libc/net/inet_net_pton.c
@@ -205,9 +205,10 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t 
size)
 static int
 inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
 {
-       int     ret;
-       int     bits;
-       char    
buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")];
+       struct in6_addr  in6;
+       int              ret;
+       int              bits;
+       char             buf[INET6_ADDRSTRLEN + sizeof("/128")];
        char            *sep;
        const char      *errstr;
 
@@ -220,18 +221,24 @@ inet_net_pton_ipv6(const char *src, u_char *dst, size_t 
size)
        if (sep != NULL)
                *sep++ = '\0';
 
-       ret = inet_pton(AF_INET6, buf, dst);
+       ret = inet_pton(AF_INET6, buf, &in6);
        if (ret != 1)
                return (-1);
 
        if (sep == NULL)
-               return 128;
+               bits = 128;
+       else {
+               bits = strtonum(sep, 0, 128, &errstr);
+               if (errstr) {
+                       errno = EINVAL;
+                       return (-1);
+               }
+       }
 
-       bits = strtonum(sep, 0, 128, &errstr);
-       if (errstr) {
-               errno = EINVAL;
+       if ((bits + 7) / 8 > size) {
+               errno = EMSGSIZE;
                return (-1);
        }
-
-       return bits;
+       memcpy(dst, &in6.s6_addr, size);
+       return (bits);
 }


-- 
I'm not entirely sure you are real.

Reply via email to