Skip to content

Commit 9c9b425

Browse files
committed
Make BIO_get_new_index thread-safe with atomics, add test coverage
1 parent 3fe2469 commit 9c9b425

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

src/bio.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2126,16 +2126,34 @@ long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on)
21262126
#endif
21272127

21282128
/* Return a new BIO type index, or WOLFSSL_FATAL_ERROR when exhausted.
2129-
* Not thread-safe. */
2129+
* Thread-safe when atomic operations are available (like OpenSSL's
2130+
* BIO_get_new_index()); otherwise falls back to a plain counter. */
21302131
int wolfSSL_BIO_get_new_index(void)
21312132
{
2133+
#if !defined(SINGLE_THREADED) && defined(WOLFSSL_ATOMIC_OPS) && \
2134+
defined(WOLFSSL_ATOMIC_INITIALIZER)
2135+
static wolfSSL_Atomic_Int wolfssl_bio_type_index =
2136+
WOLFSSL_ATOMIC_INITIALIZER(WOLFSSL_BIO_TYPE_START);
2137+
int idx = (int)wolfSSL_Atomic_Int_AddFetch(&wolfssl_bio_type_index, 1);
2138+
2139+
if (idx > 0xff) {
2140+
/* Back out the increment so repeated calls once exhausted cannot
2141+
* eventually wrap the counter. Concurrent failed calls each undo
2142+
* only their own increment, so no valid index is handed out twice. */
2143+
(void)wolfSSL_Atomic_Int_SubFetch(&wolfssl_bio_type_index, 1);
2144+
return WOLFSSL_FATAL_ERROR;
2145+
}
2146+
2147+
return idx;
2148+
#else
21322149
static int wolfssl_bio_type_index = WOLFSSL_BIO_TYPE_START;
21332150

21342151
if (wolfssl_bio_type_index >= 0xff) {
21352152
return WOLFSSL_FATAL_ERROR;
21362153
}
21372154

21382155
return ++wolfssl_bio_type_index;
2156+
#endif
21392157
}
21402158

21412159
/* creates a new custom WOLFSSL_BIO_METHOD */

tests/api/test_ossl_bio.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,5 +1899,40 @@ int test_wolfSSL_BIO_get_init(void)
18991899
return EXPECT_RESULT();
19001900
}
19011901

1902+
int test_wolfSSL_BIO_get_new_index(void)
1903+
{
1904+
EXPECT_DECLS;
1905+
#if defined(OPENSSL_EXTRA)
1906+
BIO_METHOD* method = NULL;
1907+
BIO* bio = NULL;
1908+
int idx = 0;
1909+
int prev;
1910+
1911+
/* First call hands out BIO_TYPE_START + 1, later calls increment by
1912+
* one. The index counter is process-global, so this test drains it
1913+
* completely; it must stay the only consumer in the test suite. */
1914+
ExpectIntEQ(prev = BIO_get_new_index(), BIO_TYPE_START + 1);
1915+
1916+
/* A returned index is usable as a custom method type. */
1917+
ExpectNotNull(method = BIO_meth_new(prev, "new_index_test"));
1918+
ExpectNotNull(bio = BIO_new(method));
1919+
ExpectIntEQ(BIO_method_type(bio), prev);
1920+
BIO_free(bio);
1921+
BIO_meth_free(method);
1922+
1923+
/* Monotonic by one up to the last valid index 0xff, then
1924+
* WOLFSSL_FATAL_ERROR once exhausted. */
1925+
while (EXPECT_SUCCESS() && (idx = BIO_get_new_index()) > 0) {
1926+
ExpectIntEQ(idx, prev + 1);
1927+
prev = idx;
1928+
}
1929+
ExpectIntEQ(prev, 0xff);
1930+
ExpectIntEQ(idx, WOLFSSL_FATAL_ERROR);
1931+
/* Exhaustion is sticky. */
1932+
ExpectIntEQ(BIO_get_new_index(), WOLFSSL_FATAL_ERROR);
1933+
#endif
1934+
return EXPECT_RESULT();
1935+
}
1936+
19021937
#endif /* !NO_BIO */
19031938

tests/api/test_ossl_bio.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int test_wolfSSL_BIO_set_conn_hostname(void);
4949
int test_wolfSSL_BIO_ctrl_pending_chain(void);
5050
int test_wolfSSL_BIO_meth_type_large(void);
5151
int test_wolfSSL_BIO_get_init(void);
52+
int test_wolfSSL_BIO_get_new_index(void);
5253

5354
#define TEST_OSSL_BIO_DECLS \
5455
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_gets), \
@@ -70,7 +71,8 @@ int test_wolfSSL_BIO_get_init(void);
7071
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_set_conn_hostname), \
7172
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_ctrl_pending_chain), \
7273
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_meth_type_large), \
73-
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_init)
74+
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_init), \
75+
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_new_index)
7476

7577
#define TEST_OSSL_BIO_TLS_DECLS \
7678
TEST_DECL_GROUP("ossl_bio_tls", test_wolfSSL_BIO_connect), \

0 commit comments

Comments
 (0)