[PATCH 2/3] perf record: Avoid overrunning the zstd output buffer

From: Dmitry Ilvokhin

Date: Thu Jun 18 2026 - 12:13:57 EST


zstd_compress_stream_to_records() compresses one mmap chunk into 'dst'
as a chain of records, decrementing 'dst_size' as each record's header
and compressed payload are written, but it never checks that the space
left can still hold a record before writing one.

When the compressed output does not fit in 'dst', 'dst_size -= size'
underflows ('dst_size' is a size_t), the output size is then taken as
max_record_size again, and ZSTD_compressStream() writes past the end
of 'dst'.

Bail out when the remaining 'dst_size' can no longer hold a full record
(header + max_record_size + 8-byte alignment) rather than writing past
'dst'.

Fixes: f24c1d7523e6 ("perf tools: Introduce Zstd streaming based compression API")
Signed-off-by: Dmitry Ilvokhin <d@xxxxxxxxxxxx>
---
tools/perf/util/zstd.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
index 1955fa2431d1..a0f6572ad201 100644
--- a/tools/perf/util/zstd.c
+++ b/tools/perf/util/zstd.c
@@ -32,7 +32,7 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
void *src, size_t src_size, size_t max_record_size,
size_t process_header(void *record, size_t data_size))
{
- size_t ret, size, compressed = 0;
+ size_t ret, size, compressed = 0, hdr_size = 0;
ZSTD_inBuffer input = { src, src_size, 0 };
ZSTD_outBuffer output;
void *record;
@@ -53,8 +53,14 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_
}

while (input.pos < input.size) {
+ if (hdr_size &&
+ dst_size < hdr_size + max_record_size + sizeof(u64)) {
+ pr_err("failed to compress: output buffer too small\n");
+ return -1;
+ }
record = dst;
size = process_header(record, 0);
+ hdr_size = size;
compressed += size;
dst += size;
dst_size -= size;
--
2.53.0-Meta