mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 01:33:36 +08:00
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.
This commit is contained in:
parent
47311cca31
commit
ab545460b0
@ -374,34 +374,7 @@ static const char *get_output_charset (struct binding *domainbinding);
|
|||||||
#ifdef HAVE_ALLOCA
|
#ifdef HAVE_ALLOCA
|
||||||
/* Nothing has to be done. */
|
/* Nothing has to be done. */
|
||||||
# define freea(p) /* nothing */
|
# define freea(p) /* nothing */
|
||||||
# define ADD_BLOCK(list, address) /* nothing */
|
|
||||||
# define FREE_BLOCKS(list) /* nothing */
|
|
||||||
#else
|
#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
|
# undef alloca
|
||||||
# define alloca(size) (malloc (size))
|
# define alloca(size) (malloc (size))
|
||||||
# define freea(p) free (p)
|
# 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)
|
int plural, unsigned long int n, int category)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifndef HAVE_ALLOCA
|
|
||||||
struct block_list *block_list = NULL;
|
|
||||||
#endif
|
|
||||||
struct loaded_l10nfile *domain;
|
struct loaded_l10nfile *domain;
|
||||||
struct binding *binding;
|
struct binding *binding;
|
||||||
const char *categoryname;
|
const char *categoryname;
|
||||||
const char *categoryvalue;
|
const char *categoryvalue;
|
||||||
const char *dirname;
|
const char *dirname;
|
||||||
char *xdirname = NULL;
|
char *xdirname = NULL;
|
||||||
char *xdomainname;
|
char *xdomainname = NULL;
|
||||||
char *single_locale;
|
char *single_locale = NULL;
|
||||||
char *retval;
|
char *retval;
|
||||||
size_t retlen;
|
size_t retlen;
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
@ -648,18 +618,19 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
domainname_len = strlen (domainname);
|
domainname_len = strlen (domainname);
|
||||||
xdomainname = (char *) alloca (strlen (categoryname)
|
xdomainname = (char *) malloc (strlen (categoryname)
|
||||||
+ domainname_len + 5);
|
+ domainname_len + 5);
|
||||||
ADD_BLOCK (block_list, xdomainname);
|
if (xdomainname == NULL)
|
||||||
|
goto return_untranslated;
|
||||||
|
|
||||||
stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
|
stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
|
||||||
domainname, domainname_len),
|
domainname, domainname_len),
|
||||||
".mo");
|
".mo");
|
||||||
|
|
||||||
/* Creating working area. */
|
/* Creating working area. */
|
||||||
single_locale = (char *) alloca (strlen (categoryvalue) + 1);
|
single_locale = (char *) malloc (strlen (categoryvalue) + 1);
|
||||||
ADD_BLOCK (block_list, single_locale);
|
if (single_locale == NULL)
|
||||||
|
goto return_untranslated;
|
||||||
|
|
||||||
/* Search for the given string. This is a loop because we perhaps
|
/* Search for the given string. This is a loop because we perhaps
|
||||||
got an ordered list of languages to consider for the translation. */
|
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:
|
/* Found the translation of MSGID1 in domain DOMAIN:
|
||||||
starting at RETVAL, RETLEN bytes. */
|
starting at RETVAL, RETLEN bytes. */
|
||||||
free (xdirname);
|
free (xdirname);
|
||||||
FREE_BLOCKS (block_list);
|
free (xdomainname);
|
||||||
|
free (single_locale);
|
||||||
if (foundp == NULL)
|
if (foundp == NULL)
|
||||||
{
|
{
|
||||||
/* Create a new entry and add it to the search tree. */
|
/* 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_untranslated:
|
||||||
/* Return the untranslated MSGID. */
|
/* Return the untranslated MSGID. */
|
||||||
free (xdirname);
|
free (xdirname);
|
||||||
FREE_BLOCKS (block_list);
|
free (xdomainname);
|
||||||
|
free (single_locale);
|
||||||
gl_rwlock_unlock (_nl_state_lock);
|
gl_rwlock_unlock (_nl_state_lock);
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
__libc_rwlock_unlock (__libc_setlocale_lock);
|
__libc_rwlock_unlock (__libc_setlocale_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user