[PATCH] intl: avoid alloca for arbitrary sizes (bug 32380)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Nov 20 12:37:57 GMT 2024



On 20/11/24 06:44, Andreas Schwab wrote:
> Use malloc for the copy of the domain name and the category value, which
> can both be of arbitrary size.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  intl/dcigettext.c | 51 +++++++++++------------------------------------
>  1 file changed, 12 insertions(+), 39 deletions(-)
> 
> diff --git a/intl/dcigettext.c b/intl/dcigettext.c
> index 70ba4a547f..776186785a 100644
> --- a/intl/dcigettext.c
> +++ b/intl/dcigettext.c
> @@ -374,34 +374,7 @@ static const char *get_output_charset (struct binding *domainbinding);
>  #ifdef HAVE_ALLOCA
>  /* Nothing has to be done.  */
>  # define freea(p) /* nothing */
> -# define ADD_BLOCK(list, address) /* nothing */
> -# define FREE_BLOCKS(list) /* nothing */
>  #else
> -struct block_list
> -{
> -  void *address;
> -  struct block_list *next;
> -};
> -# define ADD_BLOCK(list, addr)						      \
> -  do {									      \
> -    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
> -    /* If we cannot get a free block we cannot add the new element to	      \
> -       the list.  */							      \
> -    if (newp != NULL) {							      \
> -      newp->address = (addr);						      \
> -      newp->next = (list);						      \
> -      (list) = newp;							      \
> -    }									      \
> -  } while (0)
> -# define FREE_BLOCKS(list)						      \
> -  do {									      \
> -    while (list != NULL) {						      \
> -      struct block_list *old = list;					      \
> -      list = list->next;						      \
> -      free (old->address);						      \
> -      free (old);							      \
> -    }									      \
> -  } while (0)
>  # undef alloca
>  # define alloca(size) (malloc (size))
>  # define freea(p) free (p)
> @@ -483,17 +456,14 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
>  	    int plural, unsigned long int n, int category)
>  #endif
>  {
> -#ifndef HAVE_ALLOCA
> -  struct block_list *block_list = NULL;
> -#endif
>    struct loaded_l10nfile *domain;
>    struct binding *binding;
>    const char *categoryname;
>    const char *categoryvalue;
>    const char *dirname;
>    char *xdirname = NULL;
> -  char *xdomainname;
> -  char *single_locale;
> +  char *xdomainname = NULL;
> +  char *single_locale = NULL;
>    char *retval;
>    size_t retlen;
>    int saved_errno;
> @@ -648,18 +618,19 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
>  #endif
>  
>    domainname_len = strlen (domainname);
> -  xdomainname = (char *) alloca (strlen (categoryname)
> +  xdomainname = (char *) malloc (strlen (categoryname)
>  				 + domainname_len + 5);
> -  ADD_BLOCK (block_list, xdomainname);
> +  if (xdomainname == NULL)
> +    goto return_untranslated;
>  
>    stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
>  			    domainname, domainname_len),
>  	  ".mo");
>  
>    /* Creating working area.  */
> -  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
> -  ADD_BLOCK (block_list, single_locale);
> -
> +  single_locale = (char *) malloc (strlen (categoryvalue) + 1);
> +  if (single_locale == NULL)
> +    goto return_untranslated;
>  
>    /* Search for the given string.  This is a loop because we perhaps
>       got an ordered list of languages to consider for the translation.  */
> @@ -748,7 +719,8 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
>  	      /* Found the translation of MSGID1 in domain DOMAIN:
>  		 starting at RETVAL, RETLEN bytes.  */
>  	      free (xdirname);
> -	      FREE_BLOCKS (block_list);
> +	      free (xdomainname);
> +	      free (single_locale);
>  	      if (foundp == NULL)
>  		{
>  		  /* Create a new entry and add it to the search tree.  */
> @@ -832,7 +804,8 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
>   return_untranslated:
>    /* Return the untranslated MSGID.  */
>    free (xdirname);
> -  FREE_BLOCKS (block_list);
> +  free (xdomainname);
> +  free (single_locale);
>    gl_rwlock_unlock (_nl_state_lock);
>  #ifdef _LIBC
>    __libc_rwlock_unlock (__libc_setlocale_lock);



More information about the Libc-alpha mailing list