[tz] [PROPOSED] Fix recently-introduced zic infloop

Paul Eggert eggert at cs.ucla.edu
Fri Oct 28 05:25:36 UTC 2022


* zic.c (make_links): Diagnose link cycles instead of looping.
---
 zic.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/zic.c b/zic.c
index 4222869..501718f 100644
--- a/zic.c
+++ b/zic.c
@@ -688,7 +688,7 @@ bsearch_linkcmp(void const *key, void const *b)
 static void
 make_links(void)
 {
-  ptrdiff_t i, j, nalinks;
+  ptrdiff_t i, j, nalinks, pass_size;
   if (1 < nlinks)
     qsort(links, nlinks, sizeof *links, qsort_linkcmp);
 
@@ -700,7 +700,7 @@ make_links(void)
       i++;
     links[j++] = links[i];
   }
-  nlinks = j;
+  nlinks = pass_size = j;
 
   /* Walk through the link array making links.  However,
      if a link's target has not been made yet, append a copy to the
@@ -739,8 +739,22 @@ make_links(void)
     eat(links[i].l_filenum, links[i].l_linenum);
 
     /* If this pass examined all its links, start the next pass.  */
-    if (i == j)
+    if (i == j) {
+      if (nalinks - i == pass_size) {
+	error(_("\"Link %s %s\" is part of a link cycle"),
+	      links[i].l_target, links[i].l_linkname);
+	break;
+      }
       j = nalinks;
+      pass_size = nalinks - i;
+    }
+
+    /* Diagnose self links, which the cycle detection algorithm would not
+       otherwise catch.  */
+    if (strcmp(links[i].l_target, links[i].l_linkname) == 0) {
+      error(_("link %s targets itself"), links[i].l_target);
+      continue;
+    }
 
     /* Make this link unless its target has not been made yet.  */
     l = bsearch(links[i].l_target, &links[i + 1], j - (i + 1),
-- 
2.37.3



More information about the tz mailing list