summaryrefslogtreecommitdiff
path: root/dict.c
diff options
context:
space:
mode:
authorMichael Grunder <michael.grunder@gmail.com>2020-05-22 09:27:49 -0700
committerGitHub <noreply@github.com>2020-05-22 09:27:49 -0700
commit8e0264cfd6889b73c241b60736fe96ba1322ee6e (patch)
treec7a8f050a2e6966c45f7af919056b9653f831579 /dict.c
parent83bba659b9dbd6c77baf2ff27ff6342317869a3e (diff)
Allow users to replace allocator and handle OOM everywhere. (#800)
* Adds an indirection to every allocation/deallocation to allow users to plug in ones of their choosing (use custom functions, jemalloc, etc). * Gracefully handle OOM everywhere in hiredis. This should make it possible for users of the library to have more flexibility in how they handle such situations. * Changes `redisReaderTask->elements` from an `int` to a `long long` to prevent a possible overflow when transferring the task elements into a `redisReply`. * Adds a configurable `max elements` member to `redisReader` that defaults to 2^32 - 1. This can be set to "unlimited" by setting the value to zero.
Diffstat (limited to 'dict.c')
-rw-r--r--dict.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/dict.c b/dict.c
index eaf4e4d..34a33ea 100644
--- a/dict.c
+++ b/dict.c
@@ -73,6 +73,9 @@ static void _dictReset(dict *ht) {
/* Create a new hash table */
static dict *dictCreate(dictType *type, void *privDataPtr) {
dict *ht = hi_malloc(sizeof(*ht));
+ if (ht == NULL)
+ return NULL;
+
_dictInit(ht,type,privDataPtr);
return ht;
}
@@ -98,7 +101,9 @@ static int dictExpand(dict *ht, unsigned long size) {
_dictInit(&n, ht->type, ht->privdata);
n.size = realsize;
n.sizemask = realsize-1;
- n.table = calloc(realsize,sizeof(dictEntry*));
+ n.table = hi_calloc(realsize,sizeof(dictEntry*));
+ if (n.table == NULL)
+ return DICT_ERR;
/* Copy all the elements from the old to the new table:
* note that if the old hash table is empty ht->size is zero,
@@ -125,7 +130,7 @@ static int dictExpand(dict *ht, unsigned long size) {
}
}
assert(ht->used == 0);
- free(ht->table);
+ hi_free(ht->table);
/* Remap the new hashtable in the old */
*ht = n;
@@ -144,6 +149,9 @@ static int dictAdd(dict *ht, void *key, void *val) {
/* Allocates the memory and stores key */
entry = hi_malloc(sizeof(*entry));
+ if (entry == NULL)
+ return DICT_ERR;
+
entry->next = ht->table[index];
ht->table[index] = entry;
@@ -167,6 +175,9 @@ static int dictReplace(dict *ht, void *key, void *val) {
return 1;
/* It already exists, get the entry */
entry = dictFind(ht, key);
+ if (entry == NULL)
+ return 0;
+
/* Free the old value and set the new one */
/* 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
@@ -200,7 +211,7 @@ static int dictDelete(dict *ht, const void *key) {
dictFreeEntryKey(ht,de);
dictFreeEntryVal(ht,de);
- free(de);
+ hi_free(de);
ht->used--;
return DICT_OK;
}
@@ -223,13 +234,13 @@ static int _dictClear(dict *ht) {
nextHe = he->next;
dictFreeEntryKey(ht, he);
dictFreeEntryVal(ht, he);
- free(he);
+ hi_free(he);
ht->used--;
he = nextHe;
}
}
/* Free the table and the allocated cache structure */
- free(ht->table);
+ hi_free(ht->table);
/* Re-initialize the table */
_dictReset(ht);
return DICT_OK; /* never fails */
@@ -238,7 +249,7 @@ static int _dictClear(dict *ht) {
/* Clear & Release the hash table */
static void dictRelease(dict *ht) {
_dictClear(ht);
- free(ht);
+ hi_free(ht);
}
static dictEntry *dictFind(dict *ht, const void *key) {
@@ -258,6 +269,8 @@ static dictEntry *dictFind(dict *ht, const void *key) {
static dictIterator *dictGetIterator(dict *ht) {
dictIterator *iter = hi_malloc(sizeof(*iter));
+ if (iter == NULL)
+ return NULL;
iter->ht = ht;
iter->index = -1;
@@ -287,7 +300,7 @@ static dictEntry *dictNext(dictIterator *iter) {
}
static void dictReleaseIterator(dictIterator *iter) {
- free(iter);
+ hi_free(iter);
}
/* ------------------------- private functions ------------------------------ */