# HG changeset patch
# User Kim Alvefur <zash@zash.se>
# Date 1701447079 -3600
# Node ID 977d92aff5630f9a82268a6155bb2ec5e6d23084
# Parent  81ae5e12550f3a821e2825c19c9353431029fd5c# Parent  db30ffbf20903a54b0fabb24c024cfd755dbf8da
Merge 0.12->trunk

diff -r 81ae5e12550f -r 977d92aff563 net/http/parser.lua
--- a/net/http/parser.lua	Thu Nov 30 18:45:05 2023 +0100
+++ b/net/http/parser.lua	Fri Dec 01 17:11:19 2023 +0100
@@ -59,7 +59,13 @@
 			while buffer:length() > 0 do
 				if state == nil then -- read request
 					local index = buffer:sub(1, headlimit):find("\r\n\r\n", nil, true);
-					if not index then return; end -- not enough data
+					if not index then
+						if buffer:length() > headlimit then
+							return error_cb("header-too-large");
+						end
+						-- not enough data
+						return;
+					end
 					-- FIXME was reason_phrase meant to be passed on somewhere?
 					local method, path, httpversion, status_code, reason_phrase; -- luacheck: ignore reason_phrase
 					local first_line;
diff -r 81ae5e12550f -r 977d92aff563 spec/net_http_parser_spec.lua
--- a/spec/net_http_parser_spec.lua	Thu Nov 30 18:45:05 2023 +0100
+++ b/spec/net_http_parser_spec.lua	Fri Dec 01 17:11:19 2023 +0100
@@ -167,6 +167,33 @@
 				}
 			);
 		end);
+
+		it("should reject very large request heads", function()
+			local finished = false;
+			local success_cb = spy.new(function()
+				finished = true;
+			end)
+			local error_cb = spy.new(function()
+				finished = true;
+			end)
+			local parser = http_parser.new(success_cb, error_cb, "server", function()
+				return { head_size_limit = 1024; body_size_limit = 1024; buffer_size_limit = 2048 };
+			end)
+			parser:feed("GET / HTTP/1.1\r\n");
+			for i = 1, 64 do -- * header line > buffer_size_limit
+				parser:feed(string.format("Header-%04d: Yet-AnotherValue\r\n", i));
+				if finished then
+					-- should hit an error around half-way
+					break
+				end
+			end
+			if not finished then
+				parser:feed("\r\n")
+			end
+			assert.spy(success_cb).was_called(0);
+			assert.spy(error_cb).was_called(1);
+			assert.spy(error_cb).was_called_with("header-too-large");
+		end)
 	end);
 
 	it("should handle large chunked responses", function ()