[PATCH libX11 1/2] The validation of server responses avoids out of boundary accesses.

Julien Cristau jcristau at debian.org
Wed Oct 5 06:56:52 UTC 2016


Hi all,

Sorry I didn't get a chance to look at these before they went public...

On Sun, Sep 25, 2016 at 22:50:40 +0200, Matthieu Herrb wrote:

> From: Tobias Stoeckmann <tobias at stoeckmann.org>
> 
> v2: FontNames.c  return a NULL list whenever a single
> length field from the server is incohent.
> 
> Signed-off-by: Tobias Stoeckmann <tobias at stoeckmann.org>
> Reviewed-by: Matthieu Herrb <matthieu at herrb.eu>
> ---
>  src/FontNames.c | 23 +++++++++++++++++------
>  src/ListExt.c   | 12 ++++++++----
>  src/ModMap.c    |  3 ++-
>  3 files changed, 27 insertions(+), 11 deletions(-)
> 
> diff --git a/src/FontNames.c b/src/FontNames.c
> index 21dcafe..e55f338 100644
> --- a/src/FontNames.c
> +++ b/src/FontNames.c
> @@ -66,7 +66,7 @@ int *actualCount)	/* RETURN */
>  
>      if (rep.nFonts) {
>  	flist = Xmalloc (rep.nFonts * sizeof(char *));
> -	if (rep.length < (INT_MAX >> 2)) {
> +	if (rep.length > 0 && rep.length < (INT_MAX >> 2)) {
>  	    rlen = rep.length << 2;
>  	    ch = Xmalloc(rlen + 1);
>  	    /* +1 to leave room for last null-terminator */
> @@ -93,11 +93,22 @@ int *actualCount)	/* RETURN */
>  	    if (ch + length < chend) {
>  		flist[i] = ch + 1;  /* skip over length */
>  		ch += length + 1;  /* find next length ... */
> -		length = *(unsigned char *)ch;
> -		*ch = '\0';  /* and replace with null-termination */
> -		count++;
> -	    } else
> -		flist[i] = NULL;
> +		if (ch <= chend) {
> +		    length = *(unsigned char *)ch;
> +		    *ch = '\0';  /* and replace with null-termination */
> +		    count++;
> +		} else {
> +                    Xfree(flist);
> +                    flist = NULL;
> +                    count = 0;
> +                    break;
> +		}
> +	    } else {
> +                Xfree(flist);
> +                flist = NULL;
> +                count = 0;
> +                break;
> +            }
>  	}
>      }
>      *actualCount = count;

I believe these new error paths are missing Xfree(ch).

> diff --git a/src/ListExt.c b/src/ListExt.c
> index be6b989..0516e45 100644
> --- a/src/ListExt.c
> +++ b/src/ListExt.c
> @@ -55,7 +55,7 @@ char **XListExtensions(
>  
>  	if (rep.nExtensions) {
>  	    list = Xmalloc (rep.nExtensions * sizeof (char *));
> -	    if (rep.length < (INT_MAX >> 2)) {
> +	    if (rep.length > 0 && rep.length < (INT_MAX >> 2)) {
>  		rlen = rep.length << 2;
>  		ch = Xmalloc (rlen + 1);
>                  /* +1 to leave room for last null-terminator */
> @@ -80,9 +80,13 @@ char **XListExtensions(
>  		if (ch + length < chend) {
>  		    list[i] = ch+1;  /* skip over length */
>  		    ch += length + 1; /* find next length ... */
> -		    length = *ch;
> -		    *ch = '\0'; /* and replace with null-termination */
> -		    count++;
> +		    if (ch <= chend) {
> +			length = *ch;
> +			*ch = '\0'; /* and replace with null-termination */
> +			count++;
> +		    } else {
> +			list[i] = NULL;
> +		    }
>  		} else
>  		    list[i] = NULL;
>  	    }

This might have been more readable by just replacing the previous
if (ch + length < chend)
with
if (ch + length + 1 < chend)
?

Cheers,
Julien


More information about the xorg-devel mailing list