From: Igor Ustinov Date: Fri, 12 Dec 2025 15:26:58 +0000 (+0100) Subject: Fix the converters between the old and new BIO_read functions to handle X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be42447469dcccc68b7e115c7947e3c25124f3f2;p=thirdparty%2Fopenssl.git Fix the converters between the old and new BIO_read functions to handle end-of-file state properly. Related to openssl/project#1745 Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell MergeDate: Thu Feb 12 08:34:31 2026 (Merged from https://github.com/openssl/openssl/pull/29290) --- diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index 6b27a1c1d69..5be3acca5a9 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -254,10 +254,14 @@ int BIO_method_type(const BIO *b) } /* - * This is essentially the same as BIO_read_ex() except that it allows - * 0 or a negative value to indicate failure (retryable or not) in the return. - * This is for compatibility with the old style BIO_read(), where existing code - * may make assumptions about the return value that it might get. + * Internal BIO read function. Attempts to read dlen bytes from BIO b and + * places them in data. If any bytes were successfully read, then the number + * of bytes read is stored in readbytes. + * For compatibility with the old-style BIO_read() API, the function uses a + * return-value convention where a positive value indicates success, + * 0 indicates end-of-file, and a negative value indicates an error + * (including retryable errors). + * It also returns 0 if dlen==0. */ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) { @@ -285,6 +289,13 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) if (ret > 0) b->num_read += (uint64_t)*readbytes; + /* + * If method->bread() returned 0 when dlen>0, it can be either EOF or + * an error, and we should distinguish them + */ + if (ret == 0 && dlen > 0 && BIO_eof(b) != 1) + ret = -1; + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, dlen, 0, 0L, ret, readbytes); @@ -303,8 +314,10 @@ int BIO_read(BIO *b, void *data, int dlen) size_t readbytes; int ret; - if (dlen < 0) - return 0; + if (dlen < 0) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT); + return -1; + } ret = bio_read_intern(b, data, (size_t)dlen, &readbytes); @@ -679,6 +692,13 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) return ret; } +int BIO_eof(BIO *b) +{ + if ((b->flags & BIO_FLAGS_AUTO_EOF) != 0) + return 1; + return (int)BIO_ctrl(b, BIO_CTRL_EOF, 0, NULL); +} + long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret; diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c index 0cab60491e7..1b74ae04ab9 100644 --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -121,12 +121,25 @@ int bread_conv(BIO *bio, char *data, size_t datal, size_t *readbytes) { int ret; + if (datal == 0) { + *readbytes = 0; + return 1; + } + if (datal > INT_MAX) datal = INT_MAX; ret = bio->method->bread_old(bio, data, (int)datal); - if (ret <= 0) { + bio->flags &= ~BIO_FLAGS_AUTO_EOF; + if (ret == 0) { + if (BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL) == 0) + bio->flags |= BIO_FLAGS_AUTO_EOF; + *readbytes = 0; + return 0; + } + + if (ret < 0) { *readbytes = 0; return ret; } diff --git a/doc/man3/BIO_meth_new.pod b/doc/man3/BIO_meth_new.pod index e7d5ff67238..7f454729e26 100644 --- a/doc/man3/BIO_meth_new.pod +++ b/doc/man3/BIO_meth_new.pod @@ -111,16 +111,35 @@ BIO_meth_get_write_ex() and BIO_meth_set_write_ex() get and set the function used for writing arbitrary length data to the BIO respectively. This function will be called in response to the application calling BIO_write_ex() or BIO_write(). The parameters for the function have the same meaning as for -BIO_write_ex(). Older code may call BIO_meth_get_write() and -BIO_meth_set_write() instead. Applications should not call both -BIO_meth_set_write_ex() and BIO_meth_set_write() or call BIO_meth_get_write() +BIO_write_ex() and it must return values as described for BIO_write_ex(). + +Older code may call BIO_meth_get_write() and BIO_meth_set_write() instead +to set an old-style write function. The parameters for the function have the +same meaning as for BIO_write() and it must return values as described for +BIO_write(). + +Functions set by BIO_meth_set_write_ex() and BIO_meth_set_write() must call +BIO_set_flags() to set the BIO_FLAGS_SHOULD_RETRY flag in relevant situations. + +Applications should not call both BIO_meth_set_write_ex() and +BIO_meth_set_write() or call BIO_meth_get_write() when the function was set with BIO_meth_set_write_ex(). BIO_meth_get_read_ex() and BIO_meth_set_read_ex() get and set the function used for reading arbitrary length data from the BIO respectively. This function will be called in response to the application calling BIO_read_ex() or BIO_read(). -The parameters for the function have the same meaning as for BIO_read_ex(). -Older code may call BIO_meth_get_read() and BIO_meth_set_read() instead. +The parameters for the function have the same meaning as for BIO_read_ex() +and it must return values as described for BIO_read_ex(). +The function must handle the end-of-file condition (if applicable) and return 0 +in this case. + +Older code may call BIO_meth_get_read() and BIO_meth_set_read() instead to +set an old-style read function. The parameters for the function have the same +meaning as for BIO_read() and it must return values as described for BIO_read(). + +Functions set by BIO_meth_set_read_ex() and BIO_meth_set_read() must call +BIO_set_flags() to set the BIO_FLAGS_SHOULD_RETRY flag in relevant situations. + Applications should not call both BIO_meth_set_read_ex() and BIO_meth_set_read() or call BIO_meth_get_read() when the function was set with BIO_meth_set_read_ex(). @@ -141,6 +160,14 @@ processing ctrl messages in the BIO respectively. See the L page fo more information. This function will be called in response to the application calling BIO_ctrl(). The parameters for the function have the same meaning as for BIO_ctrl(). +If the concept of end-of-file is meaningful for a BIO and the read method is +set using BIO_meth_set_read_ex(), the ctrl function must handle the BIO_CTRL_EOF +command and return an appropriate value (1 if EOF has been reached, 0 if not, +or a negative value on failure), at least immediately after a read operation. +If the read method is set using BIO_meth_set_read(), handling of the +BIO_CTRL_EOF command is not mandatory; however, if such handling is implemented, +it must return 1 if the read function returned 0 when attempting to read a +nonzero number of bytes. BIO_meth_get_create() and BIO_meth_set_create() get and set the function used for creating a new instance of the BIO respectively. This function will be diff --git a/doc/man3/BIO_read.pod b/doc/man3/BIO_read.pod index f337aab353b..ff405a83203 100644 --- a/doc/man3/BIO_read.pod +++ b/doc/man3/BIO_read.pod @@ -61,6 +61,11 @@ BIO_read_ex() returns 1 if data was successfully read, and 0 otherwise. BIO_write_ex() returns 1 if no error was encountered writing data, 0 otherwise. Requesting to write 0 bytes is not considered an error. +BIO_read() returns the number of bytes read on success. +A return value of 0 indicates that end-of-file was reached, or that a read +of zero bytes was requested. +A negative return value indicates an error condition. + BIO_write() returns -2 if the "write" operation is not implemented by the BIO or -1 on other errors. Otherwise it returns the number of bytes written. diff --git a/doc/man3/BIO_set_flags.pod b/doc/man3/BIO_set_flags.pod index 7899cc3e575..d822fbc437d 100644 --- a/doc/man3/BIO_set_flags.pod +++ b/doc/man3/BIO_set_flags.pod @@ -112,6 +112,13 @@ Set if the last I/O operation on the B should be retried at a later time. If this bit is not set then the condition is treated as an error. This flag is normally set by the B implementation. +=back + +The following flag can be used only with the B. +The result of using this flag with other BIOs is unpredictable. + +=over 4 + =item B When set on a base64 filter B this flag disables the generation of @@ -119,6 +126,14 @@ newline characters in the encoded output and causes newlines to be ignored in the input. See also L. The flag has no effect on any other built-in B types. +=back + +The following flags can be used only with the B and +B. The result of using these flags with other BIOs +is unpredictable. + +=over 4 + =item B When set on a memory B this flag indicates that the underlying buffer is @@ -134,12 +149,8 @@ The flag has no effect on any other built-in B types. =item B -This flag may be used by a B implementation to indicate that the end -of the input stream has been reached. However, B types are not -required to use this flag to signal end-of-file conditions; they may rely -on other mechanisms such as system calls or by querying the next B in a -chain. Applications must therefore not test this flag directly to -determine whether EOF has been reached, and must use BIO_eof() instead. +This flag is for internal use only. It should not be used outside BIO +implementations. =back diff --git a/include/internal/bio.h b/include/internal/bio.h index 3602ab5eb1a..cee0e9d6564 100644 --- a/include/internal/bio.h +++ b/include/internal/bio.h @@ -44,6 +44,10 @@ int bread_conv(BIO *bio, char *data, size_t datal, size_t *read); #define BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG 75 #define BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE 90 +/* Internal BIO flags */ + +#define BIO_FLAGS_AUTO_EOF 0x80 + /* * This is used with memory BIOs: * BIO_FLAGS_MEM_LEGACY_EOF means legacy behaviour of BIO_eof() diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index ba8e81e7084..47e565174d8 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -230,6 +230,17 @@ extern "C" { #define BIO_FLAGS_UPLINK 0 #endif +/* the BIO FLAGS values 0x10 to 0x80 are reserved for internal use */ + +/* + * BIO FLAGS in the range 0x0100..0x8000 are BIO-type specific. + * Their meaning is defined by the particular BIO implementation and + * is not shared across different BIO types. The same bit value may + * have a different meaning or no meaning at all in other BIOs. + * Such flags may be part of the public API or internal to the BIO. + */ + +/* This is used with base64 BIO */ #define BIO_FLAGS_BASE64_NO_NL 0x100 /* @@ -241,8 +252,6 @@ extern "C" { #define BIO_FLAGS_NONCLEAR_RST 0x400 #define BIO_FLAGS_IN_EOF 0x800 -/* the BIO FLAGS values 0x1000 to 0x8000 are reserved for internal KTLS flags */ - typedef union bio_addr_st BIO_ADDR; typedef struct bio_addrinfo_st BIO_ADDRINFO; @@ -607,7 +616,6 @@ int BIO_read_filename(BIO *b, const char *name); #define BIO_dup_state(b, ret) BIO_ctrl(b, BIO_CTRL_DUP, 0, (char *)(ret)) #define BIO_reset(b) (int)BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL) -#define BIO_eof(b) (int)BIO_ctrl(b, BIO_CTRL_EOF, 0, NULL) #define BIO_set_close(b, c) (int)BIO_ctrl(b, BIO_CTRL_SET_CLOSE, (c), NULL) #define BIO_get_close(b) (int)BIO_ctrl(b, BIO_CTRL_GET_CLOSE, 0, NULL) #define BIO_pending(b) (int)BIO_ctrl(b, BIO_CTRL_PENDING, 0, NULL) @@ -733,6 +741,7 @@ __owur int BIO_get_wpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc); int BIO_puts(BIO *bp, const char *buf); int BIO_indent(BIO *b, int indent, int max); long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); +int BIO_eof(BIO *b); long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); diff --git a/test/bio_callback_test.c b/test/bio_callback_test.c index 305abe0e1a8..a173a5e1d28 100644 --- a/test/bio_callback_test.c +++ b/test/bio_callback_test.c @@ -13,7 +13,7 @@ #include "testutil.h" -#define MAXCOUNT 5 +#define MAXCOUNT 7 static int my_param_count; static BIO *my_param_b[MAXCOUNT]; static int my_param_oper[MAXCOUNT]; @@ -138,20 +138,20 @@ static int test_bio_callback_ex(void) my_param_count = 0; i = BIO_read(bio, buf, sizeof(buf)); if (!TEST_int_eq(i, 0) - || !TEST_int_eq(my_param_count, 2) + || !TEST_int_eq(my_param_count, 6) || !TEST_ptr_eq(my_param_b[0], bio) || !TEST_int_eq(my_param_oper[0], BIO_CB_READ) || !TEST_ptr_eq(my_param_argp[0], buf) || !TEST_size_t_eq(my_param_len[0], sizeof(buf)) || !TEST_long_eq(my_param_argl[0], 0L) || !TEST_int_eq((int)my_param_ret[0], 1) - || !TEST_ptr_eq(my_param_b[1], bio) - || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN) - || !TEST_ptr_eq(my_param_argp[1], buf) - || !TEST_size_t_eq(my_param_len[1], sizeof(buf)) - || !TEST_long_eq(my_param_argl[1], 0L) - || !TEST_size_t_eq(my_param_processed[1], 0) - || !TEST_int_eq((int)my_param_ret[1], 0)) + || !TEST_ptr_eq(my_param_b[5], bio) + || !TEST_int_eq(my_param_oper[5], BIO_CB_READ | BIO_CB_RETURN) + || !TEST_ptr_eq(my_param_argp[5], buf) + || !TEST_size_t_eq(my_param_len[5], sizeof(buf)) + || !TEST_long_eq(my_param_argl[5], 0L) + || !TEST_size_t_eq(my_param_processed[5], 0) + || !TEST_int_eq((int)my_param_ret[5], 0)) goto err; my_param_count = 0; @@ -291,19 +291,19 @@ static int test_bio_callback(void) my_param_count = 0; i = BIO_read(bio, buf, sizeof(buf)); if (!TEST_int_eq(i, 0) - || !TEST_int_eq(my_param_count, 2) + || !TEST_int_eq(my_param_count, 6) || !TEST_ptr_eq(my_param_b[0], bio) || !TEST_int_eq(my_param_oper[0], BIO_CB_READ) || !TEST_ptr_eq(my_param_argp[0], buf) || !TEST_int_eq(my_param_argi[0], sizeof(buf)) || !TEST_long_eq(my_param_argl[0], 0L) || !TEST_long_eq(my_param_ret[0], 1L) - || !TEST_ptr_eq(my_param_b[1], bio) - || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN) - || !TEST_ptr_eq(my_param_argp[1], buf) - || !TEST_int_eq(my_param_argi[1], sizeof(buf)) - || !TEST_long_eq(my_param_argl[1], 0L) - || !TEST_long_eq(my_param_ret[1], 0L)) + || !TEST_ptr_eq(my_param_b[5], bio) + || !TEST_int_eq(my_param_oper[5], BIO_CB_READ | BIO_CB_RETURN) + || !TEST_ptr_eq(my_param_argp[5], buf) + || !TEST_int_eq(my_param_argi[5], sizeof(buf)) + || !TEST_long_eq(my_param_argl[5], 0L) + || !TEST_long_eq(my_param_ret[5], 0L)) goto err; my_param_count = 0; diff --git a/test/bio_eof_test.c b/test/bio_eof_test.c new file mode 100644 index 00000000000..f9f8aa8a666 --- /dev/null +++ b/test/bio_eof_test.c @@ -0,0 +1,232 @@ +/* + * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "testutil.h" + +#define TEST_FLAG_EOF_BEHAVIOUR 0x1000 + +static int bio_create(BIO *bio) +{ + BIO_set_init(bio, 1); + return 1; +} + +static int bio_destroy(BIO *bio) +{ + BIO_set_init(bio, 0); + return 1; +} + +/* + * Test1 & Test2 read callback (old style): + * returns 0 if TEST_FLAG_EOF_BEHAVIOUR is set, else -1. + */ +static int old_read_returns_0_or_minus1(BIO *bio, char *buf, int len) +{ + (void)buf; + (void)len; + return BIO_test_flags(bio, TEST_FLAG_EOF_BEHAVIOUR) ? 0 : -1; +} + +/* + * Test3 read_ex callback (new style): + * does nothing, always returns 0, sets *readbytes to 0. + */ +static int new_read_ex_always_0(BIO *bio, char *buf, size_t len, size_t *readbytes) +{ + (void)bio; + (void)buf; + (void)len; + if (readbytes != NULL) + *readbytes = 0; + return 0; +} + +/* Test1 ctrl: does nothing */ +static long ctrl_noop(BIO *bio, int cmd, long num, void *ptr) +{ + (void)bio; + (void)cmd; + (void)num; + (void)ptr; + return 0; +} + +/* Test2 ctrl: BIO_CTRL_EOF always returns 1 */ +static long ctrl_eof_always_1(BIO *bio, int cmd, long num, void *ptr) +{ + (void)bio; + (void)num; + (void)ptr; + if (cmd == BIO_CTRL_EOF) + return 1; + return 0; +} + +/* Test3 ctrl: BIO_CTRL_EOF returns 1 if TEST_FLAG_EOF_BEHAVIOUR is set */ +static long ctrl_eof_depends_on_flag(BIO *bio, int cmd, long num, void *ptr) +{ + (void)num; + (void)ptr; + if (cmd == BIO_CTRL_EOF) + return BIO_test_flags(bio, TEST_FLAG_EOF_BEHAVIOUR) ? 1 : 0; + return 0; +} + +static BIO_METHOD *make_meth_oldread(long (*ctrl)(BIO *, int, long, void *), + const char *name) +{ + BIO_METHOD *meth = NULL; + + if (!TEST_ptr(meth = BIO_meth_new(BIO_TYPE_SOURCE_SINK, name))) + goto err; + if (!TEST_int_eq(BIO_meth_set_read(meth, old_read_returns_0_or_minus1), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_ctrl(meth, ctrl), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_create(meth, bio_create), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_destroy(meth, bio_destroy), 1)) + goto err; + return meth; + +err: + BIO_meth_free(meth); + return NULL; +} + +static BIO_METHOD *make_meth_newreadex(long (*ctrl)(BIO *, int, long, void *), + const char *name) +{ + BIO_METHOD *meth = NULL; + + if (!TEST_ptr(meth = BIO_meth_new(BIO_TYPE_SOURCE_SINK, name))) + goto err; + if (!TEST_int_eq(BIO_meth_set_read_ex(meth, new_read_ex_always_0), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_ctrl(meth, ctrl), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_create(meth, bio_create), 1)) + goto err; + if (!TEST_int_eq(BIO_meth_set_destroy(meth, bio_destroy), 1)) + goto err; + return meth; + +err: + BIO_meth_free(meth); + return NULL; +} + +static int run_subtest(const char *label, BIO_METHOD *meth, + int set_flag, int use_read_ex, + int exp_read_ret, int exp_eof_ret) +{ + BIO *bio = NULL; + char b = 0; + int r, eofr; + size_t n; + + if (!TEST_ptr(bio = BIO_new(meth))) + goto err; + + if (set_flag) + BIO_set_flags(bio, TEST_FLAG_EOF_BEHAVIOUR); + else + BIO_clear_flags(bio, TEST_FLAG_EOF_BEHAVIOUR); + + if (use_read_ex) { + r = BIO_read_ex(bio, &b, 1, &n); + if (!TEST_int_eq(r, exp_read_ret)) { + TEST_info("%s: BIO_read_ex ret=%d expected=%d", label, r, exp_read_ret); + goto err; + } + } else { + r = BIO_read(bio, &b, 1); + if (!TEST_int_eq(r, exp_read_ret)) { + TEST_info("%s: BIO_read ret=%d expected=%d", label, r, exp_read_ret); + goto err; + } + } + + eofr = BIO_eof(bio); + if (!TEST_int_eq(eofr, exp_eof_ret)) { + TEST_info("%s: BIO_eof ret=%d expected=%d", label, eofr, exp_eof_ret); + goto err; + } + + BIO_free(bio); + return 1; + +err: + BIO_free(bio); + return 0; +} + +static int old_style_read_without_eof_ctrl(void) +{ + int ok = 1; + BIO_METHOD *meth = NULL; + + if (!TEST_ptr(meth = make_meth_oldread(ctrl_noop, + "Old-style read without eof ctrl"))) + return 0; + + ok &= run_subtest("BIO_read, eof", meth, 1, 0, 0, 1); + ok &= run_subtest("BIO_read_ex, eof", meth, 1, 1, 0, 1); + ok &= run_subtest("BIO_read, error", meth, 0, 0, -1, 0); + ok &= run_subtest("BIO_read_ex, error", meth, 0, 1, 0, 0); + + BIO_meth_free(meth); + return ok; +} + +static int old_style_read_with_eof_ctrl(void) +{ + int ok = 1; + BIO_METHOD *meth = NULL; + + if (!TEST_ptr(meth = make_meth_oldread(ctrl_eof_always_1, + "Old-stype read with eof ctrl"))) + return 0; + + ok &= run_subtest("BIO_read, eof", meth, 1, 0, 0, 1); + ok &= run_subtest("BIO_read_ex, eof", meth, 1, 1, 0, 1); + ok &= run_subtest("BIO_read, error", meth, 0, 0, -1, 1); + ok &= run_subtest("BIO_read_ex, error", meth, 0, 1, 0, 1); + + BIO_meth_free(meth); + return ok; +} + +static int new_style_read_ex(void) +{ + int ok = 1; + BIO_METHOD *meth = NULL; + + if (!TEST_ptr(meth = make_meth_newreadex(ctrl_eof_depends_on_flag, + "New-style read_ex"))) + return 0; + + ok &= run_subtest("BIO_read, eof", meth, 1, 0, 0, 1); + ok &= run_subtest("BIO_read_ex, eof", meth, 1, 1, 0, 1); + ok &= run_subtest("BIO_read, error", meth, 0, 0, -1, 0); + ok &= run_subtest("BIO_read_ex, error", meth, 0, 1, 0, 0); + + BIO_meth_free(meth); + return ok; +} + +int setup_tests(void) +{ + ADD_TEST(old_style_read_without_eof_ctrl); + ADD_TEST(old_style_read_with_eof_ctrl); + ADD_TEST(new_style_read_ex); + return 1; +} diff --git a/test/build.info b/test/build.info index 8ba5587bb30..78e253e7d99 100644 --- a/test/build.info +++ b/test/build.info @@ -71,7 +71,7 @@ IF[{- !$disabled{tests} -}] fips_version_test x509_test hpke_test pairwise_fail_test \ nodefltctxtest evp_xof_test x509_load_cert_file_test bio_meth_test \ x509_acert_test x509_req_test strtoultest bio_pw_callback_test \ - engine_stubs_test base64_simdutf_test + engine_stubs_test base64_simdutf_test bio_eof_test IF[{- !$disabled{'rpk'} -}] PROGRAMS{noinst}=rpktest @@ -545,6 +545,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[bio_meth_test]=../include ../apps/include DEPEND[bio_meth_test]=../libcrypto libtestutil.a + SOURCE[bio_eof_test]=bio_eof_test.c + INCLUDE[bio_eof_test]=../include ../apps/include + DEPEND[bio_eof_test]=../libcrypto libtestutil.a + SOURCE[bioprinttest]=bioprinttest.c INCLUDE[bioprinttest]=../include ../apps/include IF[{- $config{target} =~ /^VC/ -}] diff --git a/test/recipes/61-test_bio_eof.t b/test/recipes/61-test_bio_eof.t new file mode 100644 index 00000000000..0a8d0841a55 --- /dev/null +++ b/test/recipes/61-test_bio_eof.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use OpenSSL::Test::Simple; + +simple_test("test_bio_eof", "bio_eof_test"); + diff --git a/util/libcrypto.num b/util/libcrypto.num index 80eb4309a7b..1213bfcbe4a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -2908,6 +2908,7 @@ BIO_get_wpoll_descriptor ? 4_0_0 EXIST::FUNCTION: BIO_puts ? 4_0_0 EXIST::FUNCTION: BIO_indent ? 4_0_0 EXIST::FUNCTION: BIO_ctrl ? 4_0_0 EXIST::FUNCTION: +BIO_eof ? 4_0_0 EXIST::FUNCTION: BIO_callback_ctrl ? 4_0_0 EXIST::FUNCTION: BIO_ptr_ctrl ? 4_0_0 EXIST::FUNCTION: BIO_int_ctrl ? 4_0_0 EXIST::FUNCTION: