On Mon, Jan 18, 2021 at 10:59:36AM +0100, Florian Obser wrote:
> 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:

I would have expected others to chime in, but since that didn't happen:

ok tb


> 
> 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