]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
2.3.3-57 cvs/fedora-glibc-2_3_3-57
authorJakub Jelinek <jakub@redhat.com>
Sun, 26 Sep 2004 04:48:48 +0000 (04:48 +0000)
committerJakub Jelinek <jakub@redhat.com>
Sun, 26 Sep 2004 04:48:48 +0000 (04:48 +0000)
ChangeLog
intl/dcigettext.c
intl/finddomain.c
intl/l10nflist.c
intl/loadinfo.h
intl/loadmsgcat.c
sysdeps/posix/getaddrinfo.c

index 779d045778505d6ac4d69440e3a5309284d975c0..dcbab5ec5c07c94f9bb899f290dcaeedacf3f4a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+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
+       _nl_make_l10nflist.
+       * sysdeps/posix/getaddrinfo.c (getaddrinfo): If determinination of
+       source address fails, initialized source_addr_len field so that
+       duplicate address recognition does not copy junk.  [BZ #322]
+
 2004-09-25  Jakub Jelinek  <jakub@redhat.com>
 
        * sysdeps/unix/sysv/linux/i386/setuid.c (__setuid): Remove second
index fa53b7c5748f1f7e8159b7d0fb31ea05c970b44c..d7111729b921fd30702828dff4b316a2c419214c 100644 (file)
@@ -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)
index 6988d9efc0d76063b4a2de2baabe49f7bd2fbe7c..39e54755d249b22eb7fb8f73c5d2e1c9de79a85e 100644 (file)
@@ -35,6 +35,7 @@
 #include "gettextP.h"
 #ifdef _LIBC
 # include <libintl.h>
+# include <bits/libc-lock.h>
 #else
 # include "libgnuintl.h"
 #endif
@@ -78,17 +79,23 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
                (4) modifier
    */
 
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_define_initialized (static, lock);
+  __libc_rwlock_rdlock (lock);
+
   /* If we have already tested for this locale entry there has to
      be one data set in the list of loaded domains.  */
   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                               strlen (dirname) + 1, 0, locale, NULL, NULL,
                               NULL, NULL, domainname, 0);
+  __libc_rwlock_unlock (lock);
+
   if (retval != NULL)
     {
       /* We know something about this locale.  */
       int cnt;
 
-      if (retval->decided == 0)
+      if (retval->decided <= 0)
        _nl_load_domain (retval, domainbinding);
 
       if (retval->data != NULL)
@@ -96,12 +103,13 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
 
       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);
 
          if (retval->successor[cnt]->data != NULL)
            break;
        }
+
       return cnt >= 0 ? retval : NULL;
       /* NOTREACHED */
     }
@@ -132,24 +140,29 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
   mask = _nl_explode_name (locale, &language, &modifier, &territory,
                           &codeset, &normalized_codeset);
 
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_wrlock (lock);
+
   /* Create all possible locale entries which might be interested in
      generalization.  */
   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                               strlen (dirname) + 1, mask, language, territory,
                               codeset, normalized_codeset, modifier,
                               domainname, 1);
+  __libc_rwlock_unlock (lock);
+
   if (retval == NULL)
     /* This means we are out of core.  */
     return NULL;
 
-  if (retval->decided == 0)
+  if (retval->decided <= 0)
     _nl_load_domain (retval, domainbinding);
   if (retval->data == NULL)
     {
       int 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);
          if (retval->successor[cnt]->data != NULL)
            break;
index 31760bdaaa82683cc9d1726b16fb7cfcc84cf062..5a366e59fb1c2a1f66a4fe677f1451dc797a84f7 100644 (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.
    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;
 
   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
                     || ((mask & XPG_CODESET) != 0
                         && (mask & XPG_NORM_CODESET) != 0));
   retval->data = NULL;
