Commit bd85fd7cde for openssl.org
commit bd85fd7cde7cefc417d0c30ed29fc3eb5ad3e71c
Author: kovan <xaum.io@gmail.com>
Date: Thu Jan 29 15:28:59 2026 +0100
doc: add documentation for BIO_nread0, BIO_nread, BIO_nwrite0, BIO_nwrite
Document the non-copying interface functions for BIO pairs that allow
direct access to the internal buffer:
- BIO_nread0/BIO_nread for zero-copy reading
- BIO_nwrite0/BIO_nwrite for zero-copy writing
Also add return value documentation for these functions and remove
the placeholder "[XXXXX: More return values need to be added here]".
Fixes #16366
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
MergeDate: Wed May 6 14:51:27 2026
(Merged from https://github.com/openssl/openssl/pull/29849)
diff --git a/doc/man3/BIO_s_bio.pod b/doc/man3/BIO_s_bio.pod
index 653fe4785a..482edfcfc8 100644
--- a/doc/man3/BIO_s_bio.pod
+++ b/doc/man3/BIO_s_bio.pod
@@ -5,7 +5,8 @@
BIO_s_bio, BIO_make_bio_pair, BIO_destroy_bio_pair, BIO_shutdown_wr,
BIO_set_write_buf_size, BIO_get_write_buf_size, BIO_new_bio_pair,
BIO_get_write_guarantee, BIO_ctrl_get_write_guarantee, BIO_get_read_request,
-BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request - BIO pair BIO
+BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request,
+BIO_nread0, BIO_nread, BIO_nwrite0, BIO_nwrite - BIO pair BIO
=head1 SYNOPSIS
@@ -28,6 +29,11 @@ BIO_ctrl_get_read_request, BIO_ctrl_reset_read_request - BIO pair BIO
size_t BIO_ctrl_get_read_request(BIO *b);
int BIO_ctrl_reset_read_request(BIO *b);
+ int BIO_nread0(BIO *bio, char **buf);
+ int BIO_nread(BIO *bio, char **buf, int num);
+ int BIO_nwrite0(BIO *bio, char **buf);
+ int BIO_nwrite(BIO *bio, char **buf, int num);
+
=head1 DESCRIPTION
BIO_s_bio() returns the method for a BIO pair. A BIO pair is a pair of source/sink
@@ -98,6 +104,44 @@ than that returned by BIO_get_write_guarantee().
BIO_ctrl_reset_read_request() can also be used to reset the value returned by
BIO_get_read_request() to zero.
+=head2 Non-copying Interface
+
+BIO_nread0(), BIO_nread(), BIO_nwrite0(), and BIO_nwrite() provide a non-copying
+interface for reading from and writing to BIO pairs. These functions allow
+direct access to the internal buffer, avoiding the overhead of copying data.
+
+BIO_nread0() returns in B<*buf> a pointer to the start of the available data
+in the peer's write buffer and returns the number of bytes available.
+This allows reading directly from the buffer without copying.
+It does not consume the data; a subsequent call to BIO_nread() is needed
+to advance the buffer position.
+
+BIO_nread() is similar to BIO_nread0() but also advances the read position
+by up to B<num> bytes. The actual number of bytes consumed is returned.
+The B<*buf> pointer is set to the start of the data that was consumed.
+Since the data is considered consumed after this call, the pointer returned
+by BIO_nread() should not be used afterwards unless the caller also
+controls the writing side. The typical pattern is to call BIO_nread0() first,
+use the data, and then call BIO_nread() to consume it.
+
+BIO_nwrite0() returns in B<*buf> a pointer to the start of the available
+space in the write buffer and returns the number of bytes that can be written.
+This allows writing directly to the buffer without copying.
+It does not commit the data; a subsequent call to BIO_nwrite() is needed
+to update the buffer length.
+
+BIO_nwrite() is similar to BIO_nwrite0() but also commits up to B<num> bytes
+as written. The actual number of bytes committed is returned.
+The B<*buf> pointer is set to the start of the region that was committed.
+BIO_nwrite() should only be called after the data has actually been written
+to the buffer obtained from BIO_nwrite0(), since committing signals data
+availability to the reading side.
+
+Note that due to the ring buffer implementation, if wrapping around would be
+required, BIO_nread0() and BIO_nwrite0() may return less than the total
+available space. In such cases, a second call may be needed to access the
+remaining data or space.
+
=head1 NOTES
Both halves of a BIO pair should be freed. That is even if one half is implicit
@@ -133,6 +177,17 @@ locations for B<bio1> and B<bio2>. Check the error stack for more information.
[XXXXX: More return values need to be added here]
+BIO_nread0() returns the number of bytes available for reading, 0 if the peer
+has closed and no data remains (EOF), or -1 if no data is currently available
+(retry may be appropriate). If the BIO is not initialized, -2 is returned.
+
+BIO_nwrite0() returns the number of bytes of space available for writing, or -1
+if no space is currently available (retry may be appropriate) or the BIO has
+been closed. If the BIO is not initialized, -2 is returned.
+
+BIO_nread() and BIO_nwrite() return the number of bytes consumed or committed
+respectively, or the same error values as BIO_nread0() and BIO_nwrite0().
+
=head1 EXAMPLES
The BIO pair can be used to have full control over the network access of an
@@ -176,6 +231,30 @@ and must be transferred to the network. Use BIO_ctrl_get_read_request() to
find out, how many bytes must be written into the buffer before the
SSL_operation() can successfully be continued.
+A typical usage pattern for the non-copying write interface is:
+
+ int ret;
+ char *buf;
+
+ ret = BIO_nwrite0(bio, &buf);
+ if (ret > 0) {
+ /* write up to 'ret' bytes directly to 'buf' */
+ memcpy(buf, data, len);
+ BIO_nwrite(bio, &buf, len); /* commit the write */
+ }
+
+A typical usage pattern for the non-copying read interface is:
+
+ int ret;
+ char *buf;
+
+ ret = BIO_nread0(bio, &buf);
+ if (ret > 0) {
+ /* read up to 'ret' bytes directly from 'buf' */
+ process_data(buf, ret);
+ BIO_nread(bio, &buf, ret); /* consume the data */
+ }
+
=head1 WARNINGS
As the data is buffered, SSL_operation() may return with an ERROR_SSL_WANT_READ
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index 884aeeeb68..57a255a4a5 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -189,12 +189,8 @@ BIO_method_name(3)
BIO_new_NDEF(3)
BIO_new_PKCS7(3)
BIO_new_dgram_sctp(3)
-BIO_nread(3)
-BIO_nread0(3)
BIO_number_read(3)
BIO_number_written(3)
-BIO_nwrite(3)
-BIO_nwrite0(3)
BIO_s_datagram_sctp(3)
BIO_s_log(3)
BIO_set_tcp_ndelay(3)