mirror of
https://github.com/redis/redis.git
synced 2026-05-14 03:01:49 -04:00
Avoid OOM error on very big args due to allocation of very big query buffer (#14327)
We have code to assume that if we're facing a big argument, then the next argument is likely to be very big too, so we allocate another huge query buffer. This will backfire and return OOM error on any command with an argument that's larger than half the memory limit (even if the db completely empty). To mitigate that, we reserve query buffer for another big argument, only if that big argument is less than 1/30 of the memory limit.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user