Unverified Commit 40d7fca3 authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

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.
parent 99e6e732
...@@ -190,15 +190,18 @@ static size_t rioConnRead(rio *r, void *buf, size_t len) { ...@@ -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 */ /* 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) { 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 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 /* Read either what's missing, or PROTO_IOBUF_LEN, the bigger of
* the two. */ * 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 (toread > sdsavail(r->io.conn.buf)) toread = sdsavail(r->io.conn.buf);
if (r->io.conn.read_limit != 0 && if (r->io.conn.read_limit != 0 &&
r->io.conn.read_so_far + buffered + toread > r->io.conn.read_limit) 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; toread = r->io.conn.read_limit - r->io.conn.read_so_far - buffered;
else { else {
errno = EOVERFLOW; errno = EOVERFLOW;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment