(-cc: my @google.com email)
Hi,

Junio C Hamano wrote:

> Subject: sideband: do not read beyond the end of input
>
> The caller of maybe_colorize_sideband() gives a counted buffer
> <src,n>, but the callee checked *src as if it were a NUL terminated
> buffer.  If src[] had all isspace() bytes in it, we would have made
> n negative, and then (1) called number of strncasecmp() to see if
> the remaining bytes in src[] matched keywords, reading beyond the
> end of the array, and/or (2) called strbuf_add() with negative
> count, most likely triggering the "you want to use way too much
> memory" error due to unsigned integer overflow.
>
> Signed-off-by: Junio C Hamano <gits...@pobox.com>
> ---
>  sideband.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)

This indeed avoids the "you want to use way too much memory" error
when I apply it.

> --- a/sideband.c
> +++ b/sideband.c
> @@ -75,7 +75,7 @@ static void maybe_colorize_sideband(struct strbuf *dest, 
> const char *src, int n)

Not about this patch: should the 'n' parameter be a size_t instead of
an int?  It doesn't matter in practice (since the caller has an int,
it can never be more than INT_MAX) but it might make the intent
clearer.

Based on inspecting the caller, using an int seems fine.

>               return;
>       }
>  
> -     while (isspace(*src)) {
> +     while (0 < n && isspace(*src)) {

Yes, we need to check 'n && isspace(*src)' to avoid overflowing the
buffer if it consists entirely of spaces.

>               strbuf_addch(dest, *src);
>               src++;
>               n--;
> @@ -84,6 +84,9 @@ static void maybe_colorize_sideband(struct strbuf *dest, 
> const char *src, int n)
>       for (i = 0; i < ARRAY_SIZE(keywords); i++) {
>               struct keyword_entry *p = keywords + i;
>               int len = strlen(p->keyword);
> +
> +             if (n <= len)
> +                     continue;

Using <= instead of < since we look at the character after the word as
well.  Good.

>               /*
>                * Match case insensitively, so we colorize output from existing
>                * servers regardless of the case that they use for their
>                * messages. We only highlight the word precisely, so
>                * "successful" stays uncolored.
>                */
>               if (!strncasecmp(p->keyword, src, len) && !isalnum(src[len])) {

Not about this patch: should this check "&& src[len] == ':'" instead,
as discussed upthread?

> @@ -100,8 +103,8 @@ static void maybe_colorize_sideband(struct strbuf *dest, 
> const char *src, int n)
>               }
>       }
>  
> -     strbuf_add(dest, src, n);
> +     if (0 < n)
> +             strbuf_add(dest, src, n);

This check seems unnecessary.  strbuf_add can cope fine with !n.
Should we put

        assert(n >= 0);

or even

        if (n < 0)
                BUG();

instead, since the earlier part of the fix guarantees that n >= 0?

Thanks for the careful work.  With or without such a change,
Reviewed-by: Jonathan Nieder <jrnie...@gmail.com>

Thanks.

Reply via email to