[PATCH xserver/hw/xfree86/parser/scan.c] potential buffer overflow

vdb at picaros.org vdb at picaros.org
Wed Aug 31 05:15:43 PDT 2011


> Am 31.08.2011 07:06, schrieb vdb at picaros.org:
> > [PATCH xserver/hw/xfree86/parser/scan.c] potential buffer overflow
> > 
> > The patch below fixes a potential buffer overflow in xf86addComment().  
> > This occurs if  curlen > 0 && eol_seen == 0 && iscomment == 0 , as 
> > follows from the code:
> > 
> > char *xf86addComment(char *cur, char *add)
> > 
> > <...>
> > 
> >         len = strlen(add);
> >         endnewline = add[len - 1] == '\n';
> >         len +=  1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
> > 
> >         if ((str = realloc(cur, len + curlen)) == NULL)
> >                 return cur;
> > 
> >         cur = str;
> > 
> >         if (eol_seen || (curlen && !hasnewline))
> >                 cur[curlen++] = '\n';
> >         if (!iscomment)
> >                 cur[curlen++] = '#';
> >         strcpy(cur + curlen, add);
> >         if (!endnewline)
> >                 strcat(cur, "\n");
> > 
> > Signed-off-by: Servaas Vandenberghe
> > diff --git a/hw/xfree86/parser/scan.c b/hw/xfree86/parser/scan.c
> > index 1cff3bc..99b3257 100644
> > --- a/hw/xfree86/parser/scan.c
> > +++ b/hw/xfree86/parser/scan.c
> > @@ -1093,7 +1093,7 @@ char *
> >  xf86addComment(char *cur, char *add)
> >  {
> >  	char *str;
> > -	int len, curlen, iscomment, hasnewline = 0, endnewline;
> > +	int len, curlen, iscomment, hasnewline = 0, insnewline, endnewline;
> >  
> >  	if (add == NULL || add[0] == '\0')
> >  		return cur;
> > @@ -1118,14 +1118,23 @@ xf86addComment(char *cur, char *add)
> >  
> >  	len = strlen(add);
> >  	endnewline = add[len - 1] == '\n';
> > -	len +=  1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
> >  
> > -	if ((str = realloc(cur, len + curlen)) == NULL)
> > +	insnewline = eol_seen || (curlen && !hasnewline);
> > +	if (insnewline)
> > +		len++;
> > +	if (!iscomment)
> > +		len++;
> > +	if (!endnewline)
> > +		len++;
> > +
> > +	/* Allocate + 1 char for '\0' terminator. */
> > +	str = realloc(cur, curlen + len + 1);
> > +	if (!str)
> >  		return cur;
> >  
> >  	cur = str;
> >  
> > -	if (eol_seen || (curlen && !hasnewline))
> > +	if (insnewline)
> >  		cur[curlen++] = '\n';
> >  	if (!iscomment)
> >  		cur[curlen++] = '#';
> 
> 
> So far i understand is the code adding a commentstring ("#fusel") to a string ("blah")
> (stripping \n before .. ).

The code is actually inserting characters.  Simplifying, 

  if cur[], the current comment buffer, is not \n terminated ==> append \n

  if add[], the new comment, doesn't start with # ==> append # to cur[]

  then append add[] to cur[] via strcpy()

  if add is not \n terminated ==> strcat(cur, "\n")

The result cur[] thus looks like "#curmsg\n#addmsg\n".

> A more easy way could be using asprintf() like that
> 
> result=asprintf(&buf,"%s#%s\n",cur,add);
> free(cur); cur=result;

Yes, something like

  int err;
  const char *insnl, *inshash, *termnl;

  insnl = insnewline ? "\n" : "";
  inshash = iscomment ? "" : "#";
  termnl = endnewline ? "" : "\n";

  err = asprintf(&result, "%s%s%s%s%s", cur, insnl, inshash, add, termnl);
  if (err >= 0) {
    free(cur); 
    cur = result;
  }

would work.  But since I am not the author of this code I chose to stay as
close to the original work as possible.  Moreover, the code in parser/ 
seems to predate the use of asprintf() in Xorg.  IIRC asprintf() started 
appearing in 2010.

Just my opinion, Servaas Vandenberghe.


More information about the xorg-devel mailing list