[PATCH] printf_fp: Get rid of alloca.

Joe Simmons-Talbott josimmon@redhat.com
Mon Aug 28 20:36:52 GMT 2023


Ping.

On Wed, Jul 05, 2023 at 01:19:38PM -0400, Joe Simmons-Talbott wrote:
> Replace unbounded alloca calls with scratch_buffers to avoid potential
> stack overflow.
> ---
>  stdio-common/printf_fp.c | 59 ++++++++++++++++++++++++++++------------
>  1 file changed, 41 insertions(+), 18 deletions(-)
> 
> diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
> index 6f22985ba1..9d6925a624 100644
> --- a/stdio-common/printf_fp.c
> +++ b/stdio-common/printf_fp.c
> @@ -28,6 +28,7 @@
>  #include <gmp-mparam.h>
>  #include <gmp.h>
>  #include <ieee754.h>
> +#include <scratch_buffer.h>
>  #include <stdlib/gmp-impl.h>
>  #include <stdlib/longlong.h>
>  #include <stdlib/fpioconst.h>
> @@ -181,8 +182,15 @@ __printf_fp_buffer_1 (struct __printf_buffer *buf, locale_t loc,
>  
>    /* Buffer in which we produce the output.  */
>    char *wbuffer = NULL;
> -  /* Flag whether wbuffer and buffer are malloc'ed or not.  */
> -  int buffer_malloced = 0;
> +
> +  struct scratch_buffer sbuf_frac;
> +  scratch_buffer_init (&sbuf_frac);
> +  struct scratch_buffer sbuf_tmp;
> +  scratch_buffer_init (&sbuf_tmp);
> +  struct scratch_buffer sbuf_scale;
> +  scratch_buffer_init (&sbuf_scale);
> +  struct scratch_buffer sbuf_wbuffer;
> +  scratch_buffer_init (&sbuf_wbuffer);
>  
>    p.expsign = 0;
>  
> @@ -268,9 +276,27 @@ __printf_fp_buffer_1 (struct __printf_buffer *buf, locale_t loc,
>  			     + (GREATER_MANT_DIG / BITS_PER_MP_LIMB > 2
>  				? 8 : 4))
>  			    * sizeof (mp_limb_t);
> -    p.frac = (mp_limb_t *) alloca (bignum_size);
> -    p.tmp = (mp_limb_t *) alloca (bignum_size);
> -    p.scale = (mp_limb_t *) alloca (bignum_size);
> +    
> +    if (!scratch_buffer_set_array_size (&sbuf_frac, 1, bignum_size))
> +      {
> +        __printf_buffer_mark_failed (buf);
> +        goto free_mem_out;
> +      }
> +    p.frac = sbuf_frac.data;
> +
> +    if (!scratch_buffer_set_array_size (&sbuf_tmp, 1, bignum_size))
> +      {
> +        __printf_buffer_mark_failed (buf);
> +        goto free_mem_out;
> +      }
> +    p.tmp = sbuf_tmp.data;
> +
> +    if (!scratch_buffer_set_array_size (&sbuf_scale, 1, bignum_size))
> +      {
> +        __printf_buffer_mark_failed (buf);
> +        goto free_mem_out;
> +      }
> +    p.scale = sbuf_scale.data;
>    }
>  
>    /* We now have to distinguish between numbers with positive and negative
> @@ -744,19 +770,13 @@ __printf_fp_buffer_1 (struct __printf_buffer *buf, locale_t loc,
>  	return;
>        }
>      size_t wbuffer_to_alloc = 2 + chars_needed;
> -    buffer_malloced = ! __libc_use_alloca (wbuffer_to_alloc);
> -    if (__builtin_expect (buffer_malloced, 0))
> +    if (!scratch_buffer_set_array_size (&sbuf_wbuffer, 1, wbuffer_to_alloc))
>        {
> -	wbuffer = malloc (wbuffer_to_alloc);
> -	if (wbuffer == NULL)
> -	  {
> -	    /* Signal an error to the caller.  */
> -	    __printf_buffer_mark_failed (buf);
> -	    return;
> -	  }
> +	/* Signal an error to the caller.  */
> +	__printf_buffer_mark_failed (buf);
> +	goto free_mem_out;
>        }
> -    else
> -      wbuffer = alloca (wbuffer_to_alloc);
> +    wbuffer = sbuf_wbuffer.data;
>      wcp = wstartp = wbuffer + 2;	/* Let room for rounding.  */
>  
>      /* Do the real work: put digits in allocated buffer.  */
> @@ -1025,8 +1045,11 @@ __printf_fp_buffer_1 (struct __printf_buffer *buf, locale_t loc,
>        __printf_buffer_pad (buf, info->pad, width);
>    }
>  
> -  if (buffer_malloced)
> -    free (wbuffer);
> +free_mem_out:
> +  scratch_buffer_free (&sbuf_frac);
> +  scratch_buffer_free (&sbuf_tmp);
> +  scratch_buffer_free (&sbuf_scale);
> +  scratch_buffer_free (&sbuf_wbuffer);
>  }
>  
>  /* ASCII to localization translation.  Multibyte version.  */
> -- 
> 2.39.2
> 



More information about the Libc-alpha mailing list