From ab545460b019fe66c90af5c78338ba80f62a4bda Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Wed, 20 Nov 2024 10:01:29 +0100 Subject: [PATCH] intl: avoid alloca for arbitrary sizes (bug 32380) Use malloc for the copy of the domain name and the category value, which can both be of arbitrary size. --- 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);