diff --git a/src/networking.c b/src/networking.c index 23f1c21837..9f4fec0d71 100644 --- a/src/networking.c +++ b/src/networking.c @@ -2684,9 +2684,13 @@ int processMultibulkBuffer(client *c) { c->argv[c->argc++] = createObject(OBJ_STRING,c->querybuf); c->argv_len_sum += c->bulklen; sdsIncrLen(c->querybuf,-2); /* remove CRLF */ - /* Assume that if we saw a fat argument we'll see another one - * likely... */ - c->querybuf = sdsnewlen(SDS_NOINIT,c->bulklen+2); + /* Assume that if we saw a fat argument we'll see another one likely... + * But only if that fat argument is not too big compared to the memory limit. */ + if (!server.maxmemory || (size_t)c->bulklen < server.maxmemory / 32) { + c->querybuf = sdsnewlen(SDS_NOINIT,c->bulklen+2); + } else { + c->querybuf = sdsnewlen(SDS_NOINIT, PROTO_IOBUF_LEN); + } sdsclear(c->querybuf); querybuf_len = sdslen(c->querybuf); /* Update cached length */ } else { diff --git a/tests/unit/maxmemory.tcl b/tests/unit/maxmemory.tcl index 23a9daab89..62f5965a6b 100644 --- a/tests/unit/maxmemory.tcl +++ b/tests/unit/maxmemory.tcl @@ -1,4 +1,17 @@ start_server {tags {"maxmemory" "external:skip"}} { + + test {SET and RESTORE key nearly as large as the memory limit} { + r flushall + set used [s used_memory] + r config set maxmemory [expr {$used+10000000}] + r set foo [string repeat a 8000000] + set encoded [r dump foo] + r del foo + r restore foo 0 $encoded + r strlen foo + } {8000000} {logreqres:skip} + + r flushall r config set maxmemory 11mb r config set maxmemory-policy allkeys-lru set server_pid [s process_id]