From e9f74bbdba08ee85e0ec98d5e7c783a40cec1904 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 24 Nov 2025 11:17:22 +0000 Subject: [PATCH] src: cap the data size in stream I/O functions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The main stream I/O functions have a design flaw in that they accept 'size_t' as the input data length, while intending to return the amount actually processed in an 'int'. Fortunately all functions explicitly document that less data may be processed than requested, and with the remote driver data cap we will never get anywhere near exceeding an 'int' even on 32-bit. For sanity, however, lets explicitly cap the data size in the public API to fix the design flaw. Reviewed-by: Peter Krempa Signed-off-by: Daniel P. Berrangé --- src/libvirt-stream.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c index ca4d90140e..61c700c19e 100644 --- a/src/libvirt-stream.c +++ b/src/libvirt-stream.c @@ -182,6 +182,15 @@ virStreamSend(virStreamPtr stream, virCheckStreamReturn(stream, -1); virCheckNonNullArgGoto(data, error); + /* + * We accept size_t which could be 2^64-1, but we need to return + * bytes processed in a signed int, so must cap the request to + * fit in a 'signed int' on a 32-bit platform. + */ + if (nbytes > G_MAXINT32) { + nbytes = G_MAXINT32; + } + if (stream->driver && stream->driver->streamSend) { int ret; @@ -279,6 +288,15 @@ virStreamRecv(virStreamPtr stream, virCheckStreamReturn(stream, -1); virCheckNonNullArgGoto(data, error); + /* + * We accept size_t which could be 2^64-1, but we need to return + * bytes processed in a signed int, so must cap the request to + * fit in a 'signed int' on a 32-bit platform. + */ + if (nbytes > G_MAXINT32) { + nbytes = G_MAXINT32; + } + if (stream->driver && stream->driver->streamRecv) { int ret; @@ -370,6 +388,15 @@ virStreamRecvFlags(virStreamPtr stream, virCheckStreamReturn(stream, -1); virCheckNonNullArgGoto(data, error); + /* + * We accept size_t which could be 2^64-1, but we need to return + * bytes processed in a signed int, so must cap the request to + * fit in a 'signed int' on a 32-bit platform. + */ + if (nbytes > G_MAXINT32) { + nbytes = G_MAXINT32; + } + if (stream->driver && stream->driver->streamRecvFlags) { int ret; -- 2.47.3