core: Stop using AST_INLINE_API for allocator functions.

This replaces AST_INLINE_API allocators in utils.h with real functions
implemented in astmm.c.  Associated macro's are also moved from utils.h
to astmm.h.

Remove menuselect conflicts between MALLOC_DEBUG and DEBUG_CHAOS as they
can now be combined.

This has multiple benefits:
* Simplifies asterisk/utils.h by removing inline functions and use of
  the logger.
* Removal of these inline functions decreases size of Asterisk and
  module binaries by 1% or more.
* Puts memory management functions together with and without
  MALLOC_DEBUG enabled, simplifying management of the code.
* Enables DEBUG_CHAOS for ASTMM_REDIRECT and bundled pjproject.

Change-Id: If9df4377f74bdbb627461b27a473123e05525887
16.0
Corey Farrell 7 years ago
parent d5bfba60d2
commit 4d1c9d8711

@ -78,11 +78,9 @@
<support_level>extended</support_level>
</member>
<member name="MALLOC_DEBUG" displayname="Keep Track of Memory Allocations">
<conflict>DEBUG_CHAOS</conflict>
<support_level>core</support_level>
</member>
<member name="DEBUG_CHAOS" displayname="Randomly FAIL memory allocations or other operations">
<conflict>MALLOC_DEBUG</conflict>
<support_level>core</support_level>
</member>
<member name="ADDRESS_SANITIZER" displayname="Address Sanitizer">

