Commit a1537886 authored by Michael Grunder's avatar Michael Grunder Committed by michael-grunder
Browse files

Safe allocation wrappers (#754)

Create allocation wrappers with a configurable OOM handler (defaults to abort()).

See #752, #747
parent 68503065
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com> # Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
# This file is released under the BSD license, see the COPYING file # This file is released under the BSD license, see the COPYING file
OBJ=net.o hiredis.o sds.o async.o read.o OBJ=net.o hiredis.o sds.o async.o read.o alloc.o
EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
TESTS=hiredis-test TESTS=hiredis-test
LIBNAME=libhiredis LIBNAME=libhiredis
...@@ -68,13 +68,14 @@ endif ...@@ -68,13 +68,14 @@ endif
all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME) all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
# Deps (use make dep to generate this) # Deps (use make dep to generate this)
async.o: async.c fmacros.h async.h hiredis.h read.h sds.h net.h dict.c dict.h alloc.o: alloc.c fmacros.h alloc.h
dict.o: dict.c fmacros.h dict.h async.o: async.c fmacros.h alloc.h async.h hiredis.h read.h sds.h net.h dict.c dict.h
hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h net.h dict.o: dict.c fmacros.h alloc.h dict.h
net.o: net.c fmacros.h net.h hiredis.h read.h sds.h hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h alloc.h net.h
net.o: net.c fmacros.h net.h hiredis.h read.h sds.h alloc.h
read.o: read.c fmacros.h read.h sds.h read.o: read.c fmacros.h read.h sds.h
sds.o: sds.c sds.h sds.o: sds.c sds.h sdsalloc.h
test.o: test.c fmacros.h hiredis.h read.h sds.h test.o: test.c fmacros.h hiredis.h read.h sds.h alloc.h net.h
$(DYLIBNAME): $(OBJ) $(DYLIBNAME): $(OBJ)
$(DYLIB_MAKE_CMD) $(OBJ) $(DYLIB_MAKE_CMD) $(OBJ)
...@@ -177,7 +178,7 @@ $(PKGCONFNAME): hiredis.h ...@@ -177,7 +178,7 @@ $(PKGCONFNAME): hiredis.h
install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH) mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH)
$(INSTALL) hiredis.h async.h read.h sds.h $(INSTALL_INCLUDE_PATH) $(INSTALL) hiredis.h async.h read.h sds.h alloc.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME)
......
...@@ -108,7 +108,7 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { ...@@ -108,7 +108,7 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
return REDIS_ERR; return REDIS_ERR;
/* Create container for context and r/w events */ /* Create container for context and r/w events */
e = (redisAeEvents*)malloc(sizeof(*e)); e = (redisAeEvents*)hi_malloc(sizeof(*e));
e->context = ac; e->context = ac;
e->loop = loop; e->loop = loop;
e->fd = c->fd; e->fd = c->fd;
......
...@@ -55,7 +55,7 @@ static int redisIvykisAttach(redisAsyncContext *ac) { ...@@ -55,7 +55,7 @@ static int redisIvykisAttach(redisAsyncContext *ac) {
return REDIS_ERR; return REDIS_ERR;
/* Create container for context and r/w events */ /* Create container for context and r/w events */
e = (redisIvykisEvents*)malloc(sizeof(*e)); e = (redisIvykisEvents*)hi_malloc(sizeof(*e));
e->context = ac; e->context = ac;
/* Register functions to start/stop listening for events */ /* Register functions to start/stop listening for events */
......
...@@ -119,7 +119,7 @@ static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { ...@@ -119,7 +119,7 @@ static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
return REDIS_ERR; return REDIS_ERR;
/* Create container for context and r/w events */ /* Create container for context and r/w events */
e = (redisLibevEvents*)malloc(sizeof(*e)); e = (redisLibevEvents*)hi_malloc(sizeof(*e));
e->context = ac; e->context = ac;
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
e->loop = loop; e->loop = loop;
......
...@@ -87,7 +87,7 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { ...@@ -87,7 +87,7 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
return REDIS_ERR; return REDIS_ERR;
/* Create container for context and r/w events */ /* Create container for context and r/w events */
e = (redisLibeventEvents*)malloc(sizeof(*e)); e = (redisLibeventEvents*)hi_calloc(1, sizeof(*e));
e->context = ac; e->context = ac;
/* Register functions to start/stop listening for events */ /* Register functions to start/stop listening for events */
......
/*
* Copyright (c) 2020, Michael Grunder <michael dot grunder at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "fmacros.h"
#include "alloc.h"
#include <string.h>
void *hi_malloc(size_t size) {
void *ptr = malloc(size);
if (ptr == NULL)
HIREDIS_OOM_HANDLER;
return ptr;
}
void *hi_calloc(size_t nmemb, size_t size) {
void *ptr = calloc(nmemb, size);
if (ptr == NULL)
HIREDIS_OOM_HANDLER;
return ptr;
}
void *hi_realloc(void *ptr, size_t size) {
void *newptr = realloc(ptr, size);
if (newptr == NULL)
HIREDIS_OOM_HANDLER;
return newptr;
}
char *hi_strdup(const char *str) {
char *newstr = strdup(str);
if (newstr == NULL)
HIREDIS_OOM_HANDLER;
return newstr;
}
/*
* Copyright (c) 2020, Michael Grunder <michael dot grunder at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HIREDIS_ALLOC_H
#define HIREDIS_ALLOC_H
#include <stdlib.h> /* for size_t */
#ifndef HIREDIS_OOM_HANDLER
#define HIREDIS_OOM_HANDLER abort()
#endif
#ifdef __cplusplus
extern "C" {
#endif
void *hi_malloc(size_t size);
void *hi_calloc(size_t nmemb, size_t size);
void *hi_realloc(void *ptr, size_t size);
char *hi_strdup(const char *str);
#ifdef __cplusplus
}
#endif
#endif /* HIREDIS_ALLOC_H */
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
*/ */
#include "fmacros.h" #include "fmacros.h"
#include "alloc.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
...@@ -68,7 +69,7 @@ static unsigned int callbackHash(const void *key) { ...@@ -68,7 +69,7 @@ static unsigned int callbackHash(const void *key) {
static void *callbackValDup(void *privdata, const void *src) { static void *callbackValDup(void *privdata, const void *src) {
((void) privdata); ((void) privdata);
redisCallback *dup = malloc(sizeof(*dup)); redisCallback *dup = hi_malloc(sizeof(*dup));
memcpy(dup,src,sizeof(*dup)); memcpy(dup,src,sizeof(*dup));
return dup; return dup;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
#include "fmacros.h" #include "fmacros.h"
#include "alloc.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
...@@ -71,7 +72,7 @@ static void _dictReset(dict *ht) { ...@@ -71,7 +72,7 @@ static void _dictReset(dict *ht) {
/* Create a new hash table */ /* Create a new hash table */
static dict *dictCreate(dictType *type, void *privDataPtr) { static dict *dictCreate(dictType *type, void *privDataPtr) {
dict *ht = malloc(sizeof(*ht)); dict *ht = hi_malloc(sizeof(*ht));
_dictInit(ht,type,privDataPtr); _dictInit(ht,type,privDataPtr);
return ht; return ht;
} }
...@@ -142,7 +143,7 @@ static int dictAdd(dict *ht, void *key, void *val) { ...@@ -142,7 +143,7 @@ static int dictAdd(dict *ht, void *key, void *val) {
return DICT_ERR; return DICT_ERR;
/* Allocates the memory and stores key */ /* Allocates the memory and stores key */
entry = malloc(sizeof(*entry)); entry = hi_malloc(sizeof(*entry));
entry->next = ht->table[index]; entry->next = ht->table[index];
ht->table[index] = entry; ht->table[index] = entry;
...@@ -256,7 +257,7 @@ static dictEntry *dictFind(dict *ht, const void *key) { ...@@ -256,7 +257,7 @@ static dictEntry *dictFind(dict *ht, const void *key) {
} }
static dictIterator *dictGetIterator(dict *ht) { static dictIterator *dictGetIterator(dict *ht) {
dictIterator *iter = malloc(sizeof(*iter)); dictIterator *iter = hi_malloc(sizeof(*iter));
iter->ht = ht; iter->ht = ht;
iter->index = -1; iter->index = -1;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <sys/time.h> /* for struct timeval */ #include <sys/time.h> /* for struct timeval */
#include <stdint.h> /* uintXX_t, etc */ #include <stdint.h> /* uintXX_t, etc */
#include "sds.h" /* for sds */ #include "sds.h" /* for sds */
#include "alloc.h" /* for allocation wrappers */
#define HIREDIS_MAJOR 0 #define HIREDIS_MAJOR 0
#define HIREDIS_MINOR 14 #define HIREDIS_MINOR 14
......
...@@ -287,13 +287,13 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, ...@@ -287,13 +287,13 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
if (c->tcp.host != addr) { if (c->tcp.host != addr) {
free(c->tcp.host); free(c->tcp.host);
c->tcp.host = strdup(addr); c->tcp.host = hi_strdup(addr);
} }
if (timeout) { if (timeout) {
if (c->timeout != timeout) { if (c->timeout != timeout) {
if (c->timeout == NULL) if (c->timeout == NULL)
c->timeout = malloc(sizeof(struct timeval)); c->timeout = hi_malloc(sizeof(struct timeval));
memcpy(c->timeout, timeout, sizeof(struct timeval)); memcpy(c->timeout, timeout, sizeof(struct timeval));
} }
...@@ -312,7 +312,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, ...@@ -312,7 +312,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
c->tcp.source_addr = NULL; c->tcp.source_addr = NULL;
} else if (c->tcp.source_addr != source_addr) { } else if (c->tcp.source_addr != source_addr) {
free(c->tcp.source_addr); free(c->tcp.source_addr);
c->tcp.source_addr = strdup(source_addr); c->tcp.source_addr = hi_strdup(source_addr);
} }
snprintf(_port, 6, "%d", port); snprintf(_port, 6, "%d", port);
...@@ -440,12 +440,12 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time ...@@ -440,12 +440,12 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
c->connection_type = REDIS_CONN_UNIX; c->connection_type = REDIS_CONN_UNIX;
if (c->unix_sock.path != path) if (c->unix_sock.path != path)
c->unix_sock.path = strdup(path); c->unix_sock.path = hi_strdup(path);
if (timeout) { if (timeout) {
if (c->timeout != timeout) { if (c->timeout != timeout) {
if (c->timeout == NULL) if (c->timeout == NULL)
c->timeout = malloc(sizeof(struct timeval)); c->timeout = hi_malloc(sizeof(struct timeval));
memcpy(c->timeout, timeout, sizeof(struct timeval)); memcpy(c->timeout, timeout, sizeof(struct timeval));
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment