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 dd43e724 Fix use-after-free of response header in ParseMemcacheMessage 
(#3572)
dd43e724 is described below

commit dd43e724296f54773bc4e108863d206f04397f61
Author: UB <[email protected]>
AuthorDate: Wed Sep 30 09:12:19 2026 +0530

    Fix use-after-free of response header in ParseMemcacheMessage (#3572)
---
 src/brpc/policy/memcache_binary_protocol.cpp |  7 ++++--
 test/brpc_memcache_unittest.cpp              | 37 ++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/brpc/policy/memcache_binary_protocol.cpp 
b/src/brpc/policy/memcache_binary_protocol.cpp
index dcb435b0..e30bade1 100644
--- a/src/brpc/policy/memcache_binary_protocol.cpp
+++ b/src/brpc/policy/memcache_binary_protocol.cpp
@@ -132,8 +132,11 @@ ParseResult ParseMemcacheMessage(butil::IOBuf* source,
         msg->meta.append(&local_header, sizeof(local_header));
         source->pop_front(sizeof(*header));
         source->cutn(&msg->meta, total_body_length);
-        if (header->command == MC_BINARY_SASL_AUTH) {
-            if (header->status != 0) {
+        // `header' points into source's front block; pop_front above may have
+        // released that block, so read the already byte-swapped local_header
+        // here instead of dereferencing the now-dangling `header'.
+        if (local_header.command == MC_BINARY_SASL_AUTH) {
+            if (local_header.status != 0) {
                 LOG(ERROR) << "Failed to authenticate the couchbase bucket.";
                 return MakeParseError(PARSE_ERROR_NO_RESOURCE, 
                                       "Fail to authenticate with the couchbase 
bucket");
diff --git a/test/brpc_memcache_unittest.cpp b/test/brpc_memcache_unittest.cpp
index 76c4ca4b..a43a1e01 100644
--- a/test/brpc_memcache_unittest.cpp
+++ b/test/brpc_memcache_unittest.cpp
@@ -93,6 +93,43 @@ TEST(MemcacheParserTest, PopStoreRejectsNegativeValueSize) {
     ASSERT_EQ(next_response, response.raw_buffer().to_string());
 }
 
+TEST(MemcacheParserTest, SaslAuthDoesNotReadHeaderAfterPop) {
+    // ParseMemcacheMessage fetched the 24-byte response header (a pointer into
+    // source's front block), popped those bytes with source->pop_front(), and
+    // then still dereferenced header->command / header->status on the 
SASL_AUTH
+    // path. Once the header sat alone in the front block, pop_front released 
it
+    // and the two reads became a use-after-free. Put the header in a heap 
block
+    // that is freed the moment its bytes are popped so the stale read is a
+    // definite UAF (ASAN heap-use-after-free on the unpatched tree); the fix
+    // reads the already byte-swapped local_header instead.
+    brpc::SocketId id;
+    brpc::SocketOptions options;
+    ASSERT_EQ(0, brpc::Socket::Create(options, &id));
+    brpc::SocketUniquePtr socket;
+    ASSERT_EQ(0, brpc::Socket::Address(id, &socket));
+
+    // PopPipelinedInfo() must succeed to reach the SASL_AUTH branch.
+    brpc::PipelinedInfo pi;
+    pi.count = 1;
+    socket->PushPipelinedInfo(pi);
+
+    brpc::policy::MemcacheResponseHeader* header =
+        (brpc::policy::MemcacheResponseHeader*)malloc(sizeof(*header));
+    ASSERT_TRUE(header != NULL);
+    memset(header, 0, sizeof(*header));
+    header->magic = brpc::policy::MC_MAGIC_RESPONSE;
+    header->command = brpc::policy::MC_BINARY_SASL_AUTH;
+    header->status = butil::HostToNet16(1);  // non-zero: auth failure
+    header->total_body_length = 0;           // no body: header is the whole 
front block
+
+    butil::IOBuf buf;
+    buf.append_user_data(header, sizeof(*header), [](void* p) { free(p); });
+
+    brpc::ParseResult r = brpc::policy::ParseMemcacheMessage(
+        &buf, socket.get(), false, nullptr);
+    ASSERT_EQ(brpc::PARSE_ERROR_NO_RESOURCE, r.error());
+}
+
 static pthread_once_t download_memcached_once = PTHREAD_ONCE_INIT;
 static pid_t g_mc_pid = -1;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to