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:
Ulrich Drepper 2004-09-26 04:45:24 +00:00
parent f6b90f4299
commit ce7265c743
6 changed files with 86 additions and 39 deletions

View File

@ -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>

View File

@ -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)

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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);
} }