]> granicus.if.org Git - apache/commitdiff
Add wrappers for malloc, calloc, realloc that check for out of memory
authorStefan Fritsch <sf@apache.org>
Mon, 19 Sep 2011 16:25:42 +0000 (16:25 +0000)
committerStefan Fritsch <sf@apache.org>
Mon, 19 Sep 2011 16:25:42 +0000 (16:25 +0000)
situations.  Use them in most places where malloc, and friends are used.
This results in clean error messages in an out of memory situation instead of
segfaulting or silently malfunctioning. In some places, it just allows to
remove some logging code.

PR 51568, PR 51569, PR 51571.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1172686 13f79535-47bb-0310-9956-ffa450edef68

18 files changed:
CHANGES
include/ap_config.h
include/ap_mmn.h
include/httpd.h
modules/cache/cache_cache.c
modules/cache/cache_hash.c
modules/cache/cache_pqueue.c
modules/cache/mod_socache_dbm.c
modules/examples/mod_case_filter_in.c
modules/proxy/proxy_util.c
modules/ssl/ssl_util.c
server/config.c
server/main.c
server/mpm/event/event.c
server/mpm/worker/worker.c
server/mpm_unix.c
server/scoreboard.c
server/util.c

diff --git a/CHANGES b/CHANGES
index 0fa1925048f88c63d43d1b63564e0675c095ba4d..10b6c0eb1f703bc4fadef178aae582fccfea4c8b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,10 @@ Changes with Apache 2.3.15
      PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener,
      <lowprio20 gmail.com>]
 
+  *) Add wrappers for malloc, calloc, realloc that check for out of memory
+     situations and use them in many places. PR 51568, PR 51569, PR 51571.
+     [Stefan Fritsch]
+
   *) Fix cross-compilation of mod_cgi/mod_cgid when APR_HAVE_STRUCT_RLIMIT is 
      false but RLIMIT_* are defined.  PR51371. [Eric Covener]
 
index ea2c19581bcde90589673b648f11cfa3b29607db..ee7724ddb977b0e6b683879bc758a21b3183f697 100644 (file)
 #define ap_func_attr_sentinel
 #endif
 
+#if ( defined(__GNUC__) &&                                        \
+      (__GNUC__ >= 4 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4))) \
+    || __has_attribute(warn_unused_result)
+#define ap_func_attr_warn_unused_result   __attribute__((warn_unused_result))
+#else
+#define ap_func_attr_warn_unused_result
+#endif
+
 #endif /* AP_CONFIG_H */
index ffec22da1779bb157fa031356801c4497f365508..94796ddd6836566fe02ece4c9a441a9ca31d86b8 100644 (file)
  * 20110724.5 (2.3.15-dev) add ap_set_accept_ranges()
  * 20110724.6 (2.3.15-dev) add max_overlaps and max_reversals to core_dir_config
  * 20110724.7 (2.3.15-dev) add ap_random_insecure_bytes(), ap_random_pick()
+ * 20110724.8 (2.3.15-dev) add ap_abort_on_oom(), ap_malloc(), ap_calloc(),
+ *                         ap_realloc()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20110724
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 7                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 8                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 795401550ded1e6483051044b7a5ce6aec62bd3f..000a7bf8dcac1b8fbe89d6b0075e2da5e41c59e2 100644 (file)
@@ -2086,6 +2086,38 @@ AP_DECLARE(void) ap_random_insecure_bytes(void *buf, apr_size_t size);
  */
 AP_DECLARE(apr_uint32_t) ap_random_pick(apr_uint32_t min, apr_uint32_t max);
 
