2016-09-22 13:35:13 |
Denis |
bug |
|
|
added bug |
2016-09-22 13:35:13 |
Denis |
attachment added |
|
Patch that fixes bug in memcached_servers_reset https://bugs.launchpad.net/bugs/1626565/+attachment/4746251/+files/libmemcached-ketama-servers_reset.patch |
|
2016-09-22 14:29:28 |
Denis |
description |
When used with MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED at memcached_servers_reset ketama.continuum is freed, NULL-ed, but ketama.continuum_count is not zeroed. It leads to segfault when memcached_server_add() is accessing ketama.continuum_count[0].
The following code is a proof:
#include <libmemcached/memcached.h>
#include <stdio.h>
int main() {
const char *config_string= "--SERVER=localhost";
const char *key= "foo";
const char *value= "bar";
memcached_return_t err;
size_t retlen;
char *retvalue;
memcached_st *memc= memcached(config_string, strlen(config_string));
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get failed, %s\n", memcached_strerror(memc, err));
}
memcached_servers_reset(memc);
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get 2 failed, %s\n", memcached_strerror(memc, err));
}
memcached_free(memc);
}
Actual behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
Segmentation fault (core dumped)
Expected behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
bar
gdb output:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
316 ptr->ketama.continuum[continuum_index].index= host_index;
(gdb) bt
#0 0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
#1 0x00007ffff7bbf8f6 in memcached_server_add_with_weight (shell=0x614c20, hostname=<optimized out>, port=<optimized out>, weight=0) at libmemcached/hosts.cc:585
#2 0x0000000000400c56 in main ()
(gdb) list
311 if (memcached_is_weighted_ketama(ptr))
312 {
313 for (uint32_t x = 0; x < pointer_per_hash; x++)
314 {
315 uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
316 ptr->ketama.continuum[continuum_index].index= host_index;
317 ptr->ketama.continuum[continuum_index++].value= value;
318 }
319 }
320 else
(gdb) print ptr->ketama.continuum
$1 = (memcached_continuum_item_st *) 0x0
(gdb) print ptr->ketama.continuum_count
$2 = 11
(gdb) quit
Attached is a patch to fix that. |
When used with MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED at memcached_servers_reset ketama.continuum is freed, NULL-ed, but ketama.continuum_count is not zeroed. It leads to segfault when memcached_server_add() is accessing ketama.continuum[0].
The following code is a proof:
#include <libmemcached/memcached.h>
#include <stdio.h>
int main() {
const char *config_string= "--SERVER=localhost";
const char *key= "foo";
const char *value= "bar";
memcached_return_t err;
size_t retlen;
char *retvalue;
memcached_st *memc= memcached(config_string, strlen(config_string));
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get failed, %s\n", memcached_strerror(memc, err));
}
memcached_servers_reset(memc);
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get 2 failed, %s\n", memcached_strerror(memc, err));
}
memcached_free(memc);
}
Actual behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
Segmentation fault (core dumped)
Expected behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
bar
gdb output:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
316 ptr->ketama.continuum[continuum_index].index= host_index;
(gdb) bt
#0 0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
#1 0x00007ffff7bbf8f6 in memcached_server_add_with_weight (shell=0x614c20, hostname=<optimized out>, port=<optimized out>, weight=0) at libmemcached/hosts.cc:585
#2 0x0000000000400c56 in main ()
(gdb) list
311 if (memcached_is_weighted_ketama(ptr))
312 {
313 for (uint32_t x = 0; x < pointer_per_hash; x++)
314 {
315 uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
316 ptr->ketama.continuum[continuum_index].index= host_index;
317 ptr->ketama.continuum[continuum_index++].value= value;
318 }
319 }
320 else
(gdb) print ptr->ketama.continuum
$1 = (memcached_continuum_item_st *) 0x0
(gdb) print ptr->ketama.continuum_count
$2 = 11
(gdb) quit
Attached is a patch to fix that. |
|
2016-09-22 15:29:01 |
Denis |
description |
When used with MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED at memcached_servers_reset ketama.continuum is freed, NULL-ed, but ketama.continuum_count is not zeroed. It leads to segfault when memcached_server_add() is accessing ketama.continuum[0].
The following code is a proof:
#include <libmemcached/memcached.h>
#include <stdio.h>
int main() {
const char *config_string= "--SERVER=localhost";
const char *key= "foo";
const char *value= "bar";
memcached_return_t err;
size_t retlen;
char *retvalue;
memcached_st *memc= memcached(config_string, strlen(config_string));
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get failed, %s\n", memcached_strerror(memc, err));
}
memcached_servers_reset(memc);
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get 2 failed, %s\n", memcached_strerror(memc, err));
}
memcached_free(memc);
}
Actual behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
Segmentation fault (core dumped)
Expected behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
bar
gdb output:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
316 ptr->ketama.continuum[continuum_index].index= host_index;
(gdb) bt
#0 0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
#1 0x00007ffff7bbf8f6 in memcached_server_add_with_weight (shell=0x614c20, hostname=<optimized out>, port=<optimized out>, weight=0) at libmemcached/hosts.cc:585
#2 0x0000000000400c56 in main ()
(gdb) list
311 if (memcached_is_weighted_ketama(ptr))
312 {
313 for (uint32_t x = 0; x < pointer_per_hash; x++)
314 {
315 uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
316 ptr->ketama.continuum[continuum_index].index= host_index;
317 ptr->ketama.continuum[continuum_index++].value= value;
318 }
319 }
320 else
(gdb) print ptr->ketama.continuum
$1 = (memcached_continuum_item_st *) 0x0
(gdb) print ptr->ketama.continuum_count
$2 = 11
(gdb) quit
Attached is a patch to fix that. |
libmemcached 1.0.18
When used with MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED at memcached_servers_reset ketama.continuum is freed, NULL-ed, but ketama.continuum_count is not zeroed. It leads to segfault when memcached_server_add() is accessing ketama.continuum[0].
The following code is a proof:
#include <libmemcached/memcached.h>
#include <stdio.h>
int main() {
const char *config_string= "--SERVER=localhost";
const char *key= "foo";
const char *value= "bar";
memcached_return_t err;
size_t retlen;
char *retvalue;
memcached_st *memc= memcached(config_string, strlen(config_string));
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get failed, %s\n", memcached_strerror(memc, err));
}
memcached_servers_reset(memc);
err= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true);
if (err != MEMCACHED_SUCCESS) {
printf("behavior set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_server_add(memc, "localhost", 11211);
if (err != MEMCACHED_SUCCESS) {
printf("server add 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
err= memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0);
if (err != MEMCACHED_SUCCESS) {
printf("set 2 failed, %s\n", memcached_strerror(memc, err));
exit(1);
}
retvalue= memcached_get(memc, key, strlen(key), &retlen, 0, &err);
if (retvalue) {
printf("%s\n", retvalue);
} else {
printf("get 2 failed, %s\n", memcached_strerror(memc, err));
}
memcached_free(memc);
}
Actual behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
Segmentation fault (core dumped)
Expected behavior:
$ gcc memcached_bug.c -o memcached_bug -lmemcached -ggdb
$ ./memcached_bug
bar
bar
gdb output:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
316 ptr->ketama.continuum[continuum_index].index= host_index;
(gdb) bt
#0 0x00007ffff7bbef3d in update_continuum (ptr=0x614c20) at libmemcached/hosts.cc:316
#1 0x00007ffff7bbf8f6 in memcached_server_add_with_weight (shell=0x614c20, hostname=<optimized out>, port=<optimized out>, weight=0) at libmemcached/hosts.cc:585
#2 0x0000000000400c56 in main ()
(gdb) list
311 if (memcached_is_weighted_ketama(ptr))
312 {
313 for (uint32_t x = 0; x < pointer_per_hash; x++)
314 {
315 uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
316 ptr->ketama.continuum[continuum_index].index= host_index;
317 ptr->ketama.continuum[continuum_index++].value= value;
318 }
319 }
320 else
(gdb) print ptr->ketama.continuum
$1 = (memcached_continuum_item_st *) 0x0
(gdb) print ptr->ketama.continuum_count
$2 = 11
(gdb) quit
Attached is a patch to fix that. |
|
2016-09-23 07:17:00 |
Denis |
attachment removed |
Patch that fixes bug in memcached_servers_reset https://bugs.launchpad.net/libmemcached/+bug/1626565/+attachment/4746251/+files/libmemcached-ketama-servers_reset.patch |
|
|
2016-09-23 07:18:09 |
Denis |
attachment added |
|
fixed patch https://bugs.launchpad.net/libmemcached/+bug/1626565/+attachment/4746731/+files/libmemcached-ketama-servers_reset.patch |
|
2016-09-23 07:21:20 |
Denis |
attachment removed |
fixed patch https://bugs.launchpad.net/libmemcached/+bug/1626565/+attachment/4746731/+files/libmemcached-ketama-servers_reset.patch |
|
|
2016-09-23 07:21:43 |
Denis |
attachment added |
|
fixed patch https://bugs.launchpad.net/libmemcached/+bug/1626565/+attachment/4746734/+files/libmemcached-ketama-servers_reset.patch |
|
2017-08-15 17:09:11 |
Jan Ove Kongshaug |
bug |
|
|
added subscriber Jan Ove Kongshaug |