summaryrefslogtreecommitdiff
path: root/testapp.c
diff options
context:
space:
mode:
authorbitground <70304874+bitground@users.noreply.github.com>2020-09-14 17:03:09 +0800
committerdormando <dormando@rydia.net>2020-10-26 16:36:00 -0700
commitb031143f8ab61296ddbf6c4470c5dcdbf7ae588b (patch)
tree39ad84ea0e932ddfd496b6543b5880a0f6fab53b /testapp.c
parent6b319c8c7a29e9c353dec83dc92f01905f6c8966 (diff)
downloadmemcached-b031143f8ab61296ddbf6c4470c5dcdbf7ae588b.tar.gz
Fix over-freeing in internal object cache
When returning item to the cache and the items allocated exceeded cache->limit, we should free the item and not put it to the cache. The current code will free any item that tried returned to the cache when cache->total < cache->limit which is true in most cases if the total objects has never exceeded the limit.
Diffstat (limited to 'testapp.c')
-rw-r--r--testapp.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/testapp.c b/testapp.c
index 2bbbc8c..b4ba41a 100644
--- a/testapp.c
+++ b/testapp.c
@@ -244,6 +244,34 @@ static enum test_return cache_redzone_test(void)
#endif
}
+static enum test_return cache_limit_revised_downward_test(void)
+{
+ int limit = 10, allocated_num = limit + 1, i;
+ char ** alloc_objs = calloc(allocated_num, sizeof(char *));
+
+ cache_t *cache = cache_create("test", sizeof(uint32_t), sizeof(char*),
+ NULL, NULL);
+ assert(cache != NULL);
+
+ /* cache->limit is 0 and we can allocate limit+1 items */
+ for (i = 0; i < allocated_num; i++) {
+ alloc_objs[i] = cache_alloc(cache);
+ assert(alloc_objs[i] != NULL);
+ }
+ assert(cache->total == allocated_num);
+
+ /* revised downward cache->limit */
+ cache_set_limit(cache, limit);
+
+ /* If we free one item, the cache->total should decreased by one*/
+ cache_free(cache, alloc_objs[0]);
+
+ assert(cache->total == allocated_num-1);
+ cache_destroy(cache);
+
+ return TEST_PASS;
+}
+
static enum test_return test_stats_prefix_find(void) {
PREFIX_STATS *pfs1, *pfs2;
@@ -2237,6 +2265,7 @@ struct testcase testcases[] = {
{ "cache_destructor", cache_destructor_test },
{ "cache_reuse", cache_reuse_test },
{ "cache_redzone", cache_redzone_test },
+ { "cache_limit_revised_downward", cache_limit_revised_downward_test },
{ "stats_prefix_find", test_stats_prefix_find },
{ "stats_prefix_record_get", test_stats_prefix_record_get },
{ "stats_prefix_record_delete", test_stats_prefix_record_delete },