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')