From dce7cefb7ca5b8efad865fca14c16d773a106e3d Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Fri, 31 Aug 2018 11:49:27 +0800 Subject: [PATCH] networking: fix unexpected negative or zero readlen To avoid copying buffers to create a large Redis Object which exceeding PROTO_IOBUF_LEN 32KB, we just read the remaining data we need, which may less than PROTO_IOBUF_LEN. But the remaining len may be zero, if the bulklen+2 equals sdslen(c->querybuf), in client pause context. For example: Time1: python >>> import os, socket >>> server="127.0.0.1" >>> port=6379 >>> data1="*3\r\n$3\r\nset\r\n$1\r\na\r\n$33000\r\n" >>> data2="".join("x" for _ in range(33000)) + "\r\n" >>> data3="\n\n" >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> s.settimeout(10) >>> s.connect((server, port)) >>> s.send(data1) 28 Time2: redis-cli client pause 10000 Time3: >>> s.send(data2) 33002 >>> s.send(data3) 2 >>> s.send(data3) Traceback (most recent call last): File "", line 1, in socket.error: [Errno 104] Connection reset by peer To fix that, we should check if remaining is greater than zero. --- src/networking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/networking.c b/src/networking.c index 58248ced..17d82d1a 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1439,7 +1439,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { { ssize_t remaining = (size_t)(c->bulklen+2)-sdslen(c->querybuf); - if (remaining < readlen) readlen = remaining; + if (remaining > 0 && remaining < readlen) readlen = remaining; } qblen = sdslen(c->querybuf);