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]
#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 */
* 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
*/
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
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;
*/
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;
}
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;
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;
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;
/* 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;
/* 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);
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]);
(*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));
* 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));
}
}
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);
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)
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. */
}
{
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;
}
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);
}
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;
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;
/* 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 */
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;
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;
/* 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);
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;
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);
#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);
}
}
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;
+}