RE: story about lost %ebx (stack corruption in inet_aton ?)

From: Yuriy Tsibizov <Yuriy.Tsibizov_at_gfk.com>
Date: Tue, 18 Dec 2007 12:00:38 +0300
 

> -----Original Message-----
> From: David Schultz [mailto:das_at_FreeBSD.ORG] 
> Sent: Tuesday, December 18, 2007 11:53 AM
> To: Yuriy Tsibizov
> Cc: freebsd-current_at_FreeBSD.ORG
> Subject: Re: story about lost %ebx (stack corruption in inet_aton ?)
> 
> On Tue, Dec 18, 2007, Yuriy Tsibizov wrote:
> > > My first impression was that there is a bug in gcc 
> compiler on 7-BETA
> > > and 8-CURRENT (i386 only, and only if optimization is 
> enabled), but it
> > > seems to be incorrect. Most probably source is stack corruption in
> > > inet_aton()
> > 
> > mistyped, it is inet_network() that fails...
> > 
> > testcase:
> > 
> > #include <sys/cdefs.h>
> > #include <sys/types.h>
> > #include <netinet/in.h>
> > #include <arpa/inet.h>
> > #include <ctype.h>
> > 
> > int main(){
> > int val;
> > char s[]="10.10.0.10.0/12"; // four dots here!
> > char *q;
> > 
> >         q = strchr(s,'/');
> >         if (q) {
> >                 *q = '\0';
> >                 if ((val = inet_network(s)) != INADDR_NONE) {
> >                         printf("OK\n");
> >                         return (0);
> >                 }
> >                 printf("q= %08x\n", q);
> >                 *q = '/';
> >         }
> > }
> > 
> > 
> > (should be built with -O1 or -O2 to expose that bug)
> 
> This isn't the compiler's fault. It looks like an off-by-one error
> in BIND 9.4.1 that's clobbering the saved %ebx on the stack.
> Try this:
> 
> Index: lib/libc/inet/inet_network.c
> ===================================================================
> RCS file: /usr/cvs/src/lib/libc/inet/inet_network.c,v
> retrieving revision 1.4
> diff -u -r1.4 inet_network.c
> --- lib/libc/inet/inet_network.c	3 Jun 2007 17:20:26 
> -0000	1.4
> +++ lib/libc/inet/inet_network.c	18 Dec 2007 08:50:08 -0000
> _at__at_ -83,7 +83,7 _at__at_
>  	if (!digit)
>  		return (INADDR_NONE);
>  	if (*cp == '.') {
> -		if (pp >= parts + 4 || val > 0xffU)
> +		if (pp >= parts + 3 || val > 0xffU)
>  			return (INADDR_NONE);
>  		*pp++ = val, cp++;
>  		goto again;
> 

should it be 
---------
--- inet_network.c.orig 2007-06-03 21:20:26.000000000 +0400
+++ inet_network.c      2007-12-18 11:11:33.000000000 +0300
_at__at_ -53,7 +53,7 _at__at_
 {
        in_addr_t val, base, n;
        char c;
-       in_addr_t parts[4], *pp = parts;
+       in_addr_t parts[5], *pp = parts;
        int i, digit;
 
 again:

-----------

because later
"
        n = pp - parts;
        if (n > 4U)
                return (INADDR_NONE);
"

Yuriy.
Received on Tue Dec 18 2007 - 07:59:55 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:24 UTC