This is an automated email from the ASF dual-hosted git repository.
chenBright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push:
new 7c1b5225 Fix use-after-free of the new block in SingleIOBuf::assign
(#3397)
7c1b5225 is described below
commit 7c1b52253911f4d7359ce2a3b34870d2bcccf714
Author: UB <[email protected]>
AuthorDate: Sun Jul 26 15:26:42 2026 +0530
Fix use-after-free of the new block in SingleIOBuf::assign (#3397)
Signed-off-by: ubeddulla khan <[email protected]>
---
src/butil/single_iobuf.cpp | 8 +++++++-
test/iobuf_unittest.cpp | 28 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/src/butil/single_iobuf.cpp b/src/butil/single_iobuf.cpp
index 942c4ba9..7fc9bbcd 100644
--- a/src/butil/single_iobuf.cpp
+++ b/src/butil/single_iobuf.cpp
@@ -226,7 +226,13 @@ bool SingleIOBuf::assign(const IOBuf& buf, uint32_t
msg_size) {
if (!b) {
return false;
}
- reset();
+ // Only drop the reference to the previously assigned data here.
+ // reset() would also release _cur_block, which alloc_block_by_size()
+ // has just set to `b', leaving `b' dangling.
+ if (_cur_ref.block != NULL) {
+ _cur_ref.block->dec_ref();
+ _cur_ref.block = NULL;
+ }
char* out = b->data + b->size;
const size_t nref = buf.backing_block_num();
uint32_t last_len = msg_size;
diff --git a/test/iobuf_unittest.cpp b/test/iobuf_unittest.cpp
index 18d312eb..ddd5b599 100644
--- a/test/iobuf_unittest.cpp
+++ b/test/iobuf_unittest.cpp
@@ -1952,6 +1952,34 @@ TEST_F(IOBufTest, single_iobuf) {
ASSERT_TRUE(p != nullptr);
}
+TEST_F(IOBufTest, single_iobuf_assign_large_multi_block) {
+ // The message spans more than one BlockRef of the source IOBuf and does
+ // not fit in a default-sized block, so assign() has to concatenate it
+ // into a dedicated block.
+ const uint32_t n1 = 5000;
+ const uint32_t n2 = 6000;
+ char* d1 = (char*)malloc(n1);
+ memset(d1, 'a', n1);
+ char* d2 = (char*)malloc(n2);
+ memset(d2, 'b', n2);
+ butil::IOBuf buf;
+ buf.append_user_data(d1, n1, NULL);
+ buf.append_user_data(d2, n2, NULL);
+ ASSERT_EQ(2, buf.backing_block_num());
+
+ butil::SingleIOBuf sbuf;
+ ASSERT_TRUE(sbuf.assign(buf, n1 + n2));
+ ASSERT_EQ(n1 + n2, sbuf.get_length());
+ ASSERT_EQ(std::string(n1, 'a') + std::string(n2, 'b'),
+ std::string((const char*)sbuf.get_begin(), n1 + n2));
+
+ // Assigning again on top of an already assigned SingleIOBuf.
+ ASSERT_TRUE(sbuf.assign(buf, n1 + n2));
+ ASSERT_EQ(n1 + n2, sbuf.get_length());
+ ASSERT_EQ(std::string(n1, 'a') + std::string(n2, 'b'),
+ std::string((const char*)sbuf.get_begin(), n1 + n2));
+}
+
TEST_F(IOBufTest, as_input_stream_basic) {
butil::IOBuf buf;
buf.append("hello world");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]