Lua arrays start at the index 1 by convention:

> However, it is customary in Lua to start arrays with index 1. The Lua
> libraries adhere to this convention; so, if your arrays also start with 1,
> you will be able to use their functions directly.
(https://www.lua.org/pil/11.1.html)

This patch makes the array 1-indexed. To preserve backwards compatibility
the first value for each header is duplicated into the index 0. While the
duplication might cause harm where a specific value order is expected or
required by HTTP standards (e.g. Transfer-Encoding) I consider the breakage
to be higher if index 0 ceases to exist.

This bug was introduced in commit 04c57b3357b79c9eba2dee0e1c9de724ca286660,
first released in v1.6-dev2.

Backporting depends on how careful one wants to be regarding the change in
behavior.
---
 reg-tests/lua/header_1_index.lua |  6 ++++++
 reg-tests/lua/header_1_index.vtc | 29 +++++++++++++++++++++++++++++
 src/hlua.c                       |  4 +++-
 3 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 reg-tests/lua/header_1_index.lua
 create mode 100644 reg-tests/lua/header_1_index.vtc

diff --git a/reg-tests/lua/header_1_index.lua b/reg-tests/lua/header_1_index.lua
new file mode 100644
index 000000000..9ccf1e5ab
--- /dev/null
+++ b/reg-tests/lua/header_1_index.lua
@@ -0,0 +1,6 @@
+core.register_service("header_1_index", "http", function(applet)
+       applet:add_header("count", #applet.headers["foo"])
+       applet:set_status(200)
+       applet:start_response()
+       applet:send(#applet.headers["foo"])
+end)
diff --git a/reg-tests/lua/header_1_index.vtc b/reg-tests/lua/header_1_index.vtc
new file mode 100644
index 000000000..cb918db75
--- /dev/null
+++ b/reg-tests/lua/header_1_index.vtc
@@ -0,0 +1,29 @@
+varnishtest "Lua: Check that the header list is 1-indexed."
+#REQUIRE_OPTIONS=LUA
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+    global
+        lua-load ${testdir}/header_1_index.lua
+
+    frontend fe1
+        mode http
+        ${no-htx} option http-use-htx
+        bind "fd@${fe1}"
+
+        http-request use-service lua.header_1_index
+} -start
+
+client c0 -connect ${h1_fe1_sock} {
+    txreq -url "/" \
+      -hdr "Foo: one" \
+      -hdr "Foo: two"
+    rxresp
+    expect resp.status == 200
+    expect resp.http.count == "2"
+}
+
+client c0 -start
+
+client c0 -wait
diff --git a/src/hlua.c b/src/hlua.c
index 2d29d08f0..4fe274676 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -4741,7 +4741,9 @@ __LJMP static int hlua_http_get_headers(lua_State *L, 
struct hlua_txn *htxn, str
                                lua_pushlstring(L, n.ptr, n.len);  /* push the 
header name as key. */
                                lua_newtable(L); /* create and push empty 
array. */
                                lua_pushlstring(L, v.ptr, v.len); /* push 
header value. */
-                               lua_rawseti(L, -2, 0); /* add header value to 
the newly created array */
+                               lua_rawseti(L, -2, 1); /* add header value to 
the newly created array */
+                               lua_geti(L, -1, 1); /* duplicate header value. 
*/
+                               lua_rawseti(L, -2, 0); /* add duplicated value 
to index 0 for backwards compatibility */
                                lua_rawset(L, -3); /* add the array to the 
table indexed by header name. */
                                break;
 
-- 
2.23.0


Reply via email to