diff options
author | Ulrich Drepper <drepper@redhat.com> | 2004-09-26 04:45:24 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2004-09-26 04:45:24 +0000 |
commit | ce7265c7438e18f2e4ea81582131a783a1cdd601 (patch) | |
tree | de765fda756af9cf90b3d7d3c528ac0c11f93de9 /intl/dcigettext.c | |
parent | f6b90f42997f98bdd91dac713d610b66edc55c7c (diff) | |
download | glibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.tar.gz glibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.tar.xz glibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.zip |
[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]
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r-- | intl/dcigettext.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c index fa53b7c574..d7111729b9 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -1,5 +1,5 @@ /* 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. 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->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); + + __libc_rwlock_unlock (tree_lock); + freea (search); 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_length = retlen; + __libc_rwlock_wrlock (tree_lock); + /* Insert the entry in the search tree. */ foundp = (struct known_translation_t **) tsearch (newp, &root, transcmp); + + __libc_rwlock_unlock (tree_lock); + if (foundp == NULL || __builtin_expect (*foundp != newp, 0)) /* The insert failed. */ @@ -680,7 +693,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) char *result; size_t resultlen; - if (domain_file->decided == 0) + if (domain_file->decided <= 0) _nl_load_domain (domain_file, domainbinding); if (domain_file->data == NULL) |