Skip to content

Commit 541e4ea

Browse files
add support for BIO_read/write_ex
1 parent e8514ec commit 541e4ea

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed

crypto/bio/bio.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,26 @@ int BIO_read(BIO *bio, void *buf, int len) {
186186
return ret;
187187
}
188188

189+
int BIO_read_ex(BIO *bio, void *data, size_t data_len, size_t *read_bytes) {
190+
if (bio == NULL || read_bytes == NULL) {
191+
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
192+
return 0;
193+
}
194+
195+
int read_len = (int)data_len;
196+
if (data_len > INT_MAX) {
197+
read_len = INT_MAX;
198+
}
199+
200+
int ret = BIO_read(bio, data, read_len);
201+
*read_bytes = ret;
202+
if (ret > 0) {
203+
return 1;
204+
} else {
205+
return 0;
206+
}
207+
}
208+
189209
int BIO_gets(BIO *bio, char *buf, int len) {
190210
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
191211
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
@@ -236,6 +256,28 @@ int BIO_write(BIO *bio, const void *in, int inl) {
236256
return ret;
237257
}
238258

259+
int BIO_write_ex(BIO *bio, const void *data, size_t data_len, size_t *written_bytes) {
260+
if (bio == NULL) {
261+
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
262+
return 0;
263+
}
264+
265+
int write_len = (int)data_len;
266+
if (data_len > INT_MAX) {
267+
write_len = INT_MAX;
268+
}
269+
270+
int ret = BIO_write(bio, data, write_len);
271+
if (written_bytes != NULL) {
272+
*written_bytes = ret;
273+
}
274+
if (ret > 0) {
275+
return 1;
276+
} else {
277+
return 0;
278+
}
279+
}
280+
239281
int BIO_write_all(BIO *bio, const void *data, size_t len) {
240282
const uint8_t *data_u8 = data;
241283
while (len > 0) {

crypto/bio/bio_test.cc

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class OwnedSocket {
8989
};
9090

9191
struct SockaddrStorage {
92-
SockaddrStorage() : storage() , len(sizeof(storage)) {}
92+
SockaddrStorage() : storage(), len(sizeof(storage)) {}
9393

9494
int family() const { return storage.ss_family; }
9595

@@ -1063,3 +1063,36 @@ TEST(BIOTest, InvokeConnectCallback) {
10631063
} // namespace
10641064

10651065
INSTANTIATE_TEST_SUITE_P(All, BIOPairTest, testing::Values(false, true));
1066+
1067+
TEST(BIOTest, ReadWriteEx) {
1068+
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
1069+
ASSERT_TRUE(bio);
1070+
1071+
size_t written = 0;
1072+
ASSERT_TRUE(BIO_write_ex(bio.get(), "abcdef", 6, &written));
1073+
EXPECT_EQ(written, (size_t)6);
1074+
1075+
char buf[32];
1076+
size_t read = 0;
1077+
ASSERT_TRUE(BIO_read_ex(bio.get(), buf, sizeof(buf), &read));
1078+
EXPECT_GT(read, (size_t)0);
1079+
EXPECT_EQ(Bytes(buf, read), Bytes("abcdef"));
1080+
1081+
// Test NULL |written_bytes| behavior works.
1082+
read = 0;
1083+
ASSERT_TRUE(BIO_write_ex(bio.get(), "ghilmnop", 8, nullptr));
1084+
ASSERT_TRUE(BIO_read_ex(bio.get(), buf, sizeof(buf), &read));
1085+
EXPECT_GT(read, (size_t)0);
1086+
EXPECT_EQ(Bytes(buf, read), Bytes("ghilmnop"));
1087+
1088+
// Test NULL |read_bytes| behavior fails.
1089+
ASSERT_TRUE(BIO_write_ex(bio.get(), "ghilmnop", 8, nullptr));
1090+
ASSERT_FALSE(BIO_read_ex(bio.get(), buf, sizeof(buf), nullptr));
1091+
1092+
// Test that |BIO_write/read_ex| align with their non-ex counterparts, when
1093+
// encountering NULL data.
1094+
EXPECT_FALSE(BIO_write(bio.get(), nullptr, 0));
1095+
EXPECT_FALSE(BIO_write_ex(bio.get(), nullptr, 0, &written));
1096+
EXPECT_FALSE(BIO_read(bio.get(), nullptr, 0));
1097+
EXPECT_FALSE(BIO_read_ex(bio.get(), nullptr, 0, &read));
1098+
}

include/openssl/bio.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ OPENSSL_EXPORT int BIO_up_ref(BIO *bio);
110110
// of bytes read, zero on EOF, or a negative number on error.
111111
OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len);
112112

113+
// |BIO_read_ex| calls |BIO_read| and stores the number of bytes read in
114+
// |read_bytes|. It returns one on success and zero otherwise.
115+
OPENSSL_EXPORT int BIO_read_ex(BIO *bio, void *data, size_t data_len,
116+
size_t *read_bytes);
117+
113118
// BIO_gets reads a line from |bio| and writes at most |size| bytes into |buf|.
114119
// It returns the number of bytes read or a negative number on error. This
115120
// function's output always includes a trailing NUL byte, so it will read at
@@ -127,6 +132,12 @@ OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size);
127132
// number of bytes written, or a negative number on error.
128133
OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len);
129134

135+
// |BIO_write_ex| calls |BIO_write| and stores the number of bytes written in
136+
// |written_bytes|, unless |written_bytes| is NULL. It returns one on success
137+
// and zero otherwise.
138+
OPENSSL_EXPORT int BIO_write_ex(BIO *bio, const void *data, size_t data_len,
139+
size_t *written_bytes);
140+
130141
// BIO_write_all writes |len| bytes from |data| to |bio|, looping as necessary.
131142
// It returns one if all bytes were successfully written and zero on error.
132143
OPENSSL_EXPORT int BIO_write_all(BIO *bio, const void *data, size_t len);
@@ -880,7 +891,7 @@ OPENSSL_EXPORT int (*BIO_meth_get_puts(const BIO_METHOD *method)) (BIO *, const
880891
// does not support secure heaps.
881892
OPENSSL_EXPORT OPENSSL_DEPRECATED const BIO_METHOD *BIO_s_secmem(void);
882893

883-
894+
884895
// General No-op Functions [Deprecated].
885896

886897
// BIO_set_write_buffer_size returns zero.

0 commit comments

Comments
 (0)