diff --git a/src/lua/bsdsocket.lua b/src/lua/bsdsocket.lua index 19969320494788bf2fc17a4a599e01a0ec740ef6..eb77a3af0cd62554d801a8490595fe3fa0fb78e4 100644 --- a/src/lua/bsdsocket.lua +++ b/src/lua/bsdsocket.lua @@ -560,29 +560,27 @@ end local function readline_check(self, eols, limit) local rbuf = self.rbuf - if rbuf == nil then - return nil - end if string.len(rbuf) == 0 then return nil end local shortest - for i, eol in pairs(eols) do - if string.len(rbuf) >= string.len(eol) then - local data = string.match(rbuf, "^(.-" .. eol .. ")") - if data ~= nil then - if string.len(data) > limit then - data = string.sub(data, 1, limit) - end - if shortest == nil then - shortest = data - elseif #shortest > #data then - shortest = data - end + for i, eol in ipairs(eols) do + local data = string.match(rbuf, "^(.-" .. eol .. ")") + if data ~= nil then + if string.len(data) > limit then + data = string.sub(data, 1, limit) + end + if shortest == nil then + shortest = data + elseif #shortest > #data then + shortest = data end end end + if shortest == nil and #rbuf >= limit then + return string.sub(rbuf, 1, limit) + end return shortest end @@ -592,6 +590,9 @@ local function readline(self, limit, eol, timeout) end self._errno = nil + if limit == 0 then + return '' + end local data = readline_check(self, eol, limit) if data ~= nil then self.rbuf = string.sub(self.rbuf, string.len(data) + 1) diff --git a/test/box/bsdsocket.result b/test/box/bsdsocket.result index 06e5e066d9f58d327b7174be57988fe3f36b7006..5ef12fd2ebb1399b96800390a8c81b2d9b029a4f 100644 --- a/test/box/bsdsocket.result +++ b/test/box/bsdsocket.result @@ -1377,6 +1377,80 @@ server:close() --- - true ... +-- gh-658: socket:read() incorrectly handles size and delimiter together +body = "a 10\nb 15\nabc" +--- +... +remaining = #body +--- +... +--# setopt delimiter ';' +server = socket.tcp_server('unix/', path, function(s) + s:write(body) + s:read(100500) +end); +--- +... +--# setopt delimiter '' +client = socket.tcp_connect('unix/', path) +--- +... +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +--- +... +buf == "a 10\n" +--- +- true +... +remaining = remaining - #buf +--- +... +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +--- +... +buf == "b 15\n" +--- +- true +... +remaining = remaining - #buf +--- +... +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +--- +... +buf == "abc" +--- +- true +... +remaining = remaining - #buf +--- +... +remaining == 0 +--- +- true +... +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +--- +... +buf == "" +--- +- true +... +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +--- +... +buf == "" +--- +- true +... +client:close() +--- +- true +... +server:close() +--- +- true +... -- Test that socket is closed on GC s = socket('AF_UNIX', 'SOCK_STREAM', 'ip') --- diff --git a/test/box/bsdsocket.test.lua b/test/box/bsdsocket.test.lua index e28b420c3e7140d0d4a7bef296c2e52b17127fe5..98ac0a4d2200e84ee7a28a3053135e794259db28 100644 --- a/test/box/bsdsocket.test.lua +++ b/test/box/bsdsocket.test.lua @@ -462,6 +462,32 @@ client = socket.tcp_connect('unix/', path) client:read{ line = { "\n\n", "\r\n\r\n" } } server:close() +-- gh-658: socket:read() incorrectly handles size and delimiter together +body = "a 10\nb 15\nabc" +remaining = #body +--# setopt delimiter ';' +server = socket.tcp_server('unix/', path, function(s) + s:write(body) + s:read(100500) +end); +--# setopt delimiter '' +client = socket.tcp_connect('unix/', path) +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +buf == "a 10\n" +remaining = remaining - #buf +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +buf == "b 15\n" +remaining = remaining - #buf +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +buf == "abc" +remaining = remaining - #buf +remaining == 0 +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +buf == "" +buf = client:read({ size = remaining, delimiter = "[\r\n]+"}) +buf == "" +client:close() +server:close() -- Test that socket is closed on GC s = socket('AF_UNIX', 'SOCK_STREAM', 'ip')