+/**
+ * Abort with a error message signifying out of memory
+ */
+AP_DECLARE(void) ap_abort_on_oom(void) __attribute__((noreturn));
+
+/**
+ * Wrapper for malloc() that calls ap_abort_on_oom() if out of memory
+ * @param size size of the memory block
+ * @return pointer to the allocated memory
+ * @note ap_malloc may be implemented as a macro
+ */
+AP_DECLARE(void *) ap_malloc(size_t size) __attribute__((malloc));
+
+/**
+ * Wrapper for calloc() that calls ap_abort_on_oom() if out of memory
+ * @param nelem number of elements to allocate memory for
+ * @param size size of a single element
+ * @return pointer to the allocated memory
+ * @note ap_calloc may be implemented as a macro
+ */
+AP_DECLARE(void *) ap_calloc(size_t nelem, size_t size) __attribute__((malloc));
+
+/**
+ * Wrapper for realloc() that calls ap_abort_on_oom() if out of memory
+ * @param ptr pointer to the old memory block (or NULL)
+ * @param size new size of the memory block
+ * @return pointer to the reallocated memory
+ * @note ap_realloc may be implemented as a macro
+ */
+AP_DECLARE(void *) ap_realloc(void *ptr, size_t size)
+                   ap_func_attr_warn_unused_result;
+
 
 #define AP_NORESTART APR_OS_START_USEERR + 1
 
