aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorCaleb Maclennan <caleb@alerque.com>2026-08-31 11:04:37 +0300
committerGitHub <noreply@github.com>2026-08-31 11:04:37 +0300
commit01162f05408ac4206be15842ef91048c63c23869 (patch)
tree2b7c8a2916cf8083b557a897c7d258e00a9c4fa3 /test
parent5afe174eeffc7f3e3b9ef80b5871237620c68415 (diff)
parentc84e79f6d1ae735bfa191694ec6a62eb8231166d (diff)
downloadluasocket-01162f05408ac4206be15842ef91048c63c23869.tar.gz
luasocket-01162f05408ac4206be15842ef91048c63c23869.tar.bz2
luasocket-01162f05408ac4206be15842ef91048c63c23869.zip
Merge pull request #467 from lunarmodules/fix/http-size-protect
Fix/http size protect
Diffstat (limited to 'test')
-rw-r--r--test/maxsize_http.lua110
-rw-r--r--test/maxsize_tp.lua90
2 files changed, 200 insertions, 0 deletions
diff --git a/test/maxsize_http.lua b/test/maxsize_http.lua
new file mode 100644
index 0000000..3c0dc74
--- /dev/null
+++ b/test/maxsize_http.lua
@@ -0,0 +1,110 @@
1-- Exercises the maxsize caps added to socket.http's line-based receive()
2-- calls (see PLAN-RECEIVE-MAXSIZE.md). Self-contained: uses a single
3-- process with a real TCP loopback connection, so it needs no paired
4-- server script.
5local socket = require "socket"
6local http = require "socket.http"
7local ltn12 = require "ltn12"
8
9local host = "127.0.0.1"
10
11-- connects `open_fn(host, port)` to a freshly bound loopback listener and
12-- returns the client-side object it produced plus the server-side raw
13-- socket accepted for that connection.
14local function new_pair(open_fn)
15 local server = assert(socket.bind(host, 0))
16 local ip, port = server:getsockname()
17 local client = assert(open_fn(ip, port))
18 local srv = assert(server:accept())
19 server:close()
20 return client, srv
21end
22
23local failures = 0
24
25local function check(ok, msg)
26 if ok then
27 print("PASS: " .. msg)
28 else
29 failures = failures + 1
30 print("FAIL: " .. msg)
31 end
32end
33
34local function http_open(ip, port)
35 return http.open(ip, port, socket.tcp)
36end
37
38do -- sanity: normal status line + headers still parse
39 http.MAXHEADERLINE, http.MAXHEADERSIZE = 8192, 65536
40 local h, srv = new_pair(http_open)
41 srv:send("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n")
42 local code = socket.protect(function() return h:receivestatusline() end)()
43 local headers = socket.protect(function() return h:receiveheaders() end)()
44 check(code == 200 and headers and headers["content-length"] == "0",
45 "http: normal status line + headers parse")
46 h:close(); srv:close()
47end
48
49do -- status line over MAXHEADERLINE is rejected
50 http.MAXHEADERLINE, http.MAXHEADERSIZE = 16, 1024
51 local h, srv = new_pair(http_open)
52 srv:send("HTTP/1.1 200 " .. string.rep("x", 40) .. "\r\n")
53 local code, err = socket.protect(function() return h:receivestatusline() end)()
54 check(code == nil and err == "oversized",
55 "http: status line over MAXHEADERLINE -> oversized")
56 h:close(); srv:close()
57end
58
59do -- a single header line over MAXHEADERLINE is rejected
60 http.MAXHEADERLINE, http.MAXHEADERSIZE = 32, 1024
61 local h, srv = new_pair(http_open)
62 srv:send("HTTP/1.1 200 OK\r\n")
63 assert(socket.protect(function() return h:receivestatusline() end)() == 200)
64 srv:send("X-Foo: " .. string.rep("y", 60) .. "\r\n\r\n")
65 local headers, err = socket.protect(function() return h:receiveheaders() end)()
66 check(headers == nil and err == "oversized",
67 "http: single header line over MAXHEADERLINE -> oversized")
68 h:close(); srv:close()
69end
70
71do -- each header line individually fits MAXHEADERLINE, but the total exceeds MAXHEADERSIZE
72 http.MAXHEADERLINE, http.MAXHEADERSIZE = 32, 40
73 local h, srv = new_pair(http_open)
74 srv:send("HTTP/1.1 200 OK\r\n")
75 assert(socket.protect(function() return h:receivestatusline() end)() == 200)
76 -- each header line is ~23 bytes, individually under MAXHEADERLINE(32)
77 srv:send("A: 111111111111111111\r\n")
78 srv:send("B: 222222222222222222\r\n")
79 local headers, err = socket.protect(function() return h:receiveheaders() end)()
80 check(headers == nil and err == "oversized",
81 "http: total headers over MAXHEADERSIZE -> oversized (no single line over MAXHEADERLINE)")
82 h:close(); srv:close()
83end
84
85do -- chunk-size line over MAXHEADERLINE is rejected
86 http.MAXHEADERLINE, http.MAXHEADERSIZE = 32, 1024
87 local h, srv = new_pair(http_open)
88 srv:send("HTTP/1.1 200 OK\r\n")
89 assert(socket.protect(function() return h:receivestatusline() end)() == 200)
90 srv:send("Transfer-Encoding: chunked\r\n\r\n")
91 local headers = assert(socket.protect(function() return h:receiveheaders() end)())
92 srv:send(string.rep("f", 40) .. "\r\n") -- oversized chunk-size line
93 local t = {}
94 local ok, err = socket.protect(function()
95 return h:receivebody(headers, (ltn12.sink.table(t)))
96 end)()
97 check(ok == nil and err == "oversized",
98 "http: chunk-size line over MAXHEADERLINE -> oversized")
99 h:close(); srv:close()
100end
101
102http.MAXHEADERLINE, http.MAXHEADERSIZE = 8192, 65536
103
104if failures == 0 then
105 print("All http maxsize tests passed")
106 os.exit(0)
107else
108 print(failures .. " http maxsize test(s) failed")
109 os.exit(1)
110end
diff --git a/test/maxsize_tp.lua b/test/maxsize_tp.lua
new file mode 100644
index 0000000..57ce9bc
--- /dev/null
+++ b/test/maxsize_tp.lua
@@ -0,0 +1,90 @@
1-- Exercises the maxsize caps added to socket.tp's line-based receive()
2-- calls (see PLAN-RECEIVE-MAXSIZE.md). socket.tp is the shared control
3-- channel underneath both socket.ftp and socket.smtp, so this covers both.
4-- Self-contained: uses a single process with a real TCP loopback
5-- connection, so it needs no paired server script.
6local socket = require "socket"
7local tp = require "socket.tp"
8
9local host = "127.0.0.1"
10
11-- connects `open_fn(host, port)` to a freshly bound loopback listener and
12-- returns the client-side object it produced plus the server-side raw
13-- socket accepted for that connection.
14local function new_pair(open_fn)
15 local server = assert(socket.bind(host, 0))
16 local ip, port = server:getsockname()
17 local client = assert(open_fn(ip, port))
18 local srv = assert(server:accept())
19 server:close()
20 return client, srv
21end
22
23local failures = 0
24
25local function check(ok, msg)
26 if ok then
27 print("PASS: " .. msg)
28 else
29 failures = failures + 1
30 print("FAIL: " .. msg)
31 end
32end
33
34local function tp_open(ip, port)
35 return tp.connect(ip, port, 5)
36end
37
38do -- sanity: normal single-line reply still parses
39 tp.MAXLINE, tp.MAXREPLY = 8192, 65536
40 local c, srv = new_pair(tp_open)
41 srv:send("230 logged in\r\n")
42 local code, reply = c:check("2..")
43 check(code == 230 and reply == "230 logged in",
44 "tp: normal single-line reply parses")
45 c:close(); srv:close()
46end
47
48do -- sanity: normal multiline reply still parses
49 tp.MAXLINE, tp.MAXREPLY = 8192, 65536
50 local c, srv = new_pair(tp_open)
51 srv:send("214-first line\r\n214-second line\r\n214 done\r\n")
52 local code, reply = c:check("2..")
53 check(code == 214 and reply == "214-first line\n214-second line\n214 done",
54 "tp: normal multiline reply parses")
55 c:close(); srv:close()
56end
57
58do -- a single reply line over MAXLINE is rejected
59 tp.MAXLINE, tp.MAXREPLY = 8, 65536
60 local c, srv = new_pair(tp_open)
61 srv:send("230 this line is way over the line cap\r\n")
62 local code, err = c:check("2..")
63 check(code == nil and err == "oversized",
64 "tp: single line over MAXLINE -> oversized")
65 c:close(); srv:close()
66end
67
68do -- each line individually fits MAXLINE, but the reply total exceeds MAXREPLY
69 tp.MAXLINE, tp.MAXREPLY = 16, 20
70 local c, srv = new_pair(tp_open)
71 -- first line: 14 payload bytes, under both MAXLINE(16) and MAXREPLY(20)
72 srv:send("123-aaaaaaaaaa\r\n")
73 -- second line: another 14 payload bytes, individually under MAXLINE(16),
74 -- but only 6 bytes remain in the MAXREPLY(20) budget
75 srv:send("123-bbbbbbbbbb\r\n")
76 local code, err = c:check("2..")
77 check(code == nil and err == "oversized",
78 "tp: multiline reply over MAXREPLY -> oversized (no single line over MAXLINE)")
79 c:close(); srv:close()
80end
81
82tp.MAXLINE, tp.MAXREPLY = 8192, 65536
83
84if failures == 0 then
85 print("All tp maxsize tests passed")
86 os.exit(0)
87else
88 print(failures .. " tp maxsize test(s) failed")
89 os.exit(1)
90end