Dear list,

Using the attr keyword with \hbox or \vbox will cause a fatal error when no
other (any other) attribute has been set before.

For example, the file

-----------------------------------------------------------
\attribute 1 = 1
\hbox attr 2 = 2{}
\bye
-----------------------------------------------------------

compiles without problems, while

-----------------------------------------------------------
\hbox attr 2 = 2{}
\bye
-----------------------------------------------------------

gives the following result:

-----------------------------------------------------------
This is LuaTeX, Version 1.12.0 (TeX Live 2020/Debian)
 restricted system commands enabled.
(./bug.tex
! error:  (nodes): trying to set an attribute fails, case 1
!  ==> Fatal error occurred, no output PDF file produced!
-----------------------------------------------------------

The cause of this problem problem lies in the do_set_attribute function
defined in texnodes.c: it expects an ‘attr list head, or zero’ but receives
(and tries to return!) an attribute list node instead.

The attached patch seems to solve the issue.

Regards,
Esger Renkema

diff --git a/source/texk/web2c/luatexdir/tex/packaging.c b/source/texk/web2c/luatexdir/tex/packaging.c
index 3d23c8b73..9769fba19 100644
--- a/source/texk/web2c/luatexdir/tex/packaging.c
+++ b/source/texk/web2c/luatexdir/tex/packaging.c
@@ -153,7 +153,7 @@ void scan_full_spec(group_code c, int spec_direction, int just_pack)
             attr_list = copy_attribute_list(attr_list_cache);
             attr_done = true;
         }
-        attr_list = do_set_attribute(attr_list, i, v);
+        set_attribute_on_list(attr_list, i, v);
         goto CONTINUE;
     }
     /*tex We only permit one |(b)dir| directive. */
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.c b/source/texk/web2c/luatexdir/tex/texnodes.c
index 0d7bcd5de..71a3321a2 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.c
+++ b/source/texk/web2c/luatexdir/tex/texnodes.c
@@ -3225,49 +3225,26 @@ void reset_node_properties(halfword b)
     }
 }
 
-/*tex Here |p| is an attr list head, or zero. */
-
-halfword do_set_attribute(halfword p, int i, int val)
+void set_attribute_on_list(halfword p, int i, int val)
 {
-    register halfword q;
-    register int j = 0;
-    if (p == null) {
-        /*tex Add a new head \& node. */
-        q = get_node(attribute_node_size);
-        type(q) = attribute_list_node;
-        attr_list_ref(q) = 1;
-        p = new_attribute_node((unsigned) i, val);
-        vlink(q) = p;
-        return q;
-    }
-    q = p;
-    if (vlink(p) != null) {
-        while (vlink(p) != null) {
-            int t = attribute_id(vlink(p));
-            if (t == i && attribute_value(vlink(p)) == val) {
-                /*tex There is no need to do anything. */
-                return q;
-            }
-            if (t >= i)
-                break;
-            j++;
-            p = vlink(p);
-        }
-        p = q;
-        while (j-- > 0)
-            p = vlink(p);
-        if (attribute_id(vlink(p)) == i) {
-            attribute_value(vlink(p)) = val;
-        } else {
-            /*tex Add a new node. */
-            halfword r = new_attribute_node((unsigned) i, val);
-            vlink(r) = vlink(p);
-            vlink(p) = r;
+    /*tex Here |p| is an attr list node. */
+    while (vlink(p) != null) {
+        int t = attribute_id(vlink(p));
+        if (t == i && attribute_value(vlink(p)) == val) {
+            /*tex There is no need to do anything. */
+            return;
         }
-        return q;
+        if (t >= i)
+            break;
+        p = vlink(p);
+    }
+    if (attribute_id(vlink(p)) == i) {
+        attribute_value(vlink(p)) = val;
     } else {
-        normal_error("nodes","trying to set an attribute fails, case 1");
-        return null ;
+        /*tex Add a new node. */
+        halfword r = new_attribute_node((unsigned) i, val);
+        vlink(r) = vlink(p);
+        vlink(p) = r;
     }
 }
 
@@ -3343,7 +3320,7 @@ void set_attribute(halfword n, int i, int val)
             vlink(p) = r;
         }
     } else {
-        normal_error("nodes","trying to set an attribute fails, case 2");
+        normal_error("nodes","trying to set an attribute fails");
     }
 }
 
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h
index 848f9ea47..a551c1bf0 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.h
+++ b/source/texk/web2c/luatexdir/tex/texnodes.h
@@ -89,7 +89,7 @@ extern void undump_node_mem(void);
 
 extern void update_attribute_cache(void);
 extern halfword copy_attribute_list(halfword n);
-extern halfword do_set_attribute(halfword p, int i, int val);
+extern void set_attribute_on_list(halfword p, int i, int val);
 
 #  define width_offset 2
 #  define depth_offset 3

Reply via email to