]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
src: cap the data size in stream I/O functions
authorDaniel P. Berrangé <berrange@redhat.com>
Mon, 24 Nov 2025 11:17:22 +0000 (11:17 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Mon, 24 Nov 2025 12:16:56 +0000 (12:16 +0000)
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 <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/libvirt-stream.c

index ca4d90140ee880b2d04db8ad7a14a0e22ccfea74..61c700c19e4429d4772951eff251291a429c502e 100644 (file)
@@ -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;