On 2024-08-16 07:30, Bruno Haible wrote:
Copying and then discarding an uninitialized value of integer
or pointer type (i.e. not a signalling NaN (*)) is not undefined behaviour.

Although that's how typical implementations behave, the C standard says that copying from a source variable has undefined behavior if the source could have been declared with 'register' (i.e., it's auto and never has its address taken). See C23 §6.3.2.1 paragraph 2. Since the code in question is copying from such a source, its behavior is technically undefined.

I recall running into a similar problem myself, when writing the mcel code, though I don't recall the details.

Proposed patch attached. I daresay there's lots of other places that would need a similar fix, assuming this one is acceptable.
From 442c99cf9db881ddaa591ae829c4a37f14e014ee Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 16 Aug 2024 22:07:18 -0700
Subject: [PATCH] avltree-list: avoid undefined behavior

Problem reported by Lukas Javorsky in:
https://lists.gnu.org/r/bug-gnulib/2024-08/msg00095.html
* lib/gl_anytree_list2.h (gl_tree_iterator, gl_tree_iterator_from_to):
Avoid undefined behavior in accessing uninitialized locals.
---
 ChangeLog              |  8 ++++++++
 lib/gl_anytree_list2.h | 38 ++++++++++++++------------------------
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ee8851fea5..ce41dbf7e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-08-16  Paul Eggert  <egg...@cs.ucla.edu>
+
+	avltree-list: avoid undefined behavior
+	Problem reported by Lukas Javorsky in:
+	https://lists.gnu.org/r/bug-gnulib/2024-08/msg00095.html
+	* lib/gl_anytree_list2.h (gl_tree_iterator, gl_tree_iterator_from_to):
+	Avoid undefined behavior in accessing uninitialized locals.
+
 2024-08-16  Bruno Haible  <br...@clisp.org>
 
 	gitsub.sh: For a submodule, merge from the right remote branch.
diff --git a/lib/gl_anytree_list2.h b/lib/gl_anytree_list2.h
index a66e611b14..d908bcec3c 100644
--- a/lib/gl_anytree_list2.h
+++ b/lib/gl_anytree_list2.h
@@ -581,26 +581,20 @@ gl_tree_list_free (gl_list_t list)
 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
 gl_tree_iterator (gl_list_t list)
 {
-  gl_list_iterator_t result;
   gl_list_node_t node;
 
-  result.vtable = list->base.vtable;
-  result.list = list;
   /* Start node is the leftmost node.  */
   node = list->root;
   if (node != NULL)
     while (node->left != NULL)
       node = node->left;
-  result.p = node;
-  /* End point is past the rightmost node.  */
-  result.q = NULL;
-#if defined GCC_LINT || defined lint
-  result.i = 0;
-  result.j = 0;
-  result.count = 0;
-#endif
 
-  return result;
+  /* End point is past the rightmost node, so .q is a null pointer.  */
+  return (gl_list_iterator_t) {
+    .vtable = list->base.vtable,
+    .list = list,
+    .p = node,
+  };
 }
 
 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
@@ -612,19 +606,15 @@ gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
   if (!(start_index <= end_index && end_index <= count))
     /* Invalid arguments.  */
     abort ();
-  result.vtable = list->base.vtable;
-  result.list = list;
-  /* Start node is the node at position start_index.  */
-  result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
-  /* End point is the node at position end_index.  */
-  result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
-#if defined GCC_LINT || defined lint
-  result.i = 0;
-  result.j = 0;
-  result.count = 0;
-#endif
 
-  return result;
+  return (gl_list_iterator_t) {
+    .vtable = list->base.vtable,
+    .list = list,
+    /* Start node is the node at position start_index.  */
+    .p = start_index < count ? node_at (list->root, start_index) : NULL,
+    /* End point is the node at position end_index.  */
+    .q = end_index < count ? node_at (list->root, end_index) : NULL,
+  };
 }
 
 static bool
-- 
2.43.0

Reply via email to