Skip to content

Commit a8c0f9b

Browse files
limit number of random elements returned based on config, exit loop early if client is being closed
1 parent 36d515e commit a8c0f9b

File tree

6 files changed

+27
-2
lines changed

6 files changed

+27
-2
lines changed

src/config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2912,6 +2912,7 @@ standardConfig configs[] = {
29122912
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, g_pserver->repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
29132913
createLongLongConfig("repl-backlog-disk-reserve", NULL, IMMUTABLE_CONFIG, 0, LLONG_MAX, cserver.repl_backlog_disk_size, 0, MEMORY_CONFIG, NULL, NULL),
29142914
createLongLongConfig("max-snapshot-slip", NULL, MODIFIABLE_CONFIG, 0, 5000, g_pserver->snapshot_slip, 400, 0, NULL, NULL),
2915+
createLongLongConfig("max-rand-count", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX/2, g_pserver->rand_total_threshold, LONG_MAX/2, 0, NULL, NULL),
29152916

29162917
/* Unsigned Long Long configs */
29172918
createULongLongConfig("maxmemory", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, g_pserver->maxmemory, 0, MEMORY_CONFIG, NULL, updateMaxmemory),

src/server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,6 +2729,8 @@ struct redisServer {
27292729
long long repl_batch_offStart = -1;
27302730
long long repl_batch_idxStart = -1;
27312731

2732+
long long rand_total_threshold;
2733+
27322734
int config_soft_shutdown = false;
27332735
bool soft_shutdown = false;
27342736

src/t_hash.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,8 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
10661066
addReplyBulkCBuffer(c, key, sdslen(key));
10671067
if (withvalues)
10681068
addReplyBulkCBuffer(c, value, sdslen(value));
1069+
if (c->flags & CLIENT_CLOSE_ASAP)
1070+
break;
10691071
}
10701072
} else if (hash->encoding == OBJ_ENCODING_ZIPLIST) {
10711073
ziplistEntry *keys, *vals = NULL;
@@ -1079,6 +1081,8 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
10791081
count -= sample_count;
10801082
ziplistRandomPairs((unsigned char*)ptrFromObj(hash), sample_count, keys, vals);
10811083
harndfieldReplyWithZiplist(c, sample_count, keys, vals);
1084+
if (c->flags & CLIENT_CLOSE_ASAP)
1085+
break;
10821086
}
10831087
zfree(keys);
10841088
zfree(vals);
@@ -1231,7 +1235,7 @@ void hrandfieldCommand(client *c) {
12311235
return;
12321236
} else if (c->argc == 4) {
12331237
withvalues = 1;
1234-
if (l < -LONG_MAX/2 || l > LONG_MAX/2) {
1238+
if (l < -g_pserver->rand_total_threshold || l > g_pserver->rand_total_threshold) {
12351239
addReplyError(c,"value is out of range");
12361240
return;
12371241
}

src/t_set.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,10 @@ void srandmemberWithCountCommand(client *c) {
673673
dict *d;
674674

675675
if (getRangeLongFromObjectOrReply(c,c->argv[2],-LONG_MAX,LONG_MAX,&l,NULL) != C_OK) return;
676+
if (l < -g_pserver->rand_total_threshold || l > g_pserver->rand_total_threshold) {
677+
addReplyError(c,"value is out of range");
678+
return;
679+
}
676680
if (l >= 0) {
677681
count = (unsigned long) l;
678682
} else {
@@ -706,6 +710,8 @@ void srandmemberWithCountCommand(client *c) {
706710
} else {
707711
addReplyBulkCBuffer(c,ele,sdslen(ele));
708712
}
713+
if (c->flags & CLIENT_CLOSE_ASAP)
714+
break;
709715
}
710716
return;
711717
}

src/t_zset.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4054,6 +4054,8 @@ void zrandmemberWithCountCommand(client *c, long l, int withscores) {
40544054
addReplyBulkCBuffer(c, key, sdslen(key));
40554055
if (withscores)
40564056
addReplyDouble(c, *(double*)dictGetVal(de));
4057+
if (c->flags & CLIENT_CLOSE_ASAP)
4058+
break;
40574059
}
40584060
} else if (zsetobj->encoding == OBJ_ENCODING_ZIPLIST) {
40594061
ziplistEntry *keys, *vals = NULL;
@@ -4067,6 +4069,8 @@ void zrandmemberWithCountCommand(client *c, long l, int withscores) {
40674069
count -= sample_count;
40684070
ziplistRandomPairs((unsigned char*)ptrFromObj(zsetobj), sample_count, keys, vals);
40694071
zarndmemberReplyWithZiplist(c, sample_count, keys, vals);
4072+
if (c->flags & CLIENT_CLOSE_ASAP)
4073+
break;
40704074
}
40714075
zfree(keys);
40724076
zfree(vals);
@@ -4216,7 +4220,7 @@ void zrandmemberCommand(client *c) {
42164220
return;
42174221
} else if (c->argc == 4) {
42184222
withscores = 1;
4219-
if (l < -LONG_MAX/2 || l > LONG_MAX/2) {
4223+
if (l < -g_pserver->rand_total_threshold || l > g_pserver->rand_total_threshold) {
42204224
addReplyError(c,"value is out of range");
42214225
return;
42224226
}

tests/unit/obuf-limits.tcl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,12 @@ start_server {tags {"obuf-limits"} overrides { server-threads 1 }} {
182182
assert_equal "v2" [r get k2]
183183
assert_equal "v3" [r get k3]
184184
}
185+
186+
test "Obuf limit, HRANDFIELD with huge count stopped mid-run" {
187+
r config set client-output-buffer-limit {normal 1000000 0 0}
188+
r hset myhash a b
189+
catch {r hrandfield myhash -999999999} e
190+
assert_match "*I/O error*" $e
191+
reconnect
192+
}
185193
}

0 commit comments

Comments
 (0)