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