From ba4dce62e408fceea0c39c156aa296ff2b537b1f Mon Sep 17 00:00:00 2001 From: Alexander Turenko Date: Thu, 23 Aug 2018 02:35:41 +0300 Subject: [PATCH] socket: don't truncate a datagram in recv/recvfrom We set MSG_TRUNC for recv / recvfrom calls to receive the real length of the datagram. When the datagram length is larger then the buffer size we set the EMSGSIZE errno, but still return `from` table (in case of recvfrom). Fixes #3619. --- src/lua/socket.c | 7 +++++ src/lua/socket.lua | 6 +++- test/app/socket.result | 64 +++++++++++++++++++++++++++++++++++++++- test/app/socket.test.lua | 20 +++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/lua/socket.c b/src/lua/socket.c index 14d49d106ee3..c1f971c32d1c 100644 --- a/src/lua/socket.c +++ b/src/lua/socket.c @@ -950,6 +950,7 @@ lbox_socket_recvfrom(struct lua_State *L) int fh = lua_tointeger(L, 1); int size = lua_tointeger(L, 2); int flags = lua_tointeger(L, 3); + flags |= MSG_TRUNC; struct sockaddr_storage fa; socklen_t len = sizeof(fa); @@ -968,6 +969,12 @@ lbox_socket_recvfrom(struct lua_State *L) free(buf); lua_pushnil(L); return 1; + } else if (res > size) { + free(buf); + lua_pushnil(L); + lbox_socket_push_addr(L, (struct sockaddr *)&fa, len); + errno = EMSGSIZE; + return 2; } lua_pushcfunction(L, lbox_socket_recvfrom_wrapper); diff --git a/src/lua/socket.lua b/src/lua/socket.lua index 30f21c7177c3..64bdeffdf59c 100644 --- a/src/lua/socket.lua +++ b/src/lua/socket.lua @@ -811,6 +811,7 @@ local function socket_recv(self, size, flags) if size == nil then return nil end + iflags = bit.bor(iflags, internal.SEND_FLAGS['MSG_TRUNC']) else size = size or 512 end @@ -823,6 +824,9 @@ local function socket_recv(self, size, flags) if res == -1 then self._errno = boxerrno() return nil + elseif res > size then + self._errno = boxerrno.EMSGSIZE + return nil end return ffi.string(buf, res) end @@ -848,7 +852,7 @@ local function socket_recvfrom(self, size, flags) local res, from = internal.recvfrom(fd, size, iflags) if res == nil then self._errno = boxerrno() - return nil + return nil, from end return res, from end diff --git a/test/app/socket.result b/test/app/socket.result index 2649e0d8a49d..eddf605dd2d7 100644 --- a/test/app/socket.result +++ b/test/app/socket.result @@ -884,7 +884,7 @@ data, from = s:recvfrom(10) ... data --- -- Hello, Wor +- null ... s:sendto(from.host, from.port, 'Hello, hello!') --- @@ -2658,6 +2658,68 @@ e --- - 0 ... +-- case: recv, datagram that is larger then the buffer of an explicit size +sending_socket:sendto('127.0.0.1', receiving_socket_port, message) +--- +- 1025 +... +received_message = receiving_socket:recv(512) +--- +... +e = receiving_socket:errno() +--- +... +received_message == nil -- expected true +--- +- true +... +received_message +--- +- null +... +e == errno.EMSGSIZE -- expected true +--- +- true +... +e +--- +- 90 +... +-- case: recvfrom, datagram that is larger then the buffer of an explicit size +sending_socket:sendto('127.0.0.1', receiving_socket_port, message) +--- +- 1025 +... +received_message, from = receiving_socket:recvfrom(512) +--- +... +e = receiving_socket:errno() +--- +... +received_message == nil -- expected true +--- +- true +... +received_message +--- +- null +... +from ~= nil -- expected true +--- +- true +... +from.host == '127.0.0.1' -- expected true +--- +- true +... +e == errno.EMSGSIZE -- expected true +--- +- true +... +e +--- +- 90 +... receiving_socket:close() --- - true diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua index 0c4ca90637ca..e49d3484d706 100644 --- a/test/app/socket.test.lua +++ b/test/app/socket.test.lua @@ -895,6 +895,26 @@ from.host == '127.0.0.1' -- expected true e == 0 -- expected true e +-- case: recv, datagram that is larger then the buffer of an explicit size +sending_socket:sendto('127.0.0.1', receiving_socket_port, message) +received_message = receiving_socket:recv(512) +e = receiving_socket:errno() +received_message == nil -- expected true +received_message +e == errno.EMSGSIZE -- expected true +e + +-- case: recvfrom, datagram that is larger then the buffer of an explicit size +sending_socket:sendto('127.0.0.1', receiving_socket_port, message) +received_message, from = receiving_socket:recvfrom(512) +e = receiving_socket:errno() +received_message == nil -- expected true +received_message +from ~= nil -- expected true +from.host == '127.0.0.1' -- expected true +e == errno.EMSGSIZE -- expected true +e + receiving_socket:close() sending_socket:close()