index ce518087ee144c56235be2e997711009fc1944d5..b0dd5971230c7d805c0432cd5e2d59b9a367998c 100644 (file)
@@ -58,7 +58,7 @@ cache_cache_t* cache_init(int max_entries,
                                          cache_cache_free *free_entry)
 {
     cache_cache_t *tmp;
-    tmp = malloc(sizeof(cache_cache_t));
+    tmp = ap_malloc(sizeof(cache_cache_t));
     tmp->max_entries = max_entries;
     tmp->max_size = max_size;
     tmp->current_size = 0;
index 202cf9f70c40665bddbafcd2eb9ad459bd23c13a..57f7db17ca8e31ab7829e04ac796d4e2563c5dee 100644 (file)
@@ -77,23 +77,16 @@ struct cache_hash_t {
  */
 static cache_hash_entry_t **alloc_array(cache_hash_t *ht, int max)
 {
-   return calloc(1, sizeof(*ht->array) * (max + 1));
+   return ap_calloc(1, sizeof(*ht->array) * (max + 1));
 }
 
 cache_hash_t* cache_hash_make(apr_size_t size)
 {
     cache_hash_t *ht;
-    ht = malloc(sizeof(cache_hash_t));
-    if (!ht) {
-        return NULL;
-    }
+    ht = ap_malloc(sizeof(cache_hash_t));
     ht->count = 0;
     ht->max = size;
     ht->array = alloc_array(ht, ht->max);
-    if (!ht->array) {
-        free(ht);
-        return NULL;
-    }
     return ht;
 }
 
@@ -226,10 +219,7 @@ static cache_hash_entry_t **find_entry(cache_hash_t *ht,
     if (he || !val)
         return hep;
     /* add a new entry for non-NULL values */
-    he = malloc(sizeof(*he));
-    if (!he) {
-        return NULL;
-    }
+    he = ap_malloc(sizeof(*he));
     he->next = NULL;
     he->hash = hash;
     he->key  = key;
@@ -260,8 +250,7 @@ void* cache_hash_set(cache_hash_t *ht,
     cache_hash_entry_t **hep, *tmp;
     const void *tval;
     hep = find_entry(ht, key, klen, val);
-    /* If hep == NULL, then the malloc() in find_entry failed */
-    if (hep && *hep) {
+    if (*hep) {
         if (!val) {
             /* delete entry */
             tval = (*hep)->val;
index 580b47e72a6c00de1c91dc0cec09cf43e8b77613..164bb9d26a3ab139f2d65892d0742148a98820f5 100644 (file)
@@ -50,17 +50,9 @@ cache_pqueue_t *cache_pq_init(apr_ssize_t n,
                               cache_pqueue_getpos get,
                               cache_pqueue_setpos set)
 {
-    cache_pqueue_t *q;
-
-    if (!(q = malloc(sizeof(cache_pqueue_t)))) {
-        return NULL;
-    }
-
+    cache_pqueue_t *q = ap_malloc(sizeof(cache_pqueue_t));
     /* Need to allocate n+1 elements since element 0 isn't used. */
-    if (!(q->d = malloc(sizeof(void*) * (n+1)))) {
-        free(q);
-        return NULL;
-    }
+    q->d = ap_malloc(sizeof(void*) * (n+1));
     q->avail = q->step = (n+1);  /* see comment above about n+1 */
     q->pri = pri;
     q->size = 1;
@@ -148,7 +140,7 @@ apr_status_t cache_pq_insert(cache_pqueue_t *q, void *d)
     /* allocate more memory if necessary */
     if (q->size >= q->avail) {
         newsize = q->size + q->step;
-        if (!(tmp = realloc(q->d, sizeof(void*) * newsize))) {
+        if (!(tmp = ap_realloc(q->d, sizeof(void*) * newsize))) {
             return APR_EGENERAL;
         };
         q->d = tmp;
index 2fca723a3a486a5f444ffa112b9602a92dfcc009..5020c190bb363dbd90ee4c44fbbe1be5e5cdbbd6 100644 (file)
@@ -210,12 +210,7 @@ static apr_status_t socache_dbm_store(ap_socache_instance_t *ctx,
 
     /* create DBM value */
     dbmval.dsize = sizeof(apr_time_t) + nData;
-    dbmval.dptr  = (char *)malloc(dbmval.dsize);
-    if (dbmval.dptr == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "malloc error creating DBM value");
-        return APR_ENOMEM;
-    }
+    dbmval.dptr  = (char *)ap_malloc(dbmval.dsize);
     memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t));
     memcpy((char *)dbmval.dptr+sizeof(apr_time_t), ucaData, nData);
 
index 966d7a999687ba4fc7d3c5f2a5db1e8d7a3511f6..73af077afaae0a74a7da490e1a23c7bcf65632ee 100644 (file)
@@ -109,7 +109,7 @@ static apr_status_t CaseFilterInFilter(ap_filter_t *f,
         if(ret != APR_SUCCESS)
             return ret;
 
-        buf = malloc(len);
+        buf = ap_malloc(len);
         for(n=0 ; n < len ; ++n)
             buf[n] = apr_toupper(data[n]);
 
index 25fd26c82a5b8c3dd8538091231c9827adc8e63b..f10a2b99ee61f54f9c633a0dd796dc22ead44ed3 100644 (file)
@@ -1384,7 +1384,7 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
     (*balancer)->lbmethod = lbmethod;
 
     if (do_malloc)
-        bshared = malloc(sizeof(proxy_balancer_shared));
+        bshared = ap_malloc(sizeof(proxy_balancer_shared));
     else
         bshared = apr_palloc(p, sizeof(proxy_balancer_shared));
 
@@ -1798,7 +1798,7 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
      * if called during config, we don't have shm setup yet,
      * so just note the info for later. */
     if (do_malloc)
-        wshared = malloc(sizeof(proxy_worker_shared));  /* will be freed ap_proxy_share_worker */
+        wshared = ap_malloc(sizeof(proxy_worker_shared));  /* will be freed ap_proxy_share_worker */
     else
         wshared = apr_palloc(p, sizeof(proxy_worker_shared));
 
index 6057a6f491e036a8106d6128f771c430711ab0d9..091a68fe4d2b8fbd5f49f78596ac257fc813ed33 100644 (file)
@@ -213,14 +213,14 @@ unsigned char *ssl_asn1_table_set(apr_hash_t *table,
         }
     }
     else {
-        asn1 = malloc(sizeof(*asn1));
+        asn1 = ap_malloc(sizeof(*asn1));
         asn1->source_mtime = 0; /* used as a note for encrypted private keys */
         asn1->cpData = NULL;
     }
 
     asn1->nData = length;
     if (!asn1->cpData) {
-        asn1->cpData = malloc(length);
+        asn1->cpData = ap_malloc(length);
     }
 
     apr_hash_set(table, key, klen, asn1);
index 1068b1f9a2b1c7525c1d1eb086767a3984b9498e..0c8e04cd3409374ed0202374d3eca3fd776575a9 100644 (file)
@@ -772,10 +772,10 @@ AP_DECLARE(const char *) ap_setup_prelinked_modules(process_rec *process)
     ap_loaded_modules = (module **)apr_palloc(process->pool,
         sizeof(module *) * conf_vector_length);
     if (!ap_module_short_names)
-        ap_module_short_names = calloc(sizeof(char *), conf_vector_length);
+        ap_module_short_names = ap_calloc(sizeof(char *), conf_vector_length);
 
     if (!merger_func_cache)
-        merger_func_cache = calloc(sizeof(merger_func), conf_vector_length);
+        merger_func_cache = ap_calloc(sizeof(merger_func), conf_vector_length);
 
     if (ap_loaded_modules == NULL || ap_module_short_names == NULL
         || merger_func_cache == NULL)
index 3b38bdde15f464ea20c673bdc3b8d65a9248d69b..2fdd4a1ad803e92b03496ffcd3bd241dd2736786 100644 (file)
@@ -265,14 +265,10 @@ static void destroy_and_exit_process(process_rec *process,
     exit(process_exit_value);
 }
 
-#define OOM_MESSAGE "[crit] Memory allocation failed, " \
-    "aborting process." APR_EOL_STR
-
 /* APR callback invoked if allocation fails. */
 static int abort_on_oom(int retcode)
 {
-    write(STDERR_FILENO, OOM_MESSAGE, strlen(OOM_MESSAGE));
-    abort();
+    ap_abort_on_oom();
     return retcode; /* unreachable, hopefully. */
 }
 
index 82401658d98d3b04cf0c241ce63bf21b192d3b01..2e4ca384531d4d6288112ace4abe7e1b3c25029e 100644 (file)
@@ -1007,7 +1007,7 @@ static apr_status_t s_socket_add(void *user_baton,
 {
     s_baton_t *s = (s_baton_t*)user_baton;
     /* XXXXX: recycle listener_poll_types */
-    listener_poll_type *pt = malloc(sizeof(*pt));
+    listener_poll_type *pt = ap_malloc(sizeof(*pt));
     pt->type = PT_SERF;
     pt->baton = serf_baton;
     pfd->client_data = pt;
@@ -1187,7 +1187,7 @@ static apr_status_t event_register_timed_callback(apr_time_t t,
     }
     else {
         /* XXXXX: lol, pool allocation without a context from any thread.Yeah. Right. MPMs Suck. */
-        te = malloc(sizeof(timer_event_t));
+        te = ap_malloc(sizeof(timer_event_t));
         APR_RING_ELEM_INIT(te, link);
     }
 
@@ -1766,7 +1766,7 @@ static void create_listener_thread(thread_starter * ts)
     proc_info *my_info;
     apr_status_t rv;
 
-    my_info = (proc_info *) malloc(sizeof(proc_info));
+    my_info = (proc_info *) ap_malloc(sizeof(proc_info));
     my_info->pid = my_child_num;
     my_info->tid = -1;          /* listener thread doesn't have a thread slot */
     my_info->sd = 0;
@@ -1865,12 +1865,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
                 continue;
             }
 
-            my_info = (proc_info *) malloc(sizeof(proc_info));
-            if (my_info == NULL) {
-                ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
-                             "malloc: out of memory");
-                clean_child_exit(APEXIT_CHILDFATAL);
-            }
+            my_info = (proc_info *) ap_malloc(sizeof(proc_info));
             my_info->pid = my_child_num;
             my_info->tid = i;
             my_info->sd = 0;
@@ -2047,16 +2042,8 @@ static void child_main(int child_num_arg)
     /* clear the storage; we may not create all our threads immediately,
      * and we want a 0 entry to indicate a thread which was not created
      */
-    threads = (apr_thread_t **) calloc(1,
-                                       sizeof(apr_thread_t *) *
-                                       threads_per_child);
-    if (threads == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
-                     "malloc: out of memory");
-        clean_child_exit(APEXIT_CHILDFATAL);
-    }
-
-    ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
+    threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
+    ts = apr_palloc(pchild, sizeof(*ts));
 
     apr_threadattr_create(&thread_attr, pchild);
     /* 0 means PTHREAD_CREATE_JOINABLE */
index 4f80f9a370943ddbe876782da5c742924c1b6ee1..5b9fea1aff2d7262ff7bf9ab01a8b72e02857523 100644 (file)
@@ -1006,7 +1006,7 @@ static void create_listener_thread(thread_starter *ts)
     proc_info *my_info;
     apr_status_t rv;
 
-    my_info = (proc_info *)malloc(sizeof(proc_info));
+    my_info = (proc_info *)ap_malloc(sizeof(proc_info));
     my_info->pid = my_child_num;
     my_info->tid = -1; /* listener thread doesn't have a thread slot */
     my_info->sd = 0;
@@ -1072,12 +1072,7 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
                 continue;
             }
 
-            my_info = (proc_info *)malloc(sizeof(proc_info));
-            if (my_info == NULL) {
-                ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
-                             "malloc: out of memory");
-                clean_child_exit(APEXIT_CHILDFATAL);
-            }
+            my_info = (proc_info *)ap_malloc(sizeof(proc_info));
             my_info->pid = my_child_num;
             my_info->tid = i;
             my_info->sd = 0;
@@ -1271,14 +1266,8 @@ static void child_main(int child_num_arg)
     /* clear the storage; we may not create all our threads immediately,
      * and we want a 0 entry to indicate a thread which was not created
      */
-    threads = (apr_thread_t **)calloc(1,
-                                sizeof(apr_thread_t *) * threads_per_child);
-    if (threads == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
-                     "malloc: out of memory");
-        clean_child_exit(APEXIT_CHILDFATAL);
-    }
-
+    threads = (apr_thread_t **)ap_calloc(1,
+                                  sizeof(apr_thread_t *) * threads_per_child);
     ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
 
     apr_threadattr_create(&thread_attr, pchild);
index 2dd43558bb1f508966eb8a65666321b92cdf7d3f..9675d2fa5c8890bfde83f3ae269e8b4bc3695637 100644 (file)
@@ -75,7 +75,7 @@ static extra_process_t *extras;
 
 void ap_register_extra_mpm_process(pid_t pid, ap_generation_t gen)
 {
-    extra_process_t *p = (extra_process_t *)malloc(sizeof(extra_process_t));
+    extra_process_t *p = (extra_process_t *)ap_malloc(sizeof(extra_process_t));
 
     p->next = extras;
     p->pid = pid;
index 22ce86224bdf934668a9fc279178985f18abaa52..4d2e5a3aaa9f317cdfd3e0157a16fadab81db0f8 100644 (file)
@@ -149,7 +149,7 @@ void ap_init_scoreboard(void *shared_score)
 
     ap_calc_scoreboard_size();
     ap_scoreboard_image =
-        calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *));
+        ap_calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *));
     more_storage = shared_score;
     ap_scoreboard_image->global = (global_score *)more_storage;
     more_storage += sizeof(global_score);
@@ -325,13 +325,7 @@ int ap_create_scoreboard(apr_pool_t *p, ap_scoreboard_e sb_type)
 #endif
     {
         /* A simple malloc will suffice */
-        void *sb_mem = calloc(1, scoreboard_size);
-        if (sb_mem == NULL) {
-            ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf,
-                         "(%d)%s: cannot allocate scoreboard",
-                         errno, strerror(errno));
-            return HTTP_INTERNAL_SERVER_ERROR;
-        }
+        void *sb_mem = ap_calloc(1, scoreboard_size);
         ap_init_scoreboard(sb_mem);
     }
 
