I believe this one will work

-               if(memcmp(name,pp->name,len)==0 && (pp->name[len]==':' || 
pp->name[len]==0))
+               if(len <= strlen(pp->name) && memcmp(name,pp->name,len)==0 && 
(pp->name[len]==':' || pp->name[len]==0))

pp->name is a ':' separated list of dirs, except for dirN '\0' terminated

        dir1:dir2:...:dirN

we are checking if name length len is the first component in the list
if (len > strlen(the list)) then it can't be the first component
otherwise memcmp(name,pp->name,len) and pp->name[len] are safe to access

On Sun, 10 Jun 2012 13:21:55 +0200 Roland Mainz wrote:
> On Sat, Jun 9, 2012 at 11:49 AM, Roland Mainz <[email protected]> 
> wrote:
> > On Wed, Jun 6, 2012 at 4:43 PM, Roland Mainz <[email protected]> 
> > wrote:
> >> On Wed, Jun 6, 2012 at 3:53 PM, David Korn <[email protected]> wrote:
> >>> cc: [email protected]
> >>> Subject: Re: Random coredumps in |path_addcomp()| when testing 
> >>> ast-open.2012-05-31  on Solaris 11/AMD64/64bit ...
> >>> --------
> >>>
> >>> Do you know which test this shows up on?
> >>
> >> Currently these tests _randomly_ (in non-reproduceable ways) fail
> >> within  |path_addcomp()|:
> >> -- snip --
> >> attributes.sh
> >> comvar.sh
> >> sun_solaris_compoundvario.sh
> >> -- snip --
> >>
> >>> Do you know what PATH
> >>> you are runing with?
> >>
> >> Uhm... the default one set by "shtests" ?
> >
> > This still happens in ast-ksh.2012-06-06.
> >
> > I've narrowed it down a bit...  it happened only for 64bit builds in
> > multibyte locales (e.g. $ LC_ALL=ja_JP.UTF-8 shtests --locale ... #)
> > and "zh_CN.GB18030" was more affected (based on statistics) than the
> > *.UTF-8-based locales... but it turns out that this is something which
> > only contributes to crash by shifting the layout of mapped code pages
> > a bit but is not directly connected to the issue.
> >
> > After some digging I found this:
> > -- snip --
> > program terminated by signal SEGV (no mapping at the fault address)
> > 0xfffffd7ffbc0710b: memcmp+0x007b:      movq     
> > 0x0000000000000018(%rsi),%r10
> > (dbx) where
> > =>[1] memcmp(0xfffffd7ffb7a988a, 0xfffffd7ffb7c5fe8, 0x5d, 0x2,
> > 0xfffffd7ffb7ae000, 0x1), at 0xfffffd7ffbc0710b
> >  [2] path_addcomp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb994f2d
> >  [3] path_addpath(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb9955ff
> >  [4] path_init(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb9925e4
> >  [5] path_get(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb9926ae
> >  [6] sh_subshell(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb99b9c5
> >  [7] comsubst(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb97f71b
> >  [8] varsub(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb97ec4f
> >  [9] copyto(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb979ab3
> >  [10] sh_mactrim(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb9781ba
> >  [11] nv_setlist(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb981930
> >  [12] sh_exec(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb9a3863
> >  [13] exfile(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb94acca
> >  [14] sh_main(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffb949f4d
> >  [15] main(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x40a12a
> > (dbx) print (char*)0xfffffd7ffb7a988a
> > dbx: warning: unknown language, 'c' assumed
> > (char *) 18446741324854630538U = 0xfffffd7ffb7a988a
> > "/home/test001/ksh93/ast_ksh_20120606/build_i386_64bit_opt_extrabuiltins/./src/cmd/ksh93/tests"
> > (dbx) print (char *)0xfffffd7ffb7c5fe8
> > (char *) 18446741324854747112U = 0xfffffd7ffb7c5fe8 "/bin"
> > -- snip 0
> > The code uses |memcmp()| to compare two strings but uses the string
> > length (0x5d==93 bytes) of the first argument
> > ("/home/test001/ksh93/ast_ksh_20120606/build_i386_64bit_opt_extrabuiltins")
> > ... but the 2nd argument is the string "/bin" with only four bytes
> > (plus '\0') ...  if this sits near the end of a MMU page and
> > |memcpy()| searches beyond that page into something which is not
> > mapped or declared a "red zone page" (e.g. these are pages which are
> > used directly before and after |mmap()| areas to trigger SIGSEGV for
> > reads) then the process gets wallopped with the big SIGSEGV stick.
> >
> > A quick "hotfix" for the issue may be this patch...
> > -- snip --
> > diff -r -u build_i386_32bit_debug/src/cmd/ksh93/sh/path.c
> > build_i386_64bit_opt_extrabuiltins/src/cmd/ksh93/sh/path.c
> > --- build_i386_32bit_debug/src/cmd/ksh93/sh/path.c      Tue Jun  5 19:18:06 
> > 2012
> > +++ build_i386_64bit_opt_extrabuiltins/src/cmd/ksh93/sh/path.c  Sat
> > Jun  9 10:56:34 2012
> > @@ -1470,7 +1470,10 @@
> >                len = strlen(name);
> >        for(pp=first; pp; pp=pp->next)
> >        {
> > -               if(memcmp(name,pp->name,len)==0 && (pp->name[len]==':'
> > || pp->name[len]==0))
> > +#ifndef MIN
> > +#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
> > +#endif
> > +
> > if(memcmp(name,pp->name,MIN(len,(strlen(pp->name)+1)))==0 &&
> > (pp->name[len]==':' || pp->name[len]==0))
> >                {
> >                        pp->flags |= flag;
> >                        return(first);
> > -- snip --
> [snip]

> That patch was totally broken (in more than one way... sorry... ;-( )
> ... here is the correct one:
> -- snip --
> --- src/cmd/ksh93/sh/path.c      Tue Jun  5 19:18:06 2012
> +++ src/cmd/ksh93/sh/path.c  Sun Jun 10 11:22:05 2012
> @@ -1470,7 +1470,13 @@
>                 len = strlen(name);
>         for(pp=first; pp; pp=pp->next)
>         {
> -               if(memcmp(name,pp->name,len)==0 && (pp->name[len]==':'
> || pp->name[len]==0))
> +#ifndef MIN
> +#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
> +#endif
> +               size_t mlen = MIN(len, pp->len);
> +               if((memcmp(name,pp->name, mlen)==0) &&
> +                       (name[mlen]== 0) &&
> +                       (pp->name[mlen]==':' || pp->name[mlen]==0))
>                 {
>                         pp->flags |= flag;
>                         return(first);
> -- snip --
> ... but I'll try to make a slightly better one this night (I'm
> travelling today) by putting the |memcpy()| after the first two lines
> of comparisations to avoid having to call the more expensive (e.g.
> compared to a plain single-byte compare) |memcpy()| for each cycle of
> the loop...

> ----

> Bye,
> Roland

> -- 
>   __ .  . __
>  (o.\ \/ /.o) [email protected]
>   \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
>   /O /==\ O\  TEL +49 641 3992797
>  (;O/ \/ \O;)

_______________________________________________
ast-developers mailing list
[email protected]
https://mailman.research.att.com/mailman/listinfo/ast-developers

Reply via email to