summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2020-07-23 12:37:43 +0300
committerOran Agra <oran@redislabs.com>2021-10-04 13:59:19 +0300
commit12a6b438a34b064389f347a09970237fc5f616d1 (patch)
tree8113567a454d9b398641dca01fc69eccffc37105
parentc6ad876774f3cc11e32681ea02a2eead00f2c521 (diff)
downloadredis-12a6b438a34b064389f347a09970237fc5f616d1.tar.gz
Fix harmless bug in rioConnRead (#7557)
this code is in use only if the master is disk-based, and the replica is diskless. In this case we use a buffered reader, but we must avoid reading past the rdb file, into the command stream. which Luckly rdb.c doesn't really attempt to do (it knows how much it should read). When rioConnRead detects that the extra buffering attempt reaches beyond the read limit it should read less, but if the caller actually requested more, then it should return with an error rather than a short read. the bug would have resulted in short read. in order to fix it, the code must consider the real requested size, and not the extra buffering size. (cherry picked from commit 40d7fca3685d8439bae8480ddbd59775a2390411)
-rw-r--r--src/rio.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/src/rio.c b/src/rio.c
index c8c924380..77ba69fdc 100644
--- a/src/rio.c
+++ b/src/rio.c
@@ -190,15 +190,18 @@ static size_t rioConnRead(rio *r, void *buf, size_t len) {
/* If we don't already have all the data in the sds, read more */
while (len > sdslen(r->io.conn.buf) - r->io.conn.pos) {
size_t buffered = sdslen(r->io.conn.buf) - r->io.conn.pos;
- size_t toread = len - buffered;
+ size_t needs = len - buffered;
/* Read either what's missing, or PROTO_IOBUF_LEN, the bigger of
* the two. */
- if (toread < PROTO_IOBUF_LEN) toread = PROTO_IOBUF_LEN;
+ size_t toread = needs < PROTO_IOBUF_LEN ? PROTO_IOBUF_LEN: needs;
if (toread > sdsavail(r->io.conn.buf)) toread = sdsavail(r->io.conn.buf);
if (r->io.conn.read_limit != 0 &&
r->io.conn.read_so_far + buffered + toread > r->io.conn.read_limit)
{
- if (r->io.conn.read_limit >= r->io.conn.read_so_far - buffered)
+ /* Make sure the caller didn't request to read past the limit.
+ * If they didn't we'll buffer till the limit, if they did, we'll
+ * return an error. */
+ if (r->io.conn.read_limit >= r->io.conn.read_so_far + needs)
toread = r->io.conn.read_limit - r->io.conn.read_so_far - buffered;
else {
errno = EOVERFLOW;