skip() ignores do_read()'s return value and unconditionally
subtracts the requested chunk size from 'size' on every iteration.
This was previously bounded by size being 'int': a maliciously
large 64-bit value was truncated on assignment, capping the loop
early by accident.
Now that size is size_t, a crafted file supplying a very large
size causes skip() to keep requesting BUFSIZ-sized reads and
subtracting BUFSIZ from size regardless of whether do_read()
actually succeeds, spinning indefinitely even after EOF or a read
error.
Check do_read()'s return value and break out of the loop on
failure or EOF, so forward progress is only counted when a read
actually succeeds.
Signed-off-by: Tanushree Shah <redacted>
---
tools/perf/util/trace-event-read.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 147a3b95ce06..529a56c3730f 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -71,12 +71,16 @@ static ssize_t do_read(void *data, size_t size)
static void skip(size_t size)
{
char buf[BUFSIZ];
- size_t r;
+ ssize_t ret;
while (size) {
- r = size > BUFSIZ ? BUFSIZ : size;
- do_read(buf, r);
- size -= r;
+ size_t len = size > BUFSIZ ? BUFSIZ : size;
+
+ ret = do_read(buf, len);
+ if (ret <= 0)
+ break;
+
+ size -= ret;
}
}
--
2.47.3