[BZ #322]
Update. * intl/dcigettext.c (DCIGETTEXT): Protect tfind/tsearch calls. * intl/dcigettext.c (_nl_find_msg): Call _nl_load_domain also if decided < 0. * intl/finddomain.c (_nl_find_domain): Likewise. * intl/l10nflist.c (_nl_make_l10nflist): Initialize lock. * intl/loadinfo.h (struct loaded_l10nfile): Add lock element. * intl/loadmsgcat.c (_nl_load_domain): Set decided to 1 only once we are done. First set to -1 to signal initialization is ongoing. Protect against concurrent callers with recursive lock. duplicate address recognition does not copy junk. [BZ #322]
This commit is contained in:
parent
f6b90f4299
commit
ce7265c743
12
ChangeLog
12
ChangeLog
@ -1,11 +1,19 @@
|
|||||||
2004-09-25 Ulrich Drepper <drepper@redhat.com>
|
2004-09-25 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* intl/dcigettext.c (DCIGETTEXT): Protect tfind/tsearch calls.
|
||||||
|
* intl/dcigettext.c (_nl_find_msg): Call _nl_load_domain also if
|
||||||
|
decided < 0.
|
||||||
|
* intl/finddomain.c (_nl_find_domain): Likewise.
|
||||||
|
* intl/l10nflist.c (_nl_make_l10nflist): Initialize lock.
|
||||||
|
* intl/loadinfo.h (struct loaded_l10nfile): Add lock element.
|
||||||
|
* intl/loadmsgcat.c (_nl_load_domain): Set decided to 1 only once we
|
||||||
|
are done. First set to -1 to signal initialization is ongoing.
|
||||||
|
Protect against concurrent callers with recursive lock.
|
||||||
* intl/finddomain.c (_nl_find_domain): Protect calls to
|
* intl/finddomain.c (_nl_find_domain): Protect calls to
|
||||||
_nl_make_l10nflist.
|
_nl_make_l10nflist.
|
||||||
|
|
||||||
* sysdeps/posix/getaddrinfo.c (getaddrinfo): If determinination of
|
* sysdeps/posix/getaddrinfo.c (getaddrinfo): If determinination of
|
||||||
source address fails, initialized source_addr_len field so that
|
source address fails, initialized source_addr_len field so that
|
||||||
duplicate address recognition does not copy junk.
|
duplicate address recognition does not copy junk. [BZ #322]
|
||||||
|
|
||||||
2004-09-25 Jakub Jelinek <jakub@redhat.com>
|
2004-09-25 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Implementation of the internal dcigettext function.
|
/* Implementation of the internal dcigettext function.
|
||||||
Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -439,7 +439,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
search->domainname = (char *) domainname;
|
search->domainname = (char *) domainname;
|
||||||
search->category = category;
|
search->category = category;
|
||||||
|
|
||||||
|
/* Since tfind/tsearch manage a balanced tree, concurrent tfind and
|
||||||
|
tsearch calls can be fatal. */
|
||||||
|
__libc_rwlock_define_initialized (static, tree_lock);
|
||||||
|
__libc_rwlock_rdlock (tree_lock);
|
||||||
|
|
||||||
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
|
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
|
||||||
|
|
||||||
|
__libc_rwlock_unlock (tree_lock);
|
||||||
|
|
||||||
freea (search);
|
freea (search);
|
||||||
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
|
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
|
||||||
{
|
{
|
||||||
@ -633,9 +641,14 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
newp->translation = retval;
|
newp->translation = retval;
|
||||||
newp->translation_length = retlen;
|
newp->translation_length = retlen;
|
||||||
|
|
||||||
|
__libc_rwlock_wrlock (tree_lock);
|
||||||
|
|
||||||
/* Insert the entry in the search tree. */
|
/* Insert the entry in the search tree. */
|
||||||
foundp = (struct known_translation_t **)
|
foundp = (struct known_translation_t **)
|
||||||
tsearch (newp, &root, transcmp);
|
tsearch (newp, &root, transcmp);
|
||||||
|
|
||||||
|
__libc_rwlock_unlock (tree_lock);
|
||||||
|
|
||||||
if (foundp == NULL
|
if (foundp == NULL
|
||||||
|| __builtin_expect (*foundp != newp, 0))
|
|| __builtin_expect (*foundp != newp, 0))
|
||||||
/* The insert failed. */
|
/* The insert failed. */
|
||||||
@ -680,7 +693,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
|
|||||||
char *result;
|
char *result;
|
||||||
size_t resultlen;
|
size_t resultlen;
|
||||||
|
|
||||||
if (domain_file->decided == 0)
|
if (domain_file->decided <= 0)
|
||||||
_nl_load_domain (domain_file, domainbinding);
|
_nl_load_domain (domain_file, domainbinding);
|
||||||
|
|
||||||
if (domain_file->data == NULL)
|
if (domain_file->data == NULL)
|
||||||
|
@ -80,22 +80,22 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* We need to protect modifying the _NL_LOADED_DOMAINS data. */
|
/* We need to protect modifying the _NL_LOADED_DOMAINS data. */
|
||||||
__libc_lock_define_initialized (static, lock);
|
__libc_rwlock_define_initialized (static, lock);
|
||||||
__libc_lock_lock (lock);
|
__libc_rwlock_rdlock (lock);
|
||||||
|
|
||||||
/* If we have already tested for this locale entry there has to
|
/* If we have already tested for this locale entry there has to
|
||||||
be one data set in the list of loaded domains. */
|
be one data set in the list of loaded domains. */
|
||||||
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
|
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
|
||||||
strlen (dirname) + 1, 0, locale, NULL, NULL,
|
strlen (dirname) + 1, 0, locale, NULL, NULL,
|
||||||
NULL, NULL, domainname, 0);
|
NULL, NULL, domainname, 0);
|
||||||
__libc_lock_unlock (lock);
|
__libc_rwlock_unlock (lock);
|
||||||
|
|
||||||
if (retval != NULL)
|
if (retval != NULL)
|
||||||
{
|
{
|
||||||
/* We know something about this locale. */
|
/* We know something about this locale. */
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
if (retval->decided == 0)
|
if (retval->decided <= 0)
|
||||||
_nl_load_domain (retval, domainbinding);
|
_nl_load_domain (retval, domainbinding);
|
||||||
|
|
||||||
if (retval->data != NULL)
|
if (retval->data != NULL)
|
||||||
@ -103,7 +103,7 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
|
|||||||
|
|
||||||
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
|
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
|
||||||
{
|
{
|
||||||
if (retval->successor[cnt]->decided == 0)
|
if (retval->successor[cnt]->decided <= 0)
|
||||||
_nl_load_domain (retval->successor[cnt], domainbinding);
|
_nl_load_domain (retval->successor[cnt], domainbinding);
|
||||||
|
|
||||||
if (retval->successor[cnt]->data != NULL)
|
if (retval->successor[cnt]->data != NULL)
|
||||||
@ -141,7 +141,7 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
|
|||||||
&codeset, &normalized_codeset);
|
&codeset, &normalized_codeset);
|
||||||
|
|
||||||
/* We need to protect modifying the _NL_LOADED_DOMAINS data. */
|
/* We need to protect modifying the _NL_LOADED_DOMAINS data. */
|
||||||
__libc_lock_lock (lock);
|
__libc_rwlock_wrlock (lock);
|
||||||
|
|
||||||
/* Create all possible locale entries which might be interested in
|
/* Create all possible locale entries which might be interested in
|
||||||
generalization. */
|
generalization. */
|
||||||
@ -149,20 +149,20 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
|
|||||||
strlen (dirname) + 1, mask, language, territory,
|
strlen (dirname) + 1, mask, language, territory,
|
||||||
codeset, normalized_codeset, modifier,
|
codeset, normalized_codeset, modifier,
|
||||||
domainname, 1);
|
domainname, 1);
|
||||||
__libc_lock_unlock (lock);
|
__libc_rwlock_unlock (lock);
|
||||||
|
|
||||||
if (retval == NULL)
|
if (retval == NULL)
|
||||||
/* This means we are out of core. */
|
/* This means we are out of core. */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (retval->decided == 0)
|
if (retval->decided <= 0)
|
||||||
_nl_load_domain (retval, domainbinding);
|
_nl_load_domain (retval, domainbinding);
|
||||||
if (retval->data == NULL)
|
if (retval->data == NULL)
|
||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
|
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
|
||||||
{
|
{
|
||||||
if (retval->successor[cnt]->decided == 0)
|
if (retval->successor[cnt]->decided <= 0)
|
||||||
_nl_load_domain (retval->successor[cnt], domainbinding);
|
_nl_load_domain (retval->successor[cnt], domainbinding);
|
||||||
if (retval->successor[cnt]->data != NULL)
|
if (retval->successor[cnt]->data != NULL)
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
/* Copyright (C) 1995-2002, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
|
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
|
||||||
|
|
||||||
@ -273,10 +273,14 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
retval->filename = abs_filename;
|
retval->filename = abs_filename;
|
||||||
|
/* If more than one directory is in the list this is a pseudo-entry
|
||||||
|
which just references others. We do not try to load data for it,
|
||||||
|
ever. */
|
||||||
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|
||||||
|| ((mask & XPG_CODESET) != 0
|
|| ((mask & XPG_CODESET) != 0
|
||||||
&& (mask & XPG_NORM_CODESET) != 0));
|
&& (mask & XPG_NORM_CODESET) != 0));
|
||||||
retval->data = NULL;
|
retval->data = NULL;
|
||||||
|
__libc_lock_init_recursive (retval->lock);
|
||||||
|
|
||||||
if (last == NULL)
|
if (last == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc.
|
/* Copyright (C) 1996-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||||
|
|
||||||
@ -20,6 +20,8 @@
|
|||||||
#ifndef _LOADINFO_H
|
#ifndef _LOADINFO_H
|
||||||
#define _LOADINFO_H 1
|
#define _LOADINFO_H 1
|
||||||
|
|
||||||
|
#include <bits/libc-lock.h>
|
||||||
|
|
||||||
/* Declarations of locale dependent catalog lookup functions.
|
/* Declarations of locale dependent catalog lookup functions.
|
||||||
Implemented in
|
Implemented in
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ struct loaded_l10nfile
|
|||||||
{
|
{
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int decided;
|
int decided;
|
||||||
|
__libc_lock_define_recursive (, lock);
|
||||||
|
|
||||||
const void *data;
|
const void *data;
|
||||||
|
|
||||||
|
@ -899,7 +899,7 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
struct loaded_l10nfile *domain_file;
|
struct loaded_l10nfile *domain_file;
|
||||||
struct binding *domainbinding;
|
struct binding *domainbinding;
|
||||||
{
|
{
|
||||||
int fd;
|
int fd = -1;
|
||||||
size_t size;
|
size_t size;
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
@ -912,7 +912,24 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
int revision;
|
int revision;
|
||||||
const char *nullentry;
|
const char *nullentry;
|
||||||
|
|
||||||
domain_file->decided = 1;
|
__libc_lock_lock_recursive (domain_file->lock);
|
||||||
|
if (domain_file->decided != 0)
|
||||||
|
{
|
||||||
|
/* There are two possibilities:
|
||||||
|
|
||||||
|
+ is is the same thread calling again during this
|
||||||
|
initialization via _nl_init_domain_conv and _nl_find_msg. We
|
||||||
|
have initialized everything this call needs.
|
||||||
|
|
||||||
|
+ this is another thread which tried to initialize this object.
|
||||||
|
Not necessary anymore since if the lock is available this
|
||||||
|
is finished.
|
||||||
|
*/
|
||||||
|
__libc_lock_unlock_recursive (domain_file->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
domain_file->decided = -1;
|
||||||
domain_file->data = NULL;
|
domain_file->data = NULL;
|
||||||
|
|
||||||
/* Note that it would be useless to store domainbinding in domain_file
|
/* Note that it would be useless to store domainbinding in domain_file
|
||||||
@ -924,12 +941,12 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
specification the locale file name is different for XPG and CEN
|
specification the locale file name is different for XPG and CEN
|
||||||
syntax. */
|
syntax. */
|
||||||
if (domain_file->filename == NULL)
|
if (domain_file->filename == NULL)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* Try to open the addressed file. */
|
/* Try to open the addressed file. */
|
||||||
fd = open (domain_file->filename, O_RDONLY);
|
fd = open (domain_file->filename, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* We must know about the size of the file. */
|
/* We must know about the size of the file. */
|
||||||
if (
|
if (
|
||||||
@ -940,11 +957,8 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
#endif
|
#endif
|
||||||
|| __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
|
|| __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
|
||||||
|| __builtin_expect (size < sizeof (struct mo_file_header), 0))
|
|| __builtin_expect (size < sizeof (struct mo_file_header), 0))
|
||||||
{
|
|
||||||
/* Something went wrong. */
|
/* Something went wrong. */
|
||||||
close (fd);
|
goto out;;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
/* Now we are ready to load the file. If mmap() is available we try
|
/* Now we are ready to load the file. If mmap() is available we try
|
||||||
@ -952,45 +966,42 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
|
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
|
||||||
MAP_PRIVATE, fd, 0);
|
MAP_PRIVATE, fd, 0);
|
||||||
|
|
||||||
if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
|
if (__builtin_expect (data != MAP_FAILED, 1))
|
||||||
{
|
{
|
||||||
/* mmap() call was successful. */
|
/* mmap() call was successful. */
|
||||||
close (fd);
|
close (fd);
|
||||||
|
fd = -1;
|
||||||
use_mmap = 1;
|
use_mmap = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the data is not yet available (i.e. mmap'ed) we try to load
|
/* If the data is not yet available (i.e. mmap'ed) we try to load
|
||||||
it manually. */
|
it manually. */
|
||||||
if (data == (struct mo_file_header *) -1)
|
if (data == MAP_FAILED)
|
||||||
{
|
{
|
||||||
size_t to_read;
|
size_t to_read;
|
||||||
char *read_ptr;
|
char *read_ptr;
|
||||||
|
|
||||||
data = (struct mo_file_header *) malloc (size);
|
data = (struct mo_file_header *) malloc (size);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
to_read = size;
|
to_read = size;
|
||||||
read_ptr = (char *) data;
|
read_ptr = (char *) data;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
long int nb = (long int) read (fd, read_ptr, to_read);
|
long int nb = (long int) TEMP_FAILURE_RETRY (read (fd, read_ptr,
|
||||||
|
to_read));
|
||||||
if (nb <= 0)
|
if (nb <= 0)
|
||||||
{
|
goto out;
|
||||||
#ifdef EINTR
|
|
||||||
if (nb == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
close (fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
read_ptr += nb;
|
read_ptr += nb;
|
||||||
to_read -= nb;
|
to_read -= nb;
|
||||||
}
|
}
|
||||||
while (to_read > 0);
|
while (to_read > 0);
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
|
fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Using the magic number we can test whether it really is a message
|
/* Using the magic number we can test whether it really is a message
|
||||||
@ -1005,12 +1016,12 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
free (data);
|
free (data);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
|
domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
|
||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
return;
|
goto out;
|
||||||
domain_file->data = domain;
|
domain_file->data = domain;
|
||||||
|
|
||||||
domain->data = (char *) data;
|
domain->data = (char *) data;
|
||||||
@ -1372,7 +1383,7 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
free (data);
|
free (data);
|
||||||
free (domain);
|
free (domain);
|
||||||
domain_file->data = NULL;
|
domain_file->data = NULL;
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now initialize the character set converter from the character set
|
/* Now initialize the character set converter from the character set
|
||||||
@ -1382,6 +1393,14 @@ _nl_load_domain (domain_file, domainbinding)
|
|||||||
|
|
||||||
/* Also look for a plural specification. */
|
/* Also look for a plural specification. */
|
||||||
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
|
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fd != -1)
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
domain_file->decided = 1;
|
||||||
|
|
||||||
|
__libc_lock_unlock_recursive (domain_file->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user