[PATCH v4 2/2] stdio-common: Fix buffer overflow in scanf %mc [BZ #34008]

Florian Weimer fw@deneb.enyo.de
Mon Apr 6 09:00:26 GMT 2026


* Rocket Ma:

> * stdio-common/vfscanf-internal.c: When enlarging allocated buffer with
> format %mc or %mC, glibc allocates one byte less, leading to
> user-controlled one byte overflow. This commit fixes BZ #34008, or
> CVE-2026-5450. Unify newsize calculation of allocated buffer.
>
> Signed-off-by: Rocket Ma <marocketbd@gmail.com>
> ---
>  stdio-common/vfscanf-internal.c | 74 ++++++++++++++++++++-------------
>  1 file changed, 46 insertions(+), 28 deletions(-)
>
> diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c
> index 59fc8208aa..6bf2a55876 100644
> --- a/stdio-common/vfscanf-internal.c
> +++ b/stdio-common/vfscanf-internal.c
> @@ -265,6 +265,19 @@ char_buffer_add (struct char_buffer *buffer, CHAR_T ch)
>      *buffer->current++ = ch;
>  }
>  
> +/* Calculate the result size of expanded char array in %ms, %mS,
> +   %m[, %lm[, %mc or %mC. */
> +static __always_inline size_t
> +grow_to_fit (size_t oldsize, int need, int extra)
> +{
> +  /* extra = 0 if %m[cC], %m[cC] always have positive width */
> +  if ((extra && need < 0) || oldsize < need)
> +    return oldsize * 2;
> +  /* oldsize >= need:
> +     grow requested capacity and `extra' byte for `\0' */
> +  return oldsize + need + extra;
> +}

Thanks for working on this.

The last (extra) argument is constant.  I'd suggest two functions with
descriptive names instead (maybe grow_to_fit_for_fixed for the %c
family, and grow_to_fit_with_null for the %s/%[] family that perform
null termination).  The new functions probably shouldn't be inline, so
that the compiler can apply its heuristics.

As written, the interaction with the extra argument and a negative
need argument is not quite obvious from the function alone (code and
comments).  The function seems correct because need (called width in
the caller) can only be -1 for the %s/%[] case, where extra is 1.


More information about the Libc-alpha mailing list