diff --git a/test/unit/memcached_test.rb b/test/unit/memcached_test.rb index ff3e366f..eea2f19b 100644 --- a/test/unit/memcached_test.rb +++ b/test/unit/memcached_test.rb @@ -998,6 +998,34 @@ def test_key_too_long end end + def test_storage_command_with_oversized_prefix_and_key + cache = Memcached.new @servers, @options.merge(:prefix_key => "p" * 127) + key = "k" * 250 + + assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do + cache.set key, @value + end + assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do + cache.prepend key, "value" + end + end + + def test_storage_command_with_prefix_and_key_filling_buffer + cache = Memcached.new @servers, @options.merge(:prefix_key => "p" * 127) + + assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do + cache.set "k" * 218, @value + end + end + + def test_noreply_delete_with_oversized_prefix_and_key + cache = Memcached.new @servers, @noblock_options.merge(:prefix_key => "p" * 127) + + assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do + cache.delete "k" * 250 + end + end + def test_verify_key_disabled cache = Memcached.new @servers, :verify_key => false key = "i have a space" diff --git a/vendor/libmemcached-0.32/libmemcached/memcached_storage.c b/vendor/libmemcached-0.32/libmemcached/memcached_storage.c index bf853f09..510ce74a 100644 --- a/vendor/libmemcached-0.32/libmemcached/memcached_storage.c +++ b/vendor/libmemcached-0.32/libmemcached/memcached_storage.c @@ -107,6 +107,9 @@ static inline memcached_return memcached_send(memcached_st *ptr, char *buffer_ptr= buffer; const char *command= storage_op_string(verb); + if (strlen(command) + strlen(ptr->prefix_key) + key_length + 1 >= MEMCACHED_DEFAULT_COMMAND_SIZE) + return MEMCACHED_BAD_KEY_PROVIDED; + /* Copy in the command, no space needed, we handle that in the command function*/ memcpy(buffer_ptr, command, strlen(command)); @@ -123,9 +126,9 @@ static inline memcached_return memcached_send(memcached_st *ptr, if (verb == DELETE_OP) { if (ptr->flags & MEM_NOREPLY) - write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, "noreply"); + write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE - write_length, "noreply"); } else { - write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, + write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE - write_length, "%u %llu %zu%s\r\n", flags, (unsigned long long)expiration, value_length,