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 f818ebc0 Guard negative value_size in memcache PopStore (#3392)
f818ebc0 is described below
commit f818ebc05bd8f1b9a260faff2623aad615d511a4
Author: UB <[email protected]>
AuthorDate: Wed Jul 22 08:45:03 2026 +0530
Guard negative value_size in memcache PopStore (#3392)
* guard negative value_size in memcache PopStore
Signed-off-by: ubeddulla khan <[email protected]>
* memcache: drop only the declared message when value_size is negative
Move the value_size < 0 check ahead of the pop_front so a malformed
reply no longer pops sizeof(header) + extras_length + key_length past
the declared message boundary. Discard exactly
sizeof(header) + total_body_length instead, keeping the following
pipelined responses aligned.
Signed-off-by: ubeddulla khan <[email protected]>
---------
Signed-off-by: ubeddulla khan <[email protected]>
---
src/brpc/memcache.cpp | 7 +++++++
test/brpc_memcache_unittest.cpp | 31 +++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/src/brpc/memcache.cpp b/src/brpc/memcache.cpp
index c7d6f836..8d01e7bf 100644
--- a/src/brpc/memcache.cpp
+++ b/src/brpc/memcache.cpp
@@ -501,6 +501,13 @@ bool MemcacheResponse::PopStore(uint8_t command, uint64_t*
cas_value) {
LOG_IF(ERROR, header.key_length != 0) << "STORE response must not have
key";
int value_size = (int)header.total_body_length - (int)header.extras_length
- (int)header.key_length;
+ if (value_size < 0) {
+ // extras_length + key_length overrun the declared body. Drop exactly
the
+ // declared message so that following pipelined responses stay aligned.
+ _buf.pop_front(sizeof(header) + header.total_body_length);
+ butil::string_printf(&_err, "value_size=%d is negative", value_size);
+ return false;
+ }
if (header.status != (uint16_t)STATUS_SUCCESS) {
_buf.pop_front(sizeof(header) + header.extras_length +
header.key_length);
_err.clear();
diff --git a/test/brpc_memcache_unittest.cpp b/test/brpc_memcache_unittest.cpp
index b1da9584..3b7e676b 100644
--- a/test/brpc_memcache_unittest.cpp
+++ b/test/brpc_memcache_unittest.cpp
@@ -62,6 +62,37 @@ TEST(MemcacheParserTest,
RejectOversizedResponseBeforeBufferingBody) {
}
+TEST(MemcacheParserTest, PopStoreRejectsNegativeValueSize) {
+ // A STORE error response whose extras_length + key_length exceeds
+ // total_body_length makes value_size negative. PopStore used to pass that
+ // straight to cutn(&_err, value_size); the negative value became a huge
+ // size_t and drained the rest of the (pipelined) buffer into the error
+ // string. The sibling parsers PopGet/PopCounter/PopVersion already guard
+ // value_size < 0; PopStore must do the same.
+ brpc::policy::MemcacheResponseHeader header = {};
+ header.magic = brpc::policy::MC_MAGIC_RESPONSE;
+ header.command = brpc::policy::MC_BINARY_SET;
+ header.status = 1; // non-zero: error response
+ header.extras_length = 1; // claims extras...
+ header.key_length = 0;
+ header.total_body_length = 0; // ...but body carries none ->
value_size = -1
+
+ brpc::MemcacheResponse response;
+ response.raw_buffer().append(&header, sizeof(header));
+ // Bytes of a following pipelined response that must not leak into _err.
+ const char next_response[] = "SECRET-NEXT-RESPONSE";
+ response.raw_buffer().append(next_response, sizeof(next_response) - 1);
+
+ uint64_t cas_value = 0;
+ ASSERT_FALSE(response.PopSet(&cas_value));
+ ASSERT_EQ("value_size=-1 is negative", response.LastError());
+ ASSERT_EQ(std::string::npos, response.LastError().find("RESPONSE"));
+ // Only the declared message (header + total_body_length) is dropped, so
the
+ // following pipelined response is still intact at the head of the buffer.
+ ASSERT_EQ(sizeof(next_response) - 1, response.raw_buffer().size());
+ ASSERT_EQ(next_response, response.raw_buffer().to_string());
+}
+
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]