index abecf23bb33f250c3631cbca81656c0af32ace3b..864a6b86a5e78763376e1215e9de4e9a444a90c8 100644 (file)
@@ -2583,3 +2583,36 @@ AP_DECLARE(void) ap_varbuf_free(struct ap_varbuf *vb)
     }
     vb->buf = NULL;
 }
+
+#define OOM_MESSAGE "[crit] Memory allocation failed, " \
+        "aborting process." APR_EOL_STR
+
+AP_DECLARE(void) ap_abort_on_oom()
+{
+    write(STDERR_FILENO, OOM_MESSAGE, strlen(OOM_MESSAGE));
+    abort();
+}
+
+AP_DECLARE(void *) ap_malloc(size_t size)
+{
+    void *p = malloc(size);
+    if (p == NULL && size != 0)
+        ap_abort_on_oom();
+    return p;
+}
+
+AP_DECLARE(void *) ap_calloc(size_t nelem, size_t size)
+{
+    void *p = calloc(nelem, size);
+    if (p == NULL && nelem != 0 && size != 0)
+        ap_abort_on_oom();
+    return p;
+}
+
+AP_DECLARE(void *) ap_realloc(void *ptr, size_t size)
+{
+    void *p = realloc(ptr, size);
+    if (p == NULL && size != 0)
+        ap_abort_on_oom();
+    return p;
+}