Skip to content

Commit

Permalink
add support for BIO_read/write_ex
Browse files Browse the repository at this point in the history
  • Loading branch information
samuel40791765 committed May 1, 2024
1 parent 82d888b commit 6406764
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 2 deletions.
42 changes: 42 additions & 0 deletions crypto/bio/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,26 @@ int BIO_read(BIO *bio, void *buf, int len) {
return ret;
}

int BIO_read_ex(BIO *bio, void *data, size_t data_len, size_t *read_bytes) {
if (bio == NULL || read_bytes == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
return 0;
}

int read_len = (int)data_len;
if (data_len > INT_MAX) {
read_len = INT_MAX;
}

int ret = BIO_read(bio, data, read_len);
*read_bytes = ret;
if (ret > 0) {
return 1;
} else {
return 0;
}
}

int BIO_gets(BIO *bio, char *buf, int len) {
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
Expand Down Expand Up @@ -236,6 +256,28 @@ int BIO_write(BIO *bio, const void *in, int inl) {
return ret;
}

int BIO_write_ex(BIO *bio, const void *data, size_t data_len, size_t *written_bytes) {
if (bio == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
return 0;
}

int write_len = (int)data_len;
if (data_len > INT_MAX) {
write_len = INT_MAX;
}

int ret = BIO_write(bio, data, write_len);
if (written_bytes != NULL) {
*written_bytes = ret;
}
if (ret > 0) {
return 1;
} else {
return 0;
}
}

int BIO_write_all(BIO *bio, const void *data, size_t len) {
const uint8_t *data_u8 = data;
while (len > 0) {
Expand Down
35 changes: 34 additions & 1 deletion crypto/bio/bio_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class OwnedSocket {
};

struct SockaddrStorage {
SockaddrStorage() : storage() , len(sizeof(storage)) {}
SockaddrStorage() : storage(), len(sizeof(storage)) {}

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

Expand Down Expand Up @@ -1063,3 +1063,36 @@ TEST(BIOTest, InvokeConnectCallback) {
} // namespace

INSTANTIATE_TEST_SUITE_P(All, BIOPairTest, testing::Values(false, true));

TEST(BIOTest, ReadWriteEx) {
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio);

size_t written = 0;
ASSERT_TRUE(BIO_write_ex(bio.get(), "abcdef", 6, &written));
EXPECT_EQ(written, (size_t)6);

char buf[32];
size_t read = 0;
ASSERT_TRUE(BIO_read_ex(bio.get(), buf, sizeof(buf), &read));
EXPECT_GT(read, (size_t)0);
EXPECT_EQ(Bytes(buf, read), Bytes("abcdef"));

// Test NULL |written_bytes| behavior works.
read = 0;
ASSERT_TRUE(BIO_write_ex(bio.get(), "ghilmnop", 8, nullptr));
ASSERT_TRUE(BIO_read_ex(bio.get(), buf, sizeof(buf), &read));
EXPECT_GT(read, (size_t)0);
EXPECT_EQ(Bytes(buf, read), Bytes("ghilmnop"));

// Test NULL |read_bytes| behavior fails.
ASSERT_TRUE(BIO_write_ex(bio.get(), "ghilmnop", 8, nullptr));
ASSERT_FALSE(BIO_read_ex(bio.get(), buf, sizeof(buf), nullptr));

// Test that |BIO_write/read_ex| align with their non-ex counterparts, when
// encountering NULL data.
EXPECT_FALSE(BIO_write(bio.get(), nullptr, 0));
EXPECT_FALSE(BIO_write_ex(bio.get(), nullptr, 0, &written));
EXPECT_FALSE(BIO_read(bio.get(), nullptr, 0));
EXPECT_FALSE(BIO_read_ex(bio.get(), nullptr, 0, &read));
}
13 changes: 12 additions & 1 deletion include/openssl/bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ OPENSSL_EXPORT int BIO_up_ref(BIO *bio);
// of bytes read, zero on EOF, or a negative number on error.
OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len);

// BIO_read_ex calls |BIO_read| and stores the number of bytes read in
// |read_bytes|. It returns one on success and zero otherwise.
OPENSSL_EXPORT int BIO_read_ex(BIO *bio, void *data, size_t data_len,
size_t *read_bytes);

// BIO_gets reads a line from |bio| and writes at most |size| bytes into |buf|.
// It returns the number of bytes read or a negative number on error. This
// function's output always includes a trailing NUL byte, so it will read at
Expand All @@ -127,6 +132,12 @@ OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size);
// number of bytes written, or a negative number on error.
OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len);

// BIO_write_ex calls |BIO_write| and stores the number of bytes written in
// |written_bytes|, unless |written_bytes| is NULL. It returns one on success
// and zero otherwise.
OPENSSL_EXPORT int BIO_write_ex(BIO *bio, const void *data, size_t data_len,
size_t *written_bytes);

// BIO_write_all writes |len| bytes from |data| to |bio|, looping as necessary.
// It returns one if all bytes were successfully written and zero on error.
OPENSSL_EXPORT int BIO_write_all(BIO *bio, const void *data, size_t len);
Expand Down Expand Up @@ -880,7 +891,7 @@ OPENSSL_EXPORT int (*BIO_meth_get_puts(const BIO_METHOD *method)) (BIO *, const
// does not support secure heaps.
OPENSSL_EXPORT OPENSSL_DEPRECATED const BIO_METHOD *BIO_s_secmem(void);


// General No-op Functions [Deprecated].

// BIO_set_write_buffer_size returns zero.
Expand Down

0 comments on commit 6406764

Please sign in to comment.