From 2069d06a0bb88acf17153e2ece1ffb857d11645d Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 17 Mar 2010 02:00:03 +0100 Subject: [PATCH] Fixed a bug in HSET, a memory leak, and a theoretical bug in dict.c --- dict.c | 10 ++++++++-- redis.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/dict.c b/dict.c index 725c9a51..23f7933b 100644 --- a/dict.c +++ b/dict.c @@ -232,7 +232,7 @@ int dictAdd(dict *ht, void *key, void *val) * operation. */ int dictReplace(dict *ht, void *key, void *val) { - dictEntry *entry; + dictEntry *entry, auxentry; /* Try to add the element. If the key * does not exists dictAdd will suceed. */ @@ -241,8 +241,14 @@ int dictReplace(dict *ht, void *key, void *val) /* It already exists, get the entry */ entry = dictFind(ht, key); /* Free the old value and set the new one */ - dictFreeEntryVal(ht, entry); + /* Set the new value and free the old one. Note that it is important + * to do that in this order, as the value may just be exactly the same + * as the previous one. In this context, think to reference counting, + * you want to increment (set), and then decrement (free), and not the + * reverse. */ + auxentry = *entry; dictSetHashVal(ht, entry, val); + dictFreeEntryVal(ht, &auxentry); return 0; } diff --git a/redis.c b/redis.c index 302944de..3f9c4c96 100644 --- a/redis.c +++ b/redis.c @@ -5849,7 +5849,7 @@ static void hsetCommand(redisClient *c) { tryObjectEncoding(c->argv[2]); /* note that c->argv[3] is already encoded, as the latest arg * of a bulk command is always integer encoded if possible. */ - if (dictAdd(o->ptr,c->argv[2],c->argv[3]) == DICT_OK) { + if (dictReplace(o->ptr,c->argv[2],c->argv[3])) { incrRefCount(c->argv[2]); } else { update = 1; -- 2.45.2