From 93bcca389f1f69f53141b51acc91633ddca2bd94 Mon Sep 17 00:00:00 2001 From: Trond Norbye Date: Mon, 23 Mar 2009 09:38:04 +0100 Subject: [PATCH] Use ptr->root->result if the caller didn't provide a result structure to memcached_read_one_response --- libmemcached/memcached_response.c | 12 +++----- tests/function.c | 46 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/libmemcached/memcached_response.c b/libmemcached/memcached_response.c index e9f82b0a..cb5a8672 100644 --- a/libmemcached/memcached_response.c +++ b/libmemcached/memcached_response.c @@ -21,6 +21,9 @@ memcached_return memcached_read_one_response(memcached_server_st *ptr, { memcached_server_response_decrement(ptr); + if (result == NULL) + result = &ptr->root->result; + memcached_return rc; if (ptr->root->flags & MEM_BINARY_PROTOCOL) rc= binary_read_one_response(ptr, buffer, buffer_length, result); @@ -81,16 +84,9 @@ static memcached_return textual_read_one_response(memcached_server_st *ptr, case 'V': /* VALUE || VERSION */ if (buffer[1] == 'A') /* VALUE */ { - memcached_return rc; - /* We add back in one because we will need to search for END */ memcached_server_response_increment(ptr); - if (result) - rc= value_fetch(ptr, buffer, result); - else - rc= value_fetch(ptr, buffer, &ptr->root->result); - - return rc; + return value_fetch(ptr, buffer, result); } else if (buffer[1] == 'E') /* VERSION */ { diff --git a/tests/function.c b/tests/function.c index faa45494..20637c8f 100644 --- a/tests/function.c +++ b/tests/function.c @@ -961,6 +961,51 @@ static test_return get_test4(memcached_st *memc) return 0; } +/* + * This test verifies that memcached_read_one_response doesn't try to + * dereference a NIL-pointer if you issue a multi-get and don't read out all + * responses before you execute a storage command. + */ +static test_return get_test5(memcached_st *memc) +{ + /* + ** Request the same key twice, to ensure that we hash to the same server + ** (so that we have multiple response values queued up) ;-) + */ + char *keys[]= { "key", "key" }; + size_t lengths[]= { 3, 3 }; + uint32_t flags; + size_t rlen; + + memcached_return rc= memcached_set(memc, keys[0], lengths[0], + keys[0], lengths[0], 0, 0); + assert(rc == MEMCACHED_SUCCESS); + rc= memcached_mget(memc, keys, lengths, 2); + + memcached_result_st results_obj; + memcached_result_st *results; + results=memcached_result_create(memc, &results_obj); + assert(results); + results=memcached_fetch_result(memc, &results_obj, &rc); + assert(results); + memcached_result_free(&results_obj); + + /* Don't read out the second result, but issue a set instead.. */ + rc= memcached_set(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0); + assert(rc == MEMCACHED_SUCCESS); + + char *val= memcached_get_by_key(memc, keys[0], lengths[0], "yek", 3, + &rlen, &flags, &rc); + assert(val == NULL); + assert(rc == MEMCACHED_NOTFOUND); + val= memcached_get(memc, keys[0], lengths[0], &rlen, &flags, &rc); + assert(val != NULL); + assert(rc == MEMCACHED_SUCCESS); + free(val); + + return TEST_SUCCESS; +} + /* Do not copy the style of this code, I just access hosts to testthis function */ static test_return stats_servername_test(memcached_st *memc) { @@ -3579,6 +3624,7 @@ test_st tests[] ={ {"get2", 0, get_test2 }, {"get3", 0, get_test3 }, {"get4", 0, get_test4 }, + {"partial mget", 0, get_test5 }, {"stats_servername", 0, stats_servername_test }, {"increment", 0, increment_test }, {"decrement", 0, decrement_test }, -- 2.30.2