Fix endless loop in localedef.
authorUlrich Drepper <drepper@redhat.com>
Mon, 7 Sep 2009 09:32:29 +0000 (02:32 -0700)
committerUlrich Drepper <drepper@redhat.com>
Mon, 7 Sep 2009 09:32:29 +0000 (02:32 -0700)
localedef got into an endless loop in case order_start was used for
the unnamed_section twice and the first use didn't actually result
into any definition.

ChangeLog
locale/programs/ld-collate.c

index a0ed5d5..d6cd79d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2009-09-07  Ulrich Drepper  <drepper@redhat.com>
 
+       * locale/programs/ld-collate.c (struct locale_collate_t): Add
+       unnamed_section_defined field.
+       (collate_read): Test and set unnamed_section_defined.
+
        * posix/getconf.c (vars): Handle POSIX2_LINE_MAX in addition to
        _POSIX2_LINE_MAX.
 
index bf50e77..11bd7ea 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-2003, 2005-2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2003, 2005-2008, 2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
@@ -203,6 +203,8 @@ struct locale_collate_t
   struct section_list *current_section;
   /* There always can be an unnamed section.  */
   struct section_list unnamed_section;
+  /* Flag whether the unnamed section has been defined.  */
+  bool unnamed_section_defined;
   /* To make handling of errors easier we have another section.  */
   struct section_list error_section;
   /* Sometimes we are defining the values for collating symbols before
@@ -634,7 +636,7 @@ find_element (struct linereader *ldfile, struct locale_collate_t *collate,
   if (find_entry (&collate->seq_table, str, len, &result) != 0)
     {
       /* Nope, not define yet.  So we see whether it is a
-         collation symbol.  */
+        collation symbol.  */
       void *ptr;
 
       if (find_entry (&collate->sym_table, str, len, &ptr) == 0)
@@ -788,7 +790,7 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
              if (*cp == '<')
                {
                  /* Ahh, it's a bsymbol or an UCS4 value.  If it's
-                     the latter we have to unify the name.  */
+                    the latter we have to unify the name.  */
                  const char *startp = ++cp;
                  size_t len;
 
@@ -1302,8 +1304,8 @@ order for `%.*s' already defined at %s:%Zu"),
       else
        {
          /* Determine the range.  To do so we have to determine the
-             common prefix of the both names and then the numeric
-             values of both ends.  */
+            common prefix of the both names and then the numeric
+            values of both ends.  */
          size_t lenfrom = strlen (startp->name);
          size_t lento = strlen (endp->name);
          char buf[lento + 1];
@@ -2222,14 +2224,14 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
     else
       {
        /* The entries in the list are sorted by length and then
-           alphabetically.  This is the order in which we will add the
-           elements to the collation table.  This allows simply walking
+          alphabetically.  This is the order in which we will add the
+          elements to the collation table.  This allows simply walking
           the table in sequence and stopping at the first matching
-           entry.  Since the longer sequences are coming first in the
-           list they have the possibility to match first, just as it
-           has to be.  In the worst case we are walking to the end of
-           the list where we put, if no singlebyte sequence is defined
-           in the locale definition, the weights for UNDEFINED.
+          entry.  Since the longer sequences are coming first in the
+          list they have the possibility to match first, just as it
+          has to be.  In the worst case we are walking to the end of
+          the list where we put, if no singlebyte sequence is defined
+          in the locale definition, the weights for UNDEFINED.
 
           To reduce the length of the search list we compress them a bit.
           This happens by collecting sequences of consecutive byte
@@ -2297,7 +2299,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
                  obstack_1grow_fast (&extrapool, curp->mbs[i]);
 
                /* Now find the end of the consecutive sequence and
-                   add all the indeces in the indirect pool.  */
+                  add all the indeces in the indirect pool.  */
                do
                  {
                    weightidx = output_weight (&weightpool, collate, curp);
@@ -2312,7 +2314,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
                obstack_int32_grow (&indirectpool, weightidx);
 
                /* And add the end byte sequence.  Without length this
-                   time.  */
+                  time.  */
                for (i = 1; i < curp->nmbs; ++i)
                  obstack_1grow_fast (&extrapool, curp->mbs[i]);
              }
@@ -2356,7 +2358,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
                 & (__alignof__ (int32_t) - 1)) == 0);
 
        /* If the final entry in the list is not a single character we
-           add an UNDEFINED entry here.  */
+          add an UNDEFINED entry here.  */
        if (lastp->nmbs != 1)
          {
            int added = ((sizeof (int32_t) + 1 + 1 + __alignof__ (int32_t) - 1)
@@ -3293,7 +3295,7 @@ error while adding equivalent collating symbol"));
              else
                {
                  /* One should not be allowed to open the same
-                     section twice.  */
+                    section twice.  */
                  if (sp->first != NULL)
                    lr_error (ldfile, _("\
 %s: multiple order definitions for section `%s'"),
@@ -3349,7 +3351,7 @@ error while adding equivalent collating symbol"));
                 section.  */
              collate->current_section = &collate->unnamed_section;
 
-             if (collate->unnamed_section.first != NULL)
+             if (collate->unnamed_section_defined)
                lr_error (ldfile, _("\
 %s: multiple order definitions for unnamed section"),
                          "LC_COLLATE");
@@ -3359,6 +3361,7 @@ error while adding equivalent collating symbol"));
                     the collate->sections list.  */
                  collate->unnamed_section.next = collate->sections;
                  collate->sections = &collate->unnamed_section;
+                 collate->unnamed_section_defined = true;
                }
            }
 
