Skip to content

Commit

Permalink
INTERNAL: Fix an overwrite issue for the big key
Browse files Browse the repository at this point in the history
  • Loading branch information
ing-eoking committed Jan 16, 2025
1 parent 3499c5e commit 6ae86ae
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 28 deletions.
84 changes: 57 additions & 27 deletions libmemcached/response.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 - 1]= 0;

result->key_length= key_length;
}

if (end_ptr == string_ptr)
Expand Down Expand Up @@ -508,7 +508,6 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
/* FALLTHROUGH */
case PROTOCOL_BINARY_CMD_GETK:
{
uint16_t keylen= header.response.keylen;
memcached_result_reset(result);
result->item_cas= header.response.cas;

Expand All @@ -521,29 +520,60 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
result->item_flags= ntohl(result->item_flags);
bodylen -= header.response.extlen;

uint16_t keylen= header.response.keylen;
uint16_t prefix_size= memcached_array_size(ptr->root->_namespace);

if (prefix_size >= keylen) {
return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}

/* Discard the prefix */
uint16_t rtotal= 0, rsize;
while (rtotal < prefix_size) {
char buf[MEMCACHED_MAX_KEY];
rsize= (prefix_size - rtotal) < MEMCACHED_MAX_KEY
? (prefix_size - rtotal) : MEMCACHED_MAX_KEY;
if (memcached_failed(memcached_safe_read(ptr, buf, rsize)))
{
return MEMCACHED_UNKNOWN_READ_FAILURE;
}
rtotal += rsize;
}

bodylen -= prefix_size;
keylen -= prefix_size;
result->key_length= keylen;
if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, keylen)))

if (keylen < MEMCACHED_MAX_KEY) {
rsize= keylen;
} else {
rsize= MEMCACHED_MAX_KEY - 1;
memcached_set_error(*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
}

if (memcached_failed(rc= memcached_safe_read(ptr, result->item_key, rsize)))
{
WATCHPOINT_ERROR(rc);
return MEMCACHED_UNKNOWN_READ_FAILURE;
}

// Only bother with doing this if key_length > 0
if (result->key_length)
{
if (memcached_array_size(ptr->root->_namespace) and memcached_array_size(ptr->root->_namespace) >= result->key_length)
{
return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
}
result->item_key[rsize]= 0;
rtotal= rsize;

if (memcached_array_size(ptr->root->_namespace))
/* Discard the part of key */
while (rtotal < keylen) {
char buf[MEMCACHED_MAX_KEY];
rsize= (keylen - rtotal) < MEMCACHED_MAX_KEY
? (keylen - rtotal) : MEMCACHED_MAX_KEY;
if (memcached_failed(memcached_safe_read(ptr, buf, rsize)))
{
result->key_length-= memcached_array_size(ptr->root->_namespace);
memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->_namespace), result->key_length);
return MEMCACHED_UNKNOWN_READ_FAILURE;
}
rtotal += rsize;
}

bodylen -= keylen;

if (memcached_failed(memcached_string_check(&result->value, bodylen)))
{
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
Expand Down
2 changes: 1 addition & 1 deletion libmemcached/result.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
*
* Libmemcached library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
Expand Down

0 comments on commit 6ae86ae

Please sign in to comment.