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 <[email protected]> --- 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 53f1920c3fcb..db1622fc99c2 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -72,12 +72,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
