From e7b429e2d333c7a2f2e22e25acf7c2742cf98e2e Mon Sep 17 00:00:00 2001 From: yeoncheol-kim Date: Wed, 15 Jan 2025 16:57:31 +0900 Subject: [PATCH] INTERNAL: Fix an overwrite issue for the big key --- libmemcached/response.cc | 53 +++++++++++++++++++++++++++------------- libmemcached/result.h | 4 +-- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/libmemcached/response.cc b/libmemcached/response.cc index 59485c42..65271e1e 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -76,27 +76,27 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st string_ptr= buffer; string_ptr+= 6; /* "VALUE " */ - /* We load the key */ { - char *key; - size_t prefix_length; + char *key= result->item_key; + size_t key_length= 0; - key= result->item_key; - result->key_length= 0; + string_ptr += memcached_array_size(ptr->root->_namespace); /* prefix length */ - for (prefix_length= memcached_array_size(ptr->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++) - { - if (prefix_length == 0) - { - *key= *string_ptr; - key++; - result->key_length++; + while (!iscntrl(*string_ptr) && !isspace(*string_ptr)) { + if (key_length < MEMCACHED_MAX_KEY) { + key[key_length]= *string_ptr; + } else if (key_length == MEMCACHED_MAX_KEY) { + memcached_set_error(*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT); } - else - prefix_length--; + key_length++; + string_ptr++; } - result->item_key[result->key_length]= 0; + + if (key_length < MEMCACHED_MAX_KEY) key[key_length]= 0; + else key[MEMCACHED_MAX_KEY]= 0; + + result->key_length= key_length; } if (end_ptr == string_ptr) @@ -522,12 +522,31 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan bodylen -= header.response.extlen; result->key_length= keylen; - if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, keylen))) + + uint16_t rsize; + if (keylen > MEMCACHED_MAX_KEY) { + rsize= MEMCACHED_MAX_KEY; + memcached_set_error(*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT); + } else { + rsize= keylen; + } + + if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, rsize))) { WATCHPOINT_ERROR(rc); return MEMCACHED_UNKNOWN_READ_FAILURE; } + /* Discard the part of key */ + while ((keylen -= rsize) > 0) { + char buf[MEMCACHED_MAX_KEY]; + rsize= keylen <= MEMCACHED_MAX_KEY ? keylen : MEMCACHED_MAX_KEY; + if (memcached_failed(memcached_safe_read(ptr, buf, rsize))) + { + return MEMCACHED_UNKNOWN_READ_FAILURE; + } + } + // Only bother with doing this if key_length > 0 if (result->key_length) { @@ -543,7 +562,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan } } - bodylen -= keylen; + bodylen -= result->key_length; if (memcached_failed(memcached_string_check(&result->value, bodylen))) { return MEMCACHED_MEMORY_ALLOCATION_FAILURE; diff --git a/libmemcached/result.h b/libmemcached/result.h index fe6e2803..befe6bd3 100644 --- a/libmemcached/result.h +++ b/libmemcached/result.h @@ -1,5 +1,5 @@ /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * + * * Libmemcached library * * Copyright (C) 2011 Data Differential, http://datadifferential.com/ @@ -46,7 +46,7 @@ struct memcached_result_st { memcached_st *root; memcached_string_st value; uint64_t count; - char item_key[MEMCACHED_MAX_KEY]; + char item_key[MEMCACHED_MAX_KEY+1]; // MAX_KEY + '\0' struct { bool is_allocated:1; bool is_initialized:1;