aboutsummaryrefslogtreecommitdiff
path: root/src/tp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/tp.lua')
-rw-r--r--src/tp.lua18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/tp.lua b/src/tp.lua
index bf4bc14..ff5a5cf 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -19,6 +19,10 @@ local _M = socket.tp
19-- Program constants 19-- Program constants
20----------------------------------------------------------------------------- 20-----------------------------------------------------------------------------
21_M.TIMEOUT = 60 21_M.TIMEOUT = 60
22-- maximum size of a single reply line
23_M.MAXLINE = 8192
24-- maximum total size of a (possibly multiline) reply
25_M.MAXREPLY = 65536
22 26
23----------------------------------------------------------------------------- 27-----------------------------------------------------------------------------
24-- Implementation 28-- Implementation
@@ -26,14 +30,24 @@ _M.TIMEOUT = 60
26-- gets server reply (works for SMTP and FTP) 30-- gets server reply (works for SMTP and FTP)
27local function get_reply(c) 31local function get_reply(c)
28 local code, current, sep 32 local code, current, sep
29 local line, err = c:receive("*l") 33 -- bounds total bytes read across a multiline reply, on top of the
34 -- per-line MAXLINE cap, so a peer can't exhaust memory by sending many
35 -- lines that each individually fit under MAXLINE
36 local budget = _M.MAXREPLY
37 local function recvline()
38 if budget <= 0 then return nil, "oversized" end
39 local line, err = c:receive("*l", nil, math.min(budget, _M.MAXLINE))
40 if line then budget = budget - #line end
41 return line, err
42 end
43 local line, err = recvline()
30 local reply = line 44 local reply = line
31 if err then return nil, err end 45 if err then return nil, err end
32 code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) 46 code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
33 if not code then return nil, "invalid server reply" end 47 if not code then return nil, "invalid server reply" end
34 if sep == "-" then -- reply is multiline 48 if sep == "-" then -- reply is multiline
35 repeat 49 repeat
36 line, err = c:receive("*l") 50 line, err = recvline()
37 if err then return nil, err end 51 if err then return nil, err end
38 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) 52 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
39 reply = reply .. "\n" .. line 53 reply = reply .. "\n" .. line