@@ -3579,9 +3582,9 @@ error while adding equivalent collating symbol"));
              else
                {
                  /* This is bad.  The section after which we have to
-                     reorder does not exist.  Therefore we cannot
-                     process the whole rest of this reorder
-                     specification.  */
+                    reorder does not exist.  Therefore we cannot
+                    process the whole rest of this reorder
+                    specification.  */
                  lr_error (ldfile, _("%s: section `%.*s' not known"),
                            "LC_COLLATE", (int) arg->val.str.lenmb,
                            arg->val.str.startmb);
@@ -3657,9 +3660,9 @@ error while adding equivalent collating symbol"));
          if (state == 0)
            {
              /* We are outside an `order_start' region.  This means
-                 we must only accept definitions of values for
-                 collation symbols since these are purely abstract
-                 values and don't need directions associated.  */
+                we must only accept definitions of values for
+                collation symbols since these are purely abstract
+                values and don't need directions associated.  */
              void *ptr;
 
              if (find_entry (&collate->seq_table, symstr, symlen, &ptr) == 0)
@@ -3741,7 +3744,7 @@ error while adding equivalent collating symbol"));
                    seqp->next->last = seqp->last;
 
                  /* We also have to check whether this entry is the
-                     first or last of a section.  */
+                    first or last of a section.  */
                  if (seqp->section->first == seqp)
                    {
                      if (seqp->section->first == seqp->section->last)
@@ -3798,7 +3801,7 @@ error while adding equivalent collating symbol"));
                    }
 
                  /* Process the rest of the line which might change
-                     the collation rules.  */
+                    the collation rules.  */
                  arg = lr_token (ldfile, charmap, result, repertoire,
                                  verbose);
                  if (arg->tok != tok_eof && arg->tok != tok_eol)
@@ -3810,8 +3813,8 @@ error while adding equivalent collating symbol"));
          else if (was_ellipsis != tok_none)
            {
              /* Using the information in the `ellipsis_weight'
-                 element and this and the last value we have to handle
-                 the ellipsis now.  */
+                element and this and the last value we have to handle
+                the ellipsis now.  */
              assert (state == 1);
 
              handle_ellipsis (ldfile, symstr, symlen, was_ellipsis, charmap,
@@ -3871,7 +3874,7 @@ error while adding equivalent collating symbol"));
        case tok_ellipsis3: /* absolute ellipsis */
        case tok_ellipsis4: /* symbolic decimal ellipsis */
          /* This is the symbolic (decimal or hexadecimal) or absolute
-             ellipsis.  */
+            ellipsis.  */
          if (was_ellipsis != tok_none)
            goto err_label;