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:
Oran Agra
2025-09-07 16:56:38 +03:00
committed by GitHub
parent d339fe70ad
commit dee0d11a74
2 changed files with 20 additions and 3 deletions

View File

@@ -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 {

View File

@@ -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]