+  __libc_lock_init_recursive (retval->lock);
 
   if (last == NULL)
     {
index c2b6971b36c10b48e421a32fa0ecd0ad20978018..913022eb7bc2aac392987a8cb1a398afae62e67a 100644 (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.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -20,6 +20,8 @@
 #ifndef _LOADINFO_H
 #define _LOADINFO_H    1
 
+#include <bits/libc-lock.h>
+
 /* Declarations of locale dependent catalog lookup functions.
    Implemented in
 
@@ -61,6 +63,7 @@ struct loaded_l10nfile
 {
   const char *filename;
   int decided;
+  __libc_lock_define_recursive (, lock);
 
   const void *data;
 
index 569ace2105e3e56aff677816f7091dd83bc3220f..ec886d9bd7477af56223c26131ba81e5997b96f1 100644 (file)
@@ -899,7 +899,7 @@ _nl_load_domain (domain_file, domainbinding)
      struct loaded_l10nfile *domain_file;
      struct binding *domainbinding;
 {
-  int fd;
+  int fd = -1;
   size_t size;
 #ifdef _LIBC
   struct stat64 st;
@@ -912,7 +912,24 @@ _nl_load_domain (domain_file, domainbinding)
   int revision;
   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;
 
   /* 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
      syntax.  */
   if (domain_file->filename == NULL)
-    return;
+    goto out;
 
   /* Try to open the addressed file.  */
   fd = open (domain_file->filename, O_RDONLY);
   if (fd == -1)
-    return;
+    goto out;
 
   /* We must know about the size of the file.  */
   if (
@@ -940,11 +957,8 @@ _nl_load_domain (domain_file, domainbinding)
 #endif
       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
-    {
-      /* Something went wrong.  */
-      close (fd);
-      return;
-    }
+    /* Something went wrong.  */
+    goto out;;
 
 #ifdef HAVE_MMAP
   /* 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,
                                         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.  */
       close (fd);
+      fd = -1;
       use_mmap = 1;
     }
 #endif
 
   /* If the data is not yet available (i.e. mmap'ed) we try to load
      it manually.  */
-  if (data == (struct mo_file_header *) -1)
+  if (data == MAP_FAILED)
     {
       size_t to_read;
       char *read_ptr;
 
       data = (struct mo_file_header *) malloc (size);
       if (data == NULL)
-       return;
+       goto out;
 
       to_read = size;
       read_ptr = (char *) data;
       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)
-           {
-#ifdef EINTR
-             if (nb == -1 && errno == EINTR)
-               continue;
-#endif
-             close (fd);
-             return;
-           }
+           goto out;
+
          read_ptr += nb;
          to_read -= nb;
        }
       while (to_read > 0);
 
       close (fd);
+      fd = -1;
     }
 
   /* Using the magic number we can test whether it really is a message
@@ -1005,12 +1016,12 @@ _nl_load_domain (domain_file, domainbinding)
       else
 #endif
        free (data);
-      return;
+      goto out;
     }
 
   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
   if (domain == NULL)
-    return;
+    goto out;
   domain_file->data = domain;
 
   domain->data = (char *) data;
@@ -1372,7 +1383,7 @@ _nl_load_domain (domain_file, domainbinding)
        free (data);
       free (domain);
       domain_file->data = NULL;
-      return;
+      goto out;
     }
 
   /* 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.  */
   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);
 }
 
 
index b3f9f4f9b09313d948f810d6c92dd37a7d6427f5..225c1a108864763831aaeb800ce44e7e8300fecc 100644 (file)
@@ -1561,10 +1561,7 @@ getaddrinfo (const char *name, const char *service,
          results[i].dest_addr = q;
          results[i].got_source_addr = false;
 
-         /* We overwrite the type with SOCK_DGRAM since we do not
-            want connect() to connect to the other side.  If we
-            cannot determine the source address remember this
-            fact.  If we just looked up the address for a different
+         /* If we just looked up the address for a different
             protocol, reuse the result.  */
          if (last != NULL && last->ai_addrlen == q->ai_addrlen
              && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
@@ -1576,21 +1573,28 @@ getaddrinfo (const char *name, const char *service,
            }
          else
            {
+             /* We overwrite the type with SOCK_DGRAM since we do not
+                want connect() to connect to the other side.  If we
+                cannot determine the source address remember this
+                fact.  */
              int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
-             if (fd != -1)
+             socklen_t sl = sizeof (results[i].source_addr);
+             if (fd != -1
+                 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
+                 && __getsockname (fd,
+                                   (struct sockaddr *) &results[i].source_addr,
+                                   &sl) == 0)
                {
-                 socklen_t sl = sizeof (results[i].source_addr);
-                 if (__connect (fd, q->ai_addr, q->ai_addrlen) == 0
-                     && __getsockname (fd,
-                                       (struct sockaddr *) &results[i].source_addr,
-                                       &sl) == 0)
-                   {
-                     results[i].source_addr_len = sl;
-                     results[i].got_source_addr = true;
-                   }
-
-                 close_not_cancel_no_status (fd);
+                 results[i].source_addr_len = sl;
+                 results[i].got_source_addr = true;
                }
+             else
+               /* Just make sure that if we have to process the same
+                  address again we do not copy any memory.  */
+               results[i].source_addr_len = 0;
+
+             if (fd != -1)
+               close_not_cancel_no_status (fd);
            }
 
          /* Remember the canonical name.  */