@ -20,10 +20,7 @@
#include "asterisk/autoconfig.h"
#include "asterisk/compat.h"
#if !defined(NO_MALLOC_DEBUG) && !defined(STANDALONE) && !defined(STANDALONE2)
#include "asterisk/astmm.h"
#endif
/* Default to allowing the umask or filesystem ACLs to determine actual file
* creation permissions

@ -17,13 +17,12 @@
*/
/*! \file
* \brief Asterisk memory usage debugging
* This file provides headers for MALLOC_DEBUG, a define used for tracking down
* memory leaks. It should never be \#included directly; always use the
* MALLOC_DEBUG definition in menuselect to activate those functions.
* \brief Asterisk memory management routines
*
* This file should never be \#included directly, it is included
* by asterisk.h.
*/
#ifdef __cplusplus
extern "C" {
#endif
@ -32,26 +31,45 @@ extern "C" {
#define _ASTERISK_ASTMM_H
/* IWYU pragma: private, include "asterisk.h" */
#if defined(MALLOC_DEBUG)
#if defined(MALLOC_DEBUG) && !defined(STANDALONE) && !defined(STANDALONE2)
#define __AST_DEBUG_MALLOC
void __ast_mm_init_phase_1(void);
void __ast_mm_init_phase_2(void);
#endif
void *ast_std_malloc(size_t size);
void *ast_std_calloc(size_t nmemb, size_t size);
void *ast_std_malloc(size_t size) attribute_malloc;
void *ast_std_calloc(size_t nmemb, size_t size) attribute_malloc;
void *ast_std_realloc(void *ptr, size_t size);
void ast_std_free(void *ptr);
/*!
* \brief free() wrapper
*
* ast_free_ptr should be used when a function pointer for free() needs to be passed
* as the argument to a function. Otherwise, astmm will cause seg faults.
*/
void ast_free_ptr(void *ptr);
void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func);
void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void *__ast_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void __ast_free(void *ptr, const char *file, int lineno, const char *func);
void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);
char *__ast_strdup(const char *s, const char *file, int lineno, const char *func) attribute_malloc;
char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func) attribute_malloc;
int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
__attribute__((format(printf, 5, 6)));
int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
__attribute__((format(printf, 2, 0)));
/* The __ast_repl functions should not used from Asterisk sources, they are exposed
* for use by ASTMM_REDIRECT and bundled pjproject. */
void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);
char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func);
char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func);
char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func) attribute_malloc;
char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func) attribute_malloc;
int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
__attribute__((format(printf, 5, 6)));
int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
@ -123,22 +141,22 @@ int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char
#if ASTMM_LIBC == ASTMM_REDIRECT
/* Redefine libc functions to our own versions */
#define calloc(a, b) \
__ast_repl_calloc(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define malloc(a) \
__ast_repl_malloc(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free(a) \
__ast_free(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define realloc(a, b) \
__ast_repl_realloc(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strdup(a) \
__ast_repl_strdup(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strndup(a, b) \
__ast_repl_strndup(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define asprintf(a, b, c...) \
__ast_repl_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, b, c)
#define vasprintf(a, b, c) \
__ast_repl_vasprintf(a, b, c, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define calloc(nmemb, size) \
__ast_repl_calloc(nmemb, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define malloc(size) \
__ast_repl_malloc(size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free(ptr) \
__ast_free(ptr, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define realloc(ptr, size) \
__ast_repl_realloc(ptr, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strdup(s) \
__ast_repl_strdup(s, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strndup(s, n) \
__ast_repl_strndup(s, n, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define asprintf(strp, format, args...) \
__ast_repl_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, strp, format, args)
#define vasprintf(strp, format, ap) \
__ast_repl_vasprintf(strp, format, ap, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#elif ASTMM_LIBC == ASTMM_BLOCK
@ -171,6 +189,132 @@ int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char
#define ast_free(a) \
__ast_free(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for malloc()
*
* ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The argument and return value are the same as malloc()
*/
#define ast_malloc(len) \
__ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for calloc()
*
* ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc(num, len) \
__ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for calloc() for use in cache pools
*
* ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails. When memory debugging is in use,
* the memory allocated by this function will be marked as 'cache' so it can be
* distinguished from normal memory allocations.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc_cache(num, len) \
__ast_calloc_cache((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for realloc()
*
* ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as realloc()
*/
#define ast_realloc(p, len) \
__ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for strdup()
*
* ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
* argument is provided, ast_strdup will return NULL without generating any
* kind of error log message.
*
* The argument and return value are the same as strdup()
*/
#define ast_strdup(str) \
__ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for strndup()
*
* ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
* string to duplicate. If a NULL argument is provided, ast_strdup will return
* NULL without generating any kind of error log message.
*
* The arguments and return value are the same as strndup()
*/
#define ast_strndup(str, len) \
__ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for asprintf()
*
* ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as asprintf()
*/
#define ast_asprintf(ret, fmt, ...) \
__ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
/*!
* \brief A wrapper for vasprintf()
*
* ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as vasprintf()
*/
#define ast_vasprintf(ret, fmt, ap) \
__ast_vasprintf((ret), (fmt), (ap), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
\brief call __builtin_alloca to ensure we get gcc builtin semantics
\param size The size of the buffer we want allocated
This macro will attempt to allocate memory from the stack. If it fails
you won't get a NULL returned, but a SEGFAULT if you're lucky.
*/
#define ast_alloca(size) __builtin_alloca(size)
#if !defined(ast_strdupa) && defined(__GNUC__)
/*!
* \brief duplicate a string in memory from the stack
* \param s The string to duplicate
*
* This macro will duplicate the given string. It returns a pointer to the stack
* allocatted memory for the new string.
*/
#define ast_strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen(__old) + 1; \
char *__new = __builtin_alloca(__len); \
memcpy (__new, __old, __len); \
__new; \
}))
#endif
#else
#error "NEVER INCLUDE astmm.h DIRECTLY!!"
#endif /* _ASTERISK_ASTMM_H */

@ -483,364 +483,6 @@ long int ast_random(void);
*/
#define ast_random_double() (((double)ast_random()) / RAND_MAX)
/*!
* \brief DEBUG_CHAOS returns failure randomly
*
* DEBUG_CHAOS_RETURN(failure); can be used to fake
* failure of functions such as memory allocation,
* for the purposes of testing failure handling.
*/
#ifdef DEBUG_CHAOS
#ifndef DEBUG_CHAOS_ALLOC_CHANCE
#define DEBUG_CHAOS_ALLOC_CHANCE 100000
#endif
/* Could #define DEBUG_CHAOS_ENABLE ast_fully_booted */
#ifndef DEBUG_CHAOS_ENABLE
#define DEBUG_CHAOS_ENABLE 1
#endif
#define DEBUG_CHAOS_RETURN(CHANCE, FAILURE) \
do { \
if ((DEBUG_CHAOS_ENABLE) && (ast_random() % CHANCE == 0)) { \
return FAILURE; \
} \
} while (0)
#else
#define DEBUG_CHAOS_RETURN(c,f)
#endif
#if !defined(NO_MALLOC_DEBUG) && !defined(STANDALONE) && !defined(STANDALONE2)
void *ast_std_malloc(size_t size);
void *ast_std_calloc(size_t nmemb, size_t size);
void *ast_std_realloc(void *ptr, size_t size);
void ast_std_free(void *ptr);
/*!
* \brief free() wrapper
*
* ast_free_ptr should be used when a function pointer for free() needs to be passed
* as the argument to a function. Otherwise, astmm will cause seg faults.
*/
void ast_free_ptr(void *ptr);
void __ast_free(void *ptr, const char *file, int lineno, const char *func);
#else
/*
* Need to defeat the MALLOC_DEBUG API when building the standalone utilities.
*/
#define ast_std_malloc malloc
#define ast_std_calloc calloc
#define ast_std_realloc realloc
#define ast_std_free free
#define ast_free_ptr free
#define ast_free free
#define __ast_repl_calloc(nmemb, size, file, lineno, func) \
calloc(nmemb, size)
#define __ast_repl_calloc_cache(nmemb, size, file, lineno, func) \
calloc(nmemb, size)
#define __ast_repl_malloc(size, file, lineno, func) \
malloc(size)
#define __ast_repl_realloc(ptr, size, file, lineno, func) \
realloc(ptr, size)
#define __ast_repl_strdup(s, file, lineno, func) \
strdup(s)
#define __ast_repl_strndup(s, n, file, lineno, func) \
strndup(s, n)
#define __ast_repl_vasprintf(strp, format, ap, file, lineno, func) \
vasprintf(strp, format, ap)
#endif
#if defined(AST_IN_CORE)
#define MALLOC_FAILURE_MSG \
ast_log_safe(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file)
#else
#define MALLOC_FAILURE_MSG \
ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file)
#endif
AST_INLINE_API(
void * attribute_malloc __ast_malloc(size_t len, const char *file, int lineno, const char *func),
{
void *p;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
p = __ast_repl_malloc(len, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
)
AST_INLINE_API(
void * attribute_malloc __ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
{
void *p;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
p = __ast_repl_calloc(num, len, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
)
AST_INLINE_API(
void * attribute_malloc __ast_calloc_cache(size_t num, size_t len, const char *file, int lineno, const char *func),
{
void *p;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
p = __ast_repl_calloc_cache(num, len, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
)
AST_INLINE_API(
void *__ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
{
void *newp;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
newp = __ast_repl_realloc(p, len, file, lineno, func);
if (!newp) {
MALLOC_FAILURE_MSG;
}
return newp;
}
)
AST_INLINE_API(
char * attribute_malloc __ast_strdup(const char *str, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
if (str) {
newstr = __ast_repl_strdup(str, file, lineno, func);
if (!newstr) {
MALLOC_FAILURE_MSG;
}
}
return newstr;
}
)
AST_INLINE_API(
char * attribute_malloc __ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
if (str) {
newstr = __ast_repl_strndup(str, len, file, lineno, func);
if (!newstr) {
MALLOC_FAILURE_MSG;
}
}
return newstr;
}
)
AST_INLINE_API(
__attribute__((format(printf, 5, 6)))
int __ast_asprintf(const char *file, int lineno, const char *func, char **ret, const char *fmt, ...),
{
int res;
va_list ap;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
va_start(ap, fmt);
res = __ast_repl_vasprintf(ret, fmt, ap, file, lineno, func);
if (res < 0) {
/*
* *ret is undefined so set to NULL to ensure it is
* initialized to something useful.
*/
*ret = NULL;
MALLOC_FAILURE_MSG;
}
va_end(ap);
return res;
}
)
AST_INLINE_API(
__attribute__((format(printf, 2, 0)))
int __ast_vasprintf(char **ret, const char *fmt, va_list ap, const char *file, int lineno, const char *func),
{
int res;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
res = __ast_repl_vasprintf(ret, fmt, ap, file, lineno, func);
if (res < 0) {
/*
* *ret is undefined so set to NULL to ensure it is
* initialized to something useful.
*/
*ret = NULL;
MALLOC_FAILURE_MSG;
}
return res;
}
)
/*!
* \brief A wrapper for malloc()
*
* ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The argument and return value are the same as malloc()
*/
#define ast_malloc(len) \
__ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for calloc()
*
* ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc(num, len) \
__ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for calloc() for use in cache pools
*
* ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails. When memory debugging is in use,
* the memory allocated by this function will be marked as 'cache' so it can be
* distinguished from normal memory allocations.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc_cache(num, len) \
__ast_calloc_cache((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for realloc()
*
* ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as realloc()
*/
#define ast_realloc(p, len) \
__ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for strdup()
*
* ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
* argument is provided, ast_strdup will return NULL without generating any
* kind of error log message.
*
* The argument and return value are the same as strdup()
*/
#define ast_strdup(str) \
__ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for strndup()
*
* ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
* string to duplicate. If a NULL argument is provided, ast_strdup will return
* NULL without generating any kind of error log message.
*
* The arguments and return value are the same as strndup()
*/
#define ast_strndup(str, len) \
__ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for asprintf()
*
* ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as asprintf()
*/
#define ast_asprintf(ret, fmt, ...) \
__ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
/*!
* \brief A wrapper for vasprintf()
*
* ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as vasprintf()
*/
#define ast_vasprintf(ret, fmt, ap) \
__ast_vasprintf((ret), (fmt), (ap), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
\brief call __builtin_alloca to ensure we get gcc builtin semantics
\param size The size of the buffer we want allocated
This macro will attempt to allocate memory from the stack. If it fails
you won't get a NULL returned, but a SEGFAULT if you're lucky.
*/
#define ast_alloca(size) __builtin_alloca(size)
#if !defined(ast_strdupa) && defined(__GNUC__)
/*!
* \brief duplicate a string in memory from the stack
* \param s The string to duplicate
*
* This macro will duplicate the given string. It returns a pointer to the stack
* allocatted memory for the new string.
*/
#define ast_strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen(__old) + 1; \
char *__new = __builtin_alloca(__len); \
memcpy (__new, __old, __len); \
__new; \
}))
#endif
/*!
* \brief Disable PMTU discovery on a socket
* \param sock The socket to manipulate

@ -31,6 +31,40 @@
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#include "asterisk/logger.h"
/*!
* \brief DEBUG_CHAOS returns failure randomly
*
* DEBUG_CHAOS_RETURN(failure); can be used to fake
* failure of functions such as memory allocation,
* for the purposes of testing failure handling.
*/
#ifdef DEBUG_CHAOS
#ifndef DEBUG_CHAOS_ALLOC_CHANCE
#define DEBUG_CHAOS_ALLOC_CHANCE 100000
#endif
/* Could #define DEBUG_CHAOS_ENABLE ast_fully_booted */
#ifndef DEBUG_CHAOS_ENABLE
#define DEBUG_CHAOS_ENABLE 1
#endif
#define DEBUG_CHAOS_RETURN(CHANCE, FAILURE) \
do { \
if ((DEBUG_CHAOS_ENABLE) && (ast_random() % CHANCE == 0)) { \
return FAILURE; \
} \
} while (0)
#else
#define DEBUG_CHAOS_RETURN(c,f)
#endif
#if defined(STANDALONE) || defined(STANDALONE2)
#define ast_log_safe ast_log
#endif
#define MALLOC_FAILURE_MSG \
ast_log_safe(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file)
#if defined(__AST_DEBUG_MALLOC)
#include "asterisk/paths.h" /* use ast_config_AST_LOG_DIR */
@ -191,6 +225,8 @@ static void *__ast_alloc_region(size_t size, const enum func_type which, const c
unsigned int *fence;
int hash;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
astmm_log("Memory Allocation Failure - '%d' bytes at %s %s() line %d\n",
(int) size, file, func, lineno);
@ -425,7 +461,7 @@ static void regions_check_all_fences(void)
ast_mutex_unlock(&reglock);
}
static void __ast_free_region(void *ptr, const char *file, int lineno, const char *func)
void __ast_free(void *ptr, const char *file, int lineno, const char *func)
{
struct ast_region *reg;
@ -466,7 +502,7 @@ void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno,
return ptr;
}
void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
static void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *ptr;
@ -491,11 +527,6 @@ void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *f
return ptr;
}
void __ast_free(void *ptr, const char *file, int lineno, const char *func)
{
__ast_free_region(ptr, file, lineno, func);
}
/*!
* \note reglock must be locked before calling.
*/
@ -538,7 +569,7 @@ void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, c
}
if (!size) {
__ast_free_region(ptr, file, lineno, func);
__ast_free(ptr, file, lineno, func);
return NULL;
}
@ -553,7 +584,7 @@ void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, c
/* Make sure that the added memory is not zero. */
memset(new_mem + len, MALLOC_FILLER, size - len);
}
__ast_free_region(ptr, file, lineno, func);
__ast_free(ptr, file, lineno, func);
} else {
/* Make sure that the malloced memory is not zero. */
memset(new_mem, MALLOC_FILLER, size);
@ -568,12 +599,10 @@ char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char
size_t len;
void *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0)))
if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0))) {
strcpy(ptr, s);
}
return ptr;
}
@ -583,10 +612,6 @@ char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno,
size_t len;
char *ptr;
if (!s) {
return NULL;
}
len = strnlen(s, n);
if ((ptr = __ast_alloc_region(len + 1, FUNC_STRNDUP, file, lineno, func, 0))) {
memcpy(ptr, s, len);
@ -601,18 +626,21 @@ int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **s
int size;
va_list ap, ap2;
char s;
void *ptr;
*strp = NULL;
va_start(ap, fmt);
va_copy(ap2, ap);
size = vsnprintf(&s, 1, fmt, ap2);
va_end(ap2);
if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) {
ptr = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0);
if (!ptr) {
/* As with stdlib *strp is undefined if allocation fails. */
va_end(ap);
return -1;
}
vsnprintf(*strp, size + 1, fmt, ap);
vsnprintf(ptr, size + 1, fmt, ap);
va_end(ap);
*strp = ptr;
return size;
}
@ -622,16 +650,18 @@ int __ast_repl_vasprintf(char **strp, const char *fmt, va_list ap, const char *f
int size;
va_list ap2;
char s;
void *ptr;
*strp = NULL;
va_copy(ap2, ap);
size = vsnprintf(&s, 1, fmt, ap2);
va_end(ap2);
if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) {
va_end(ap);
ptr = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0);
if (!ptr) {
/* As with stdlib *strp is undefined if allocation fails. */
return -1;
}
vsnprintf(*strp, size + 1, fmt, ap);
vsnprintf(ptr, size + 1, fmt, ap);
*strp = ptr;
return size;
}
@ -1522,16 +1552,22 @@ void __ast_mm_init_phase_2(void)
void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return calloc(nmemb, size);
}
void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
static void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return calloc(nmemb, size);
}
void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return malloc(size);
}
@ -1542,38 +1578,164 @@ void __ast_free(void *ptr, const char *file, int lineno, const char *func)
void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return realloc(ptr, size);
}
char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return strdup(s);
}
char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
return strndup(s, n);
}
int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
{
int res;
va_list ap;
int rc = 0;
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
va_start(ap, format);
rc = vasprintf(strp, format, ap);
res = vasprintf(strp, format, ap);
va_end(ap);
return rc;
return res;
}
int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
{
DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
return vasprintf(strp, format, ap);
}
#endif /* defined(__AST_DEBUG_MALLOC) */
void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *p;
p = __ast_repl_calloc(nmemb, size, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *p;
p = __ast_repl_calloc_cache(nmemb, size, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
{
void *p;
p = __ast_repl_malloc(size, file, lineno, func);
if (!p) {
MALLOC_FAILURE_MSG;
}
return p;
}
void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
{
void *newp;
newp = __ast_repl_realloc(ptr, size, file, lineno, func);
if (!newp) {
MALLOC_FAILURE_MSG;
}
return newp;
}
char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
{
char *newstr = NULL;
if (s) {
newstr = __ast_repl_strdup(s, file, lineno, func);
if (!newstr) {
MALLOC_FAILURE_MSG;
}
}
return newstr;
}
char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
{
char *newstr = NULL;
if (s) {
newstr = __ast_repl_strndup(s, n, file, lineno, func);
if (!newstr) {
MALLOC_FAILURE_MSG;
}
}
return newstr;
}
int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
{
int res;
va_list ap;
va_start(ap, format);
res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
if (res < 0) {
/*
* *strp is undefined so set to NULL to ensure it is
* initialized to something useful.
*/
*strp = NULL;
MALLOC_FAILURE_MSG;
}
va_end(ap);
return res;
}
int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
{
int res;
res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
if (res < 0) {
/*
* *strp is undefined so set to NULL to ensure it is
* initialized to something useful.
*/
*strp = NULL;
MALLOC_FAILURE_MSG;
}
return res;
}
void *ast_std_malloc(size_t size)
{
return malloc(size);

@ -25,14 +25,24 @@
extern "C" {
#endif
#ifndef attribute_malloc
#ifdef HAVE_ATTRIBUTE_malloc
/* HAVE_ATTRIBUTE_malloc is never defined from pjproject. This is here as a placeholder
* hopefully we can just use __attribute__((malloc)) unconditionally. */
#define attribute_malloc __attribute__((malloc))
#else
#define attribute_malloc
#endif
#endif
int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
__attribute__((format(printf, 5, 6)));
void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void __ast_free(void *ptr, const char *file, int lineno, const char *func);
void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func);
void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc;
void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);
char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func);
char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func);
char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func) attribute_malloc;
char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func) attribute_malloc;
int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
__attribute__((format(printf, 2, 0)));
@ -47,29 +57,29 @@ int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char
#undef vasprintf
/* Provide our own definitions */
#define asprintf(a, b, c...) \
__ast_repl_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, b, c)
#define asprintf(strp, format, args...) \
__ast_repl_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, strp, format, args)
#define calloc(a,b) \
__ast_repl_calloc(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define calloc(nmemb, size) \
__ast_repl_calloc(nmemb, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free(a) \
__ast_free(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free(ptr) \
__ast_free(ptr, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define malloc(a) \
__ast_repl_malloc(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define malloc(size) \
__ast_repl_malloc(size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define realloc(a,b) \
__ast_repl_realloc(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define realloc(ptr, size) \
__ast_repl_realloc(ptr, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strdup(a) \
__ast_repl_strdup(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strdup(s) \
__ast_repl_strdup(s, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strndup(a,b) \
__ast_repl_strndup(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strndup(s, n) \
__ast_repl_strndup(s, n, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define vasprintf(a,b,c) \
__ast_repl_vasprintf(a,b,c,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define vasprintf(strp, format, ap) \
__ast_repl_vasprintf(strp, format, ap, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#ifdef __cplusplus
}

1
utils/.gitignore vendored

@ -3,6 +3,7 @@ aelparse
aelparse.c
ast_expr2.c
ast_expr2f.c
astmm.c
astman
astcanary
astdb2bdb

@ -86,7 +86,7 @@ clean:
rm -f *.o $(ALL_UTILS) check_expr
rm -f .*.d
rm -f *.s *.i
rm -f md5.c strcompat.c ast_expr2.c ast_expr2.h ast_expr2f.c pbx_ael.c pval.c hashtab.c lock.c
rm -f astmm.c md5.c strcompat.c ast_expr2.c ast_expr2.h ast_expr2f.c pbx_ael.c pval.c hashtab.c lock.c
rm -f aelparse.c aelbison.c conf2ael
rm -f threadstorage.c
rm -f utils.c strings.c poll.c version.c sha1.c astobj2.c refcounter
@ -100,11 +100,14 @@ md5.c: $(ASTTOPDIR)/main/md5.c
astman: astman.o md5.o
astman: LIBS+=$(NEWT_LIB)
astman.o: _ASTCFLAGS+=-DNO_MALLOC_DEBUG
stereorize: stereorize.o frame.o
stereorize: LIBS+=-lm
astmm.c: $(ASTTOPDIR)/main/astmm.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
$(CMD_PREFIX) cp "$<" "$@"
hashtab.c: $(ASTTOPDIR)/main/hashtab.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
$(CMD_PREFIX) cp "$<" "$@"
@ -134,7 +137,7 @@ ast_expr2f.c: $(ASTTOPDIR)/main/ast_expr2f.c
$(CMD_PREFIX) cp "$<" "$@"
ast_expr2f.o: _ASTCFLAGS+=-I$(ASTTOPDIR)/main -Wno-unused
check_expr: check_expr.o ast_expr2.o ast_expr2f.o strcompat.o threadstorage.o clicompat.o
check_expr: check_expr.o ast_expr2.o ast_expr2f.o strcompat.o threadstorage.o clicompat.o astmm.o
aelbison.c: $(ASTTOPDIR)/res/ael/ael.tab.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
@ -162,7 +165,7 @@ aelparse.c: $(ASTTOPDIR)/res/ael/ael_lex.c
aelparse.o: _ASTCFLAGS+=-I$(ASTTOPDIR)/res -Wno-unused
aelparse: LIBS+=-lm
aelparse: aelparse.o aelbison.o pbx_ael.o hashtab.o lock.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o
aelparse: aelparse.o aelbison.o pbx_ael.o hashtab.o lock.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o astmm.o
threadstorage.c: $(ASTTOPDIR)/main/threadstorage.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
@ -171,15 +174,15 @@ threadstorage.c: $(ASTTOPDIR)/main/threadstorage.c
extconf.o: extconf.c
conf2ael: conf2ael.o ast_expr2f.o ast_expr2.o hashtab.o lock.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o strcompat.o
conf2ael: conf2ael.o ast_expr2f.o ast_expr2.o hashtab.o lock.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o strcompat.o astmm.o
check_expr2: $(ASTTOPDIR)/main/ast_expr2f.c $(ASTTOPDIR)/main/ast_expr2.c $(ASTTOPDIR)/main/ast_expr2.h
check_expr2: $(ASTTOPDIR)/main/ast_expr2f.c $(ASTTOPDIR)/main/ast_expr2.c $(ASTTOPDIR)/main/ast_expr2.h astmm.o
$(ECHO_PREFIX) echo " [CC] ast_expr2f.c -> ast_expr2fz.o"
$(CC) -g -c -I$(ASTTOPDIR)/include -DSTANDALONE $(ASTTOPDIR)/main/ast_expr2f.c -o ast_expr2fz.o
$(ECHO_PREFIX) echo " [CC] ast_expr2.c -> ast_expr2z.o"
$(CC) -g -c -I$(ASTTOPDIR)/include -DSTANDALONE2 $(ASTTOPDIR)/main/ast_expr2.c -o ast_expr2z.o
$(ECHO_PREFIX) echo " [LD] ast_expr2fz.o ast_expr2z.o -> check_expr2"
$(CC) -g -o check_expr2 ast_expr2fz.o ast_expr2z.o -lm
$(CC) -g -o check_expr2 ast_expr2fz.o ast_expr2z.o astmm.o -lm
$(ECHO_PREFIX) echo " [RM] ast_expr2fz.o ast_expr2z.o"
rm ast_expr2z.o ast_expr2fz.o
./check_expr2 expr2.testinput

@ -11,6 +11,7 @@
<support_level>extended</support_level>
***/
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#include <locale.h>

@ -26,6 +26,7 @@
<support_level>extended</support_level>
***/
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#include <newt.h>

@ -20,6 +20,7 @@
<support_level>extended</support_level>
***/
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#include "asterisk/ast_expr.h"

@ -27,6 +27,7 @@
<support_level>extended</support_level>
***/
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#include "asterisk/paths.h" /* CONFIG_DIR */

@ -43,7 +43,7 @@
<support_level>extended</support_level>
***/
#define ASTMM_LIBC ASTMM_REDIRECT
#define ASTMM_LIBC ASTMM_IGNORE
#include "asterisk.h"
#undef DEBUG_THREADS
@ -681,9 +681,6 @@ int ast_channel_trylock(struct ast_channel *chan);
/* from utils.h */
#define ast_free free
#define ast_free_ptr free
struct ast_flags { /* stolen from utils.h */
unsigned int flags;
};
@ -704,222 +701,6 @@ struct ast_flags { /* stolen from utils.h */
(p)->flags &= ~(flag); \
} while (0)
#define MALLOC_FAILURE_MSG \
ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
/*!
* \brief A wrapper for malloc()
*
* ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The argument and return value are the same as malloc()
*/
#define ast_malloc(len) \
__ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
void * attribute_malloc __ast_malloc(size_t len, const char *file, int lineno, const char *func),
{
void *p;
if (!(p = malloc(len)))
MALLOC_FAILURE_MSG;
return p;
}
)
/*!
* \brief A wrapper for calloc()
*
* ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc(num, len) \
__ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
void * attribute_malloc __ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
{
void *p;
if (!(p = calloc(num, len)))
MALLOC_FAILURE_MSG;
return p;
}
)
/*!
* \brief A wrapper for calloc() for use in cache pools
*
* ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
* message in the case that the allocation fails. When memory debugging is in use,
* the memory allocated by this function will be marked as 'cache' so it can be
* distinguished from normal memory allocations.
*
* The arguments and return value are the same as calloc()
*/
#define ast_calloc_cache(num, len) \
__ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief A wrapper for realloc()
*
* ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as realloc()
*/
#define ast_realloc(p, len) \
__ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
void *__ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
{
void *newp;
if (!(newp = realloc(p, len)))
MALLOC_FAILURE_MSG;
return newp;
}
)
/*!
* \brief A wrapper for strdup()
*
* ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
* argument is provided, ast_strdup will return NULL without generating any
* kind of error log message.
*
* The argument and return value are the same as strdup()
*/
#define ast_strdup(str) \
__ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
char * attribute_malloc __ast_strdup(const char *str, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
if (str) {
if (!(newstr = strdup(str)))
MALLOC_FAILURE_MSG;
}
return newstr;
}
)
/*!
* \brief A wrapper for strndup()
*
* ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
* string to duplicate. If a NULL argument is provided, ast_strdup will return
* NULL without generating any kind of error log message.
*
* The arguments and return value are the same as strndup()
*/
#define ast_strndup(str, len) \
__ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
char * attribute_malloc __ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
{
char *newstr = NULL;
if (str) {
if (!(newstr = strndup(str, len)))
MALLOC_FAILURE_MSG;
}
return newstr;
}
)
/*!
* \brief A wrapper for asprintf()
*
* ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as asprintf()
*/
#define ast_asprintf(ret, fmt, ...) \
__ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
AST_INLINE_API(
__attribute__((format(printf, 5, 6)))
int __ast_asprintf(const char *file, int lineno, const char *func, char **ret, const char *fmt, ...),
{
int res;
va_list ap;
va_start(ap, fmt);
if ((res = vasprintf(ret, fmt, ap)) == -1)
MALLOC_FAILURE_MSG;
va_end(ap);
return res;
}
)
/*!
* \brief A wrapper for vasprintf()
*
* ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
* message in the case that the allocation fails.
*
* The arguments and return value are the same as vasprintf()
*/
#define ast_vasprintf(ret, fmt, ap) \
__ast_vasprintf((ret), (fmt), (ap), __FILE__, __LINE__, __PRETTY_FUNCTION__)
AST_INLINE_API(
__attribute__((format(printf, 2, 0)))
int __ast_vasprintf(char **ret, const char *fmt, va_list ap, const char *file, int lineno, const char *func),
{
int res;
if ((res = vasprintf(ret, fmt, ap)) == -1)
MALLOC_FAILURE_MSG;
return res;
}
)
#if !defined(ast_strdupa) && defined(__GNUC__)
/*!
\brief duplicate a string in memory from the stack
\param s The string to duplicate
This macro will duplicate the given string. It returns a pointer to the stack
allocatted memory for the new string.
*/
#define ast_strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen(__old) + 1; \
char *__new = __builtin_alloca(__len); \
memcpy (__new, __old, __len); \
__new; \
}))
#endif
/* from config.c */
#define MAX_NESTED_COMMENTS 128

Loading…
Cancel
Save