From 209c5ba4657b641bf261da7ac9ce7d3f809109c2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Feb 2021 05:33:02 +0100 Subject: larger map, stats reload fix, code format --- docs/Changelog.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index e9efdf38..f2041917 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,6 +26,8 @@ sending a mail to . `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) + - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now + reloaded and used, thanks to Vimal Joseph for this PR! - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map -- cgit 1.4.1 From 267b085f80074e61bdacf1e85e99014b6b2cdad2 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 10 Feb 2021 15:15:16 +0100 Subject: dlmalloc only for non glibc qasan and AFL_QEMU_FORCE_DFL --- docs/env_variables.md | 6 + qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/libqasan/dlmalloc.c | 4769 ++++++++++++++++------------------------- qemu_mode/libqasan/malloc.c | 147 +- qemu_mode/qemuafl | 2 +- 5 files changed, 2003 insertions(+), 2923 deletions(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index 4c3b1cfb..ab56c178 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -514,6 +514,12 @@ The QEMU wrapper used to instrument binary-only code supports several settings: stack pointer in which QEMU can find the return address when `start addr` is hit. + - With `AFL_USE_QASAN` you can enable QEMU AddressSanitizer for dynamically + linked binaries. + + - With `AFL_QEMU_FORCE_DFL` you force QEMU to ignore the registered singal + handlers of the target. + ## 6) Settings for afl-cmin The corpus minimization script offers very little customization: diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 97184973..d9f0ec33 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -6ab6bf28de +47722f64e4 diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index 3c7dcea8..7e3cb159 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -1,3 +1,7 @@ +#include + +#ifndef __GLIBC__ + /* This is a version (aka dlmalloc) of malloc/free/realloc written by Doug Lea and released to the public domain, as explained at @@ -203,12 +207,9 @@ mspaces as thread-locals. For example: static __thread mspace tlms = 0; void* tlmalloc(size_t bytes) { - if (tlms == 0) tlms = create_mspace(0, 0); return mspace_malloc(tlms, bytes); - } - void tlfree(void* mem) { mspace_free(tlms, mem); } Unless FOOTERS is defined, each mspace is completely independent. @@ -528,198 +529,197 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP /* Version identifier to allow people to support multiple versions */ #ifndef DLMALLOC_VERSION - #define DLMALLOC_VERSION 20806 -#endif /* DLMALLOC_VERSION */ +#define DLMALLOC_VERSION 20806 +#endif /* DLMALLOC_VERSION */ #ifndef DLMALLOC_EXPORT - #define DLMALLOC_EXPORT extern +#define DLMALLOC_EXPORT extern #endif #ifndef WIN32 - #ifdef _WIN32 - #define WIN32 1 - #endif /* _WIN32 */ - #ifdef _WIN32_WCE - #define LACKS_FCNTL_H - #define WIN32 1 - #endif /* _WIN32_WCE */ -#endif /* WIN32 */ +#ifdef _WIN32 +#define WIN32 1 +#endif /* _WIN32 */ +#ifdef _WIN32_WCE +#define LACKS_FCNTL_H +#define WIN32 1 +#endif /* _WIN32_WCE */ +#endif /* WIN32 */ #ifdef WIN32 - #define WIN32_LEAN_AND_MEAN - #include - #include - #define HAVE_MMAP 1 - #define HAVE_MORECORE 0 - #define LACKS_UNISTD_H - #define LACKS_SYS_PARAM_H - #define LACKS_SYS_MMAN_H - #define LACKS_STRING_H - #define LACKS_STRINGS_H - #define LACKS_SYS_TYPES_H - #define LACKS_ERRNO_H - #define LACKS_SCHED_H - #ifndef MALLOC_FAILURE_ACTION - #define MALLOC_FAILURE_ACTION - #endif /* MALLOC_FAILURE_ACTION */ - #ifndef MMAP_CLEARS - #ifdef _WIN32_WCE /* WINCE reportedly does not clear */ - #define MMAP_CLEARS 0 - #else - #define MMAP_CLEARS 1 - #endif /* _WIN32_WCE */ - #endif /*MMAP_CLEARS */ -#endif /* WIN32 */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#define HAVE_MMAP 1 +#define HAVE_MORECORE 0 +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRING_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_ERRNO_H +#define LACKS_SCHED_H +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef MMAP_CLEARS +#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ +#define MMAP_CLEARS 0 +#else +#define MMAP_CLEARS 1 +#endif /* _WIN32_WCE */ +#endif /*MMAP_CLEARS */ +#endif /* WIN32 */ #if defined(DARWIN) || defined(_DARWIN) - /* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ - #ifndef HAVE_MORECORE - #define HAVE_MORECORE 0 - #define HAVE_MMAP 1 - /* OSX allocators provide 16 byte alignment */ - #ifndef MALLOC_ALIGNMENT - #define MALLOC_ALIGNMENT ((size_t)16U) - #endif - #endif /* HAVE_MORECORE */ -#endif /* DARWIN */ +/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ +#ifndef HAVE_MORECORE +#define HAVE_MORECORE 0 +#define HAVE_MMAP 1 +/* OSX allocators provide 16 byte alignment */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)16U) +#endif +#endif /* HAVE_MORECORE */ +#endif /* DARWIN */ #ifndef LACKS_SYS_TYPES_H - #include /* For size_t */ -#endif /* LACKS_SYS_TYPES_H */ +#include /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ /* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ - #define USE_LOCKS \ - ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ - (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) -#endif /* USE_LOCKS */ - -#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ - #if ((defined(__GNUC__) && \ - ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ - defined(__i386__) || defined(__x86_64__))) || \ - (defined(_MSC_VER) && _MSC_VER >= 1310)) - #ifndef USE_SPIN_LOCKS - #define USE_SPIN_LOCKS 1 - #endif /* USE_SPIN_LOCKS */ - #elif USE_SPIN_LOCKS - #error "USE_SPIN_LOCKS defined without implementation" - #endif /* ... locks available... */ +#define MAX_SIZE_T (~(size_t)0) + +#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ + (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#endif /* USE_LOCKS */ + +#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ +#if ((defined(__GNUC__) && \ + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ + defined(__i386__) || defined(__x86_64__))) || \ + (defined(_MSC_VER) && _MSC_VER>=1310)) +#ifndef USE_SPIN_LOCKS +#define USE_SPIN_LOCKS 1 +#endif /* USE_SPIN_LOCKS */ +#elif USE_SPIN_LOCKS +#error "USE_SPIN_LOCKS defined without implementation" +#endif /* ... locks available... */ #elif !defined(USE_SPIN_LOCKS) - #define USE_SPIN_LOCKS 0 -#endif /* USE_LOCKS */ +#define USE_SPIN_LOCKS 0 +#endif /* USE_LOCKS */ #ifndef ONLY_MSPACES - #define ONLY_MSPACES 0 -#endif /* ONLY_MSPACES */ +#define ONLY_MSPACES 0 +#endif /* ONLY_MSPACES */ #ifndef MSPACES - #if ONLY_MSPACES - #define MSPACES 1 - #else /* ONLY_MSPACES */ - #define MSPACES 0 - #endif /* ONLY_MSPACES */ -#endif /* MSPACES */ +#if ONLY_MSPACES +#define MSPACES 1 +#else /* ONLY_MSPACES */ +#define MSPACES 0 +#endif /* ONLY_MSPACES */ +#endif /* MSPACES */ #ifndef MALLOC_ALIGNMENT - #define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *))) -#endif /* MALLOC_ALIGNMENT */ +#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *))) +#endif /* MALLOC_ALIGNMENT */ #ifndef FOOTERS - #define FOOTERS 0 -#endif /* FOOTERS */ +#define FOOTERS 0 +#endif /* FOOTERS */ #ifndef ABORT - #define ABORT abort() -#endif /* ABORT */ +#define ABORT abort() +#endif /* ABORT */ #ifndef ABORT_ON_ASSERT_FAILURE - #define ABORT_ON_ASSERT_FAILURE 1 -#endif /* ABORT_ON_ASSERT_FAILURE */ +#define ABORT_ON_ASSERT_FAILURE 1 +#endif /* ABORT_ON_ASSERT_FAILURE */ #ifndef PROCEED_ON_ERROR - #define PROCEED_ON_ERROR 0 -#endif /* PROCEED_ON_ERROR */ +#define PROCEED_ON_ERROR 0 +#endif /* PROCEED_ON_ERROR */ #ifndef INSECURE - #define INSECURE 0 -#endif /* INSECURE */ +#define INSECURE 0 +#endif /* INSECURE */ #ifndef MALLOC_INSPECT_ALL - #define MALLOC_INSPECT_ALL 0 -#endif /* MALLOC_INSPECT_ALL */ +#define MALLOC_INSPECT_ALL 0 +#endif /* MALLOC_INSPECT_ALL */ #ifndef HAVE_MMAP - #define HAVE_MMAP 1 -#endif /* HAVE_MMAP */ +#define HAVE_MMAP 1 +#endif /* HAVE_MMAP */ #ifndef MMAP_CLEARS - #define MMAP_CLEARS 1 -#endif /* MMAP_CLEARS */ +#define MMAP_CLEARS 1 +#endif /* MMAP_CLEARS */ #ifndef HAVE_MREMAP - #ifdef linux - #define HAVE_MREMAP 1 - #define _GNU_SOURCE /* Turns on mremap() definition */ - #else /* linux */ - #define HAVE_MREMAP 0 - #endif /* linux */ -#endif /* HAVE_MREMAP */ +#ifdef linux +#define HAVE_MREMAP 1 +#define _GNU_SOURCE /* Turns on mremap() definition */ +#else /* linux */ +#define HAVE_MREMAP 0 +#endif /* linux */ +#endif /* HAVE_MREMAP */ #ifndef MALLOC_FAILURE_ACTION - #define MALLOC_FAILURE_ACTION errno = ENOMEM; -#endif /* MALLOC_FAILURE_ACTION */ +#define MALLOC_FAILURE_ACTION errno = ENOMEM; +#endif /* MALLOC_FAILURE_ACTION */ #ifndef HAVE_MORECORE - #if ONLY_MSPACES - #define HAVE_MORECORE 0 - #else /* ONLY_MSPACES */ - #define HAVE_MORECORE 1 - #endif /* ONLY_MSPACES */ -#endif /* HAVE_MORECORE */ +#if ONLY_MSPACES +#define HAVE_MORECORE 0 +#else /* ONLY_MSPACES */ +#define HAVE_MORECORE 1 +#endif /* ONLY_MSPACES */ +#endif /* HAVE_MORECORE */ #if !HAVE_MORECORE - #define MORECORE_CONTIGUOUS 0 -#else /* !HAVE_MORECORE */ - #define MORECORE_DEFAULT sbrk - #ifndef MORECORE_CONTIGUOUS - #define MORECORE_CONTIGUOUS 1 - #endif /* MORECORE_CONTIGUOUS */ -#endif /* HAVE_MORECORE */ +#define MORECORE_CONTIGUOUS 0 +#else /* !HAVE_MORECORE */ +#define MORECORE_DEFAULT sbrk +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif /* MORECORE_CONTIGUOUS */ +#endif /* HAVE_MORECORE */ #ifndef DEFAULT_GRANULARITY - #if (MORECORE_CONTIGUOUS || defined(WIN32)) - #define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ - #else /* MORECORE_CONTIGUOUS */ - #define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) - #endif /* MORECORE_CONTIGUOUS */ -#endif /* DEFAULT_GRANULARITY */ +#if (MORECORE_CONTIGUOUS || defined(WIN32)) +#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ +#else /* MORECORE_CONTIGUOUS */ +#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) +#endif /* MORECORE_CONTIGUOUS */ +#endif /* DEFAULT_GRANULARITY */ #ifndef DEFAULT_TRIM_THRESHOLD - #ifndef MORECORE_CANNOT_TRIM - #define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) - #else /* MORECORE_CANNOT_TRIM */ - #define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T - #endif /* MORECORE_CANNOT_TRIM */ -#endif /* DEFAULT_TRIM_THRESHOLD */ +#ifndef MORECORE_CANNOT_TRIM +#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) +#else /* MORECORE_CANNOT_TRIM */ +#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T +#endif /* MORECORE_CANNOT_TRIM */ +#endif /* DEFAULT_TRIM_THRESHOLD */ #ifndef DEFAULT_MMAP_THRESHOLD - #if HAVE_MMAP - #define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) - #else /* HAVE_MMAP */ - #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T - #endif /* HAVE_MMAP */ -#endif /* DEFAULT_MMAP_THRESHOLD */ +#if HAVE_MMAP +#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) +#else /* HAVE_MMAP */ +#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* DEFAULT_MMAP_THRESHOLD */ #ifndef MAX_RELEASE_CHECK_RATE - #if HAVE_MMAP - #define MAX_RELEASE_CHECK_RATE 4095 - #else - #define MAX_RELEASE_CHECK_RATE MAX_SIZE_T - #endif /* HAVE_MMAP */ -#endif /* MAX_RELEASE_CHECK_RATE */ +#if HAVE_MMAP +#define MAX_RELEASE_CHECK_RATE 4095 +#else +#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* MAX_RELEASE_CHECK_RATE */ #ifndef USE_BUILTIN_FFS - #define USE_BUILTIN_FFS 0 -#endif /* USE_BUILTIN_FFS */ +#define USE_BUILTIN_FFS 0 +#endif /* USE_BUILTIN_FFS */ #ifndef USE_DEV_RANDOM - #define USE_DEV_RANDOM 0 -#endif /* USE_DEV_RANDOM */ +#define USE_DEV_RANDOM 0 +#endif /* USE_DEV_RANDOM */ #ifndef NO_MALLINFO - #define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ +#define NO_MALLINFO 0 +#endif /* NO_MALLINFO */ #ifndef MALLINFO_FIELD_TYPE - #define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ +#define MALLINFO_FIELD_TYPE size_t +#endif /* MALLINFO_FIELD_TYPE */ #ifndef NO_MALLOC_STATS - #define NO_MALLOC_STATS 0 -#endif /* NO_MALLOC_STATS */ +#define NO_MALLOC_STATS 0 +#endif /* NO_MALLOC_STATS */ #ifndef NO_SEGMENT_TRAVERSAL - #define NO_SEGMENT_TRAVERSAL 0 -#endif /* NO_SEGMENT_TRAVERSAL */ +#define NO_SEGMENT_TRAVERSAL 0 +#endif /* NO_SEGMENT_TRAVERSAL */ /* mallopt tuning options. SVID/XPG defines four standard parameter @@ -731,9 +731,9 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #undef M_TRIM_THRESHOLD #undef M_GRANULARITY #undef M_MMAP_THRESHOLD -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) +#define M_TRIM_THRESHOLD (-1) +#define M_GRANULARITY (-2) +#define M_MMAP_THRESHOLD (-3) /* ------------------------ Mallinfo declarations ------------------------ */ @@ -762,32 +762,28 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP /* #define HAVE_USR_INCLUDE_MALLOC_H */ - #ifdef HAVE_USR_INCLUDE_MALLOC_H - #include "/usr/include/malloc.h" - #else /* HAVE_USR_INCLUDE_MALLOC_H */ - #ifndef STRUCT_MALLINFO_DECLARED - /* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is - * defined */ - #define _STRUCT_MALLINFO - #define STRUCT_MALLINFO_DECLARED 1 +#ifdef HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else /* HAVE_USR_INCLUDE_MALLOC_H */ +#ifndef STRUCT_MALLINFO_DECLARED +/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ +#define _STRUCT_MALLINFO +#define STRUCT_MALLINFO_DECLARED 1 struct mallinfo { - - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ - + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ }; - - #endif /* STRUCT_MALLINFO_DECLARED */ - #endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* NO_MALLINFO */ +#endif /* STRUCT_MALLINFO_DECLARED */ +#endif /* HAVE_USR_INCLUDE_MALLOC_H */ +#endif /* NO_MALLINFO */ /* Try to persuade compilers to inline. The most critical functions for @@ -796,14 +792,14 @@ struct mallinfo { #ifndef FORCEINLINE #if defined(__GNUC__) - #define FORCEINLINE __inline __attribute__((always_inline)) +#define FORCEINLINE __inline __attribute__ ((always_inline)) #elif defined(_MSC_VER) #define FORCEINLINE __forceinline #endif #endif #ifndef NOINLINE #if defined(__GNUC__) - #define NOINLINE __attribute__((noinline)) + #define NOINLINE __attribute__ ((noinline)) #elif defined(_MSC_VER) #define NOINLINE __declspec(noinline) #else @@ -813,43 +809,42 @@ struct mallinfo { #ifdef __cplusplus extern "C" { - - #ifndef FORCEINLINE - #define FORCEINLINE inline - #endif -#endif /* __cplusplus */ #ifndef FORCEINLINE - #define FORCEINLINE + #define FORCEINLINE inline +#endif +#endif /* __cplusplus */ +#ifndef FORCEINLINE + #define FORCEINLINE #endif #if !ONLY_MSPACES /* ------------------- Declarations of public routines ------------------- */ - #ifndef USE_DL_PREFIX - #define dlcalloc calloc - #define dlfree free - #define dlmalloc malloc - #define dlmemalign memalign - #define dlposix_memalign posix_memalign - #define dlrealloc realloc - #define dlrealloc_in_place realloc_in_place - #define dlvalloc valloc - #define dlpvalloc pvalloc - #define dlmallinfo mallinfo - #define dlmallopt mallopt - #define dlmalloc_trim malloc_trim - #define dlmalloc_stats malloc_stats - #define dlmalloc_usable_size malloc_usable_size - #define dlmalloc_footprint malloc_footprint - #define dlmalloc_max_footprint malloc_max_footprint - #define dlmalloc_footprint_limit malloc_footprint_limit - #define dlmalloc_set_footprint_limit malloc_set_footprint_limit - #define dlmalloc_inspect_all malloc_inspect_all - #define dlindependent_calloc independent_calloc - #define dlindependent_comalloc independent_comalloc - #define dlbulk_free bulk_free - #endif /* USE_DL_PREFIX */ +#ifndef USE_DL_PREFIX +#define dlcalloc calloc +#define dlfree free +#define dlmalloc malloc +#define dlmemalign memalign +#define dlposix_memalign posix_memalign +#define dlrealloc realloc +#define dlrealloc_in_place realloc_in_place +#define dlvalloc valloc +#define dlpvalloc pvalloc +#define dlmallinfo mallinfo +#define dlmallopt mallopt +#define dlmalloc_trim malloc_trim +#define dlmalloc_stats malloc_stats +#define dlmalloc_usable_size malloc_usable_size +#define dlmalloc_footprint malloc_footprint +#define dlmalloc_max_footprint malloc_max_footprint +#define dlmalloc_footprint_limit malloc_footprint_limit +#define dlmalloc_set_footprint_limit malloc_set_footprint_limit +#define dlmalloc_inspect_all malloc_inspect_all +#define dlindependent_calloc independent_calloc +#define dlindependent_comalloc independent_comalloc +#define dlbulk_free bulk_free +#endif /* USE_DL_PREFIX */ /* malloc(size_t n) @@ -865,7 +860,7 @@ extern "C" { maximum supported value of n differs across systems, but is in all cases less than the maximum representable value of a size_t. */ -DLMALLOC_EXPORT void *dlmalloc(size_t); +DLMALLOC_EXPORT void* dlmalloc(size_t); /* free(void* p) @@ -874,14 +869,14 @@ DLMALLOC_EXPORT void *dlmalloc(size_t); It has no effect if p is null. If p was not malloced or already freed, free(p) will by default cause the current program to abort. */ -DLMALLOC_EXPORT void dlfree(void *); +DLMALLOC_EXPORT void dlfree(void*); /* calloc(size_t n_elements, size_t element_size); Returns a pointer to n_elements * element_size bytes, with all locations set to zero. */ -DLMALLOC_EXPORT void *dlcalloc(size_t, size_t); +DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); /* realloc(void* p, size_t n) @@ -905,7 +900,7 @@ DLMALLOC_EXPORT void *dlcalloc(size_t, size_t); The old unix realloc convention of allowing the last-free'd chunk to be used as an argument to realloc is not supported. */ -DLMALLOC_EXPORT void *dlrealloc(void *, size_t); +DLMALLOC_EXPORT void* dlrealloc(void*, size_t); /* realloc_in_place(void* p, size_t n) @@ -920,7 +915,7 @@ DLMALLOC_EXPORT void *dlrealloc(void *, size_t); Returns p if successful; otherwise null. */ -DLMALLOC_EXPORT void *dlrealloc_in_place(void *, size_t); +DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); /* memalign(size_t alignment, size_t n); @@ -934,7 +929,7 @@ DLMALLOC_EXPORT void *dlrealloc_in_place(void *, size_t); Overreliance on memalign is a sure way to fragment space. */ -DLMALLOC_EXPORT void *dlmemalign(size_t, size_t); +DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); /* int posix_memalign(void** pp, size_t alignment, size_t n); @@ -944,14 +939,14 @@ DLMALLOC_EXPORT void *dlmemalign(size_t, size_t); returns EINVAL if the alignment is not a power of two (3) fails and returns ENOMEM if memory cannot be allocated. */ -DLMALLOC_EXPORT int dlposix_memalign(void **, size_t, size_t); +DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); /* valloc(size_t n); Equivalent to memalign(pagesize, n), where pagesize is the page size of the system. If the pagesize is unknown, 4096 is used. */ -DLMALLOC_EXPORT void *dlvalloc(size_t); +DLMALLOC_EXPORT void* dlvalloc(size_t); /* mallopt(int parameter_number, int parameter_value) @@ -1026,7 +1021,7 @@ DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); */ DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); - #if MALLOC_INSPECT_ALL +#if MALLOC_INSPECT_ALL /* malloc_inspect_all(void(*handler)(void *start, void *end, @@ -1048,23 +1043,19 @@ DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); than 1000, you could write: static int count = 0; void count_chunks(void* start, void* end, size_t used, void* arg) { - if (used >= 1000) ++count; - } - then: malloc_inspect_all(count_chunks, NULL); malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. */ -DLMALLOC_EXPORT void dlmalloc_inspect_all(void (*handler)(void *, void *, - size_t, void *), - void *arg); +DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), + void* arg); - #endif /* MALLOC_INSPECT_ALL */ +#endif /* MALLOC_INSPECT_ALL */ - #if !NO_MALLINFO +#if !NO_MALLINFO /* mallinfo() Returns (by copy) a struct containing various summary statistics: @@ -1088,7 +1079,7 @@ DLMALLOC_EXPORT void dlmalloc_inspect_all(void (*handler)(void *, void *, thus be inaccurate. */ DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); - #endif /* NO_MALLINFO */ +#endif /* NO_MALLINFO */ /* independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); @@ -1126,7 +1117,6 @@ DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); struct Node { int item; struct Node* next; }; struct Node* build_list() { - struct Node** pool; int n = read_number_of_nodes_needed(); if (n <= 0) return 0; @@ -1138,11 +1128,9 @@ DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); pool[i]->next = pool[i+1]; free(pool); // Can now free the array (or not, if it is needed later) return first; - } - */ -DLMALLOC_EXPORT void **dlindependent_calloc(size_t, size_t, void **); +DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); /* independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); @@ -1181,7 +1169,6 @@ DLMALLOC_EXPORT void **dlindependent_calloc(size_t, size_t, void **); struct Foot { ... } void send_message(char* msg) { - int msglen = strlen(msg); size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; void* chunks[3]; @@ -1191,7 +1178,6 @@ DLMALLOC_EXPORT void **dlindependent_calloc(size_t, size_t, void **); char* body = (char*)(chunks[1]); struct Foot* foot = (struct Foot*)(chunks[2]); // ... - } In general though, independent_comalloc is worth using only for @@ -1202,7 +1188,7 @@ DLMALLOC_EXPORT void **dlindependent_calloc(size_t, size_t, void **); since it cannot reuse existing noncontiguous small chunks that might be available for some of the elements. */ -DLMALLOC_EXPORT void **dlindependent_comalloc(size_t, size_t *, void **); +DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); /* bulk_free(void* array[], size_t n_elements) @@ -1213,14 +1199,14 @@ DLMALLOC_EXPORT void **dlindependent_comalloc(size_t, size_t *, void **); is returned. For large arrays of pointers with poor locality, it may be worthwhile to sort this array before calling bulk_free. */ -DLMALLOC_EXPORT size_t dlbulk_free(void **, size_t n_elements); +DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); /* pvalloc(size_t n); Equivalent to valloc(minimum-page-that-holds(n)), that is, round up n to nearest pagesize. */ -DLMALLOC_EXPORT void *dlpvalloc(size_t); +DLMALLOC_EXPORT void* dlpvalloc(size_t); /* malloc_trim(size_t pad); @@ -1243,7 +1229,7 @@ DLMALLOC_EXPORT void *dlpvalloc(size_t); Malloc_trim returns 1 if it actually released any memory, else 0. */ -DLMALLOC_EXPORT int dlmalloc_trim(size_t); +DLMALLOC_EXPORT int dlmalloc_trim(size_t); /* malloc_stats(); @@ -1264,7 +1250,7 @@ DLMALLOC_EXPORT int dlmalloc_trim(size_t); malloc_stats prints only the most commonly interesting statistics. More information can be obtained by calling mallinfo. */ -DLMALLOC_EXPORT void dlmalloc_stats(void); +DLMALLOC_EXPORT void dlmalloc_stats(void); /* malloc_usable_size(void* p); @@ -1280,9 +1266,9 @@ DLMALLOC_EXPORT void dlmalloc_stats(void); p = malloc(n); assert(malloc_usable_size(p) >= 256); */ -size_t dlmalloc_usable_size(void *); +size_t dlmalloc_usable_size(void*); -#endif /* ONLY_MSPACES */ +#endif /* ONLY_MSPACES */ #if MSPACES @@ -1290,7 +1276,7 @@ size_t dlmalloc_usable_size(void *); mspace is an opaque type representing an independent region of space that supports mspace_malloc, etc. */ -typedef void *mspace; +typedef void* mspace; /* create_mspace creates and returns a new independent space with the @@ -1322,8 +1308,7 @@ DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); Destroying this space will deallocate all additionally allocated space (if possible) but not the initial base. */ -DLMALLOC_EXPORT mspace create_mspace_with_base(void *base, size_t capacity, - int locked); +DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); /* mspace_track_large_chunks controls whether requests for large chunks @@ -1338,11 +1323,12 @@ DLMALLOC_EXPORT mspace create_mspace_with_base(void *base, size_t capacity, */ DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); + /* mspace_malloc behaves as malloc, but operates within the given space. */ -DLMALLOC_EXPORT void *mspace_malloc(mspace msp, size_t bytes); +DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); /* mspace_free behaves as free, but operates within @@ -1352,7 +1338,7 @@ DLMALLOC_EXPORT void *mspace_malloc(mspace msp, size_t bytes); free may be called instead of mspace_free because freed chunks from any space are handled by their originating spaces. */ -DLMALLOC_EXPORT void mspace_free(mspace msp, void *mem); +DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); /* mspace_realloc behaves as realloc, but operates within @@ -1363,38 +1349,33 @@ DLMALLOC_EXPORT void mspace_free(mspace msp, void *mem); realloced chunks from any space are handled by their originating spaces. */ -DLMALLOC_EXPORT void *mspace_realloc(mspace msp, void *mem, size_t newsize); +DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); /* mspace_calloc behaves as calloc, but operates within the given space. */ -DLMALLOC_EXPORT void *mspace_calloc(mspace msp, size_t n_elements, - size_t elem_size); +DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); /* mspace_memalign behaves as memalign, but operates within the given space. */ -DLMALLOC_EXPORT void *mspace_memalign(mspace msp, size_t alignment, - size_t bytes); +DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); /* mspace_independent_calloc behaves as independent_calloc, but operates within the given space. */ -DLMALLOC_EXPORT void **mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, - void * chunks[]); +DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]); /* mspace_independent_comalloc behaves as independent_comalloc, but operates within the given space. */ -DLMALLOC_EXPORT void **mspace_independent_comalloc(mspace msp, - size_t n_elements, - size_t sizes[], - void * chunks[]); +DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]); /* mspace_footprint() returns the number of bytes obtained from the @@ -1408,18 +1389,19 @@ DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); */ DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); - #if !NO_MALLINFO + +#if !NO_MALLINFO /* mspace_mallinfo behaves as mallinfo, but reports properties of the given space. */ DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); - #endif /* NO_MALLINFO */ +#endif /* NO_MALLINFO */ /* malloc_usable_size(void* p) behaves the same as malloc_usable_size; */ -DLMALLOC_EXPORT size_t mspace_usable_size(const void *mem); +DLMALLOC_EXPORT size_t mspace_usable_size(const void* mem); /* mspace_malloc_stats behaves as malloc_stats, but reports @@ -1438,13 +1420,11 @@ DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); */ DLMALLOC_EXPORT int mspace_mallopt(int, int); -#endif /* MSPACES */ +#endif /* MSPACES */ #ifdef __cplusplus - -} /* end of extern "C" */ - -#endif /* __cplusplus */ +} /* end of extern "C" */ +#endif /* __cplusplus */ /* ======================================================================== @@ -1459,207 +1439,195 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int); /*------------------------------ internal #includes ---------------------- */ #ifdef _MSC_VER - #pragma warning(disable : 4146) /* no "unsigned" warnings */ -#endif /* _MSC_VER */ +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ +#endif /* _MSC_VER */ #if !NO_MALLOC_STATS - #include /* for printing in malloc_stats */ -#endif /* NO_MALLOC_STATS */ +#include /* for printing in malloc_stats */ +#endif /* NO_MALLOC_STATS */ #ifndef LACKS_ERRNO_H - #include /* for MALLOC_FAILURE_ACTION */ -#endif /* LACKS_ERRNO_H */ +#include /* for MALLOC_FAILURE_ACTION */ +#endif /* LACKS_ERRNO_H */ #ifdef DEBUG - #if ABORT_ON_ASSERT_FAILURE - #undef assert - #define assert(x) \ - if (!(x)) ABORT - #else /* ABORT_ON_ASSERT_FAILURE */ - #include - #endif /* ABORT_ON_ASSERT_FAILURE */ -#else /* DEBUG */ - #ifndef assert - #define assert(x) - #endif - #define DEBUG 0 -#endif /* DEBUG */ +#if ABORT_ON_ASSERT_FAILURE +#undef assert +#define assert(x) if(!(x)) ABORT +#else /* ABORT_ON_ASSERT_FAILURE */ +#include +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#ifndef assert +#define assert(x) +#endif +#define DEBUG 0 +#endif /* DEBUG */ #if !defined(WIN32) && !defined(LACKS_TIME_H) - #include /* for magic initialization */ -#endif /* WIN32 */ +#include /* for magic initialization */ +#endif /* WIN32 */ #ifndef LACKS_STDLIB_H - #include /* for abort() */ -#endif /* LACKS_STDLIB_H */ +#include /* for abort() */ +#endif /* LACKS_STDLIB_H */ #ifndef LACKS_STRING_H - #include /* for memset etc */ -#endif /* LACKS_STRING_H */ +#include /* for memset etc */ +#endif /* LACKS_STRING_H */ #if USE_BUILTIN_FFS - #ifndef LACKS_STRINGS_H - #include /* for ffs */ - #endif /* LACKS_STRINGS_H */ -#endif /* USE_BUILTIN_FFS */ +#ifndef LACKS_STRINGS_H +#include /* for ffs */ +#endif /* LACKS_STRINGS_H */ +#endif /* USE_BUILTIN_FFS */ #if HAVE_MMAP - #ifndef LACKS_SYS_MMAN_H - /* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ - #if (defined(linux) && !defined(__USE_GNU)) - #define __USE_GNU 1 - #include /* for mmap */ - #undef __USE_GNU - #else - #include /* for mmap */ - #endif /* linux */ - #endif /* LACKS_SYS_MMAN_H */ - #ifndef LACKS_FCNTL_H - #include - #endif /* LACKS_FCNTL_H */ -#endif /* HAVE_MMAP */ +#ifndef LACKS_SYS_MMAN_H +/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ +#if (defined(linux) && !defined(__USE_GNU)) +#define __USE_GNU 1 +#include /* for mmap */ +#undef __USE_GNU +#else +#include /* for mmap */ +#endif /* linux */ +#endif /* LACKS_SYS_MMAN_H */ +#ifndef LACKS_FCNTL_H +#include +#endif /* LACKS_FCNTL_H */ +#endif /* HAVE_MMAP */ #ifndef LACKS_UNISTD_H - #include /* for sbrk, sysconf */ -#else /* LACKS_UNISTD_H */ - #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -extern void *sbrk(ptrdiff_t); - #endif /* FreeBSD etc */ -#endif /* LACKS_UNISTD_H */ +#include /* for sbrk, sysconf */ +#else /* LACKS_UNISTD_H */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +extern void* sbrk(ptrdiff_t); +#endif /* FreeBSD etc */ +#endif /* LACKS_UNISTD_H */ /* Declarations for locking */ #if USE_LOCKS - #ifndef WIN32 - #if defined(__SVR4) && defined(__sun) /* solaris */ - #include - #elif !defined(LACKS_SCHED_H) - #include - #endif /* solaris or LACKS_SCHED_H */ - #if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || \ - !USE_SPIN_LOCKS - #include - #endif /* USE_RECURSIVE_LOCKS ... */ - #elif defined(_MSC_VER) - #ifndef _M_AMD64 - /* These are already defined on AMD64 builds */ - #ifdef __cplusplus +#ifndef WIN32 +#if defined (__SVR4) && defined (__sun) /* solaris */ +#include +#elif !defined(LACKS_SCHED_H) +#include +#endif /* solaris or LACKS_SCHED_H */ +#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS +#include +#endif /* USE_RECURSIVE_LOCKS ... */ +#elif defined(_MSC_VER) +#ifndef _M_AMD64 +/* These are already defined on AMD64 builds */ +#ifdef __cplusplus extern "C" { - - #endif /* __cplusplus */ -LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, - LONG Comp); +#endif /* __cplusplus */ +LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); - #ifdef __cplusplus - +#ifdef __cplusplus } - - #endif /* __cplusplus */ - #endif /* _M_AMD64 */ - #pragma intrinsic(_InterlockedCompareExchange) - #pragma intrinsic(_InterlockedExchange) - #define interlockedcompareexchange _InterlockedCompareExchange - #define interlockedexchange _InterlockedExchange - #elif defined(WIN32) && defined(__GNUC__) - #define interlockedcompareexchange(a, b, c) \ - __sync_val_compare_and_swap(a, c, b) - #define interlockedexchange __sync_lock_test_and_set - #endif /* Win32 */ -#else /* USE_LOCKS */ -#endif /* USE_LOCKS */ +#endif /* __cplusplus */ +#endif /* _M_AMD64 */ +#pragma intrinsic (_InterlockedCompareExchange) +#pragma intrinsic (_InterlockedExchange) +#define interlockedcompareexchange _InterlockedCompareExchange +#define interlockedexchange _InterlockedExchange +#elif defined(WIN32) && defined(__GNUC__) +#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) +#define interlockedexchange __sync_lock_test_and_set +#endif /* Win32 */ +#else /* USE_LOCKS */ +#endif /* USE_LOCKS */ #ifndef LOCK_AT_FORK - #define LOCK_AT_FORK 0 +#define LOCK_AT_FORK 0 #endif /* Declarations for bit scanning on win32 */ -#if defined(_MSC_VER) && _MSC_VER >= 1300 - #ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ - #ifdef __cplusplus +#if defined(_MSC_VER) && _MSC_VER>=1300 +#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ +#ifdef __cplusplus extern "C" { - - #endif /* __cplusplus */ +#endif /* __cplusplus */ unsigned char _BitScanForward(unsigned long *index, unsigned long mask); unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); - #ifdef __cplusplus - +#ifdef __cplusplus } +#endif /* __cplusplus */ - #endif /* __cplusplus */ - - #define BitScanForward _BitScanForward - #define BitScanReverse _BitScanReverse - #pragma intrinsic(_BitScanForward) - #pragma intrinsic(_BitScanReverse) - #endif /* BitScanForward */ -#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ +#define BitScanForward _BitScanForward +#define BitScanReverse _BitScanReverse +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* BitScanForward */ +#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ #ifndef WIN32 - #ifndef malloc_getpagesize - #ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ - #ifndef _SC_PAGE_SIZE - #define _SC_PAGE_SIZE _SC_PAGESIZE - #endif - #endif - #ifdef _SC_PAGE_SIZE - #define malloc_getpagesize sysconf(_SC_PAGE_SIZE) - #else - #if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) -extern size_t getpagesize(); - #define malloc_getpagesize getpagesize() - #else - #ifdef WIN32 /* use supplied emulation of getpagesize */ - #define malloc_getpagesize getpagesize() - #else - #ifndef LACKS_SYS_PARAM_H - #include - #endif - #ifdef EXEC_PAGESIZE - #define malloc_getpagesize EXEC_PAGESIZE - #else - #ifdef NBPG - #ifndef CLSIZE - #define malloc_getpagesize NBPG - #else - #define malloc_getpagesize (NBPG * CLSIZE) - #endif - #else - #ifdef NBPC - #define malloc_getpagesize NBPC - #else - #ifdef PAGESIZE - #define malloc_getpagesize PAGESIZE - #else /* just guess */ - #define malloc_getpagesize ((size_t)4096U) - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif +#ifndef malloc_getpagesize +# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +# ifndef _SC_PAGE_SIZE +# define _SC_PAGE_SIZE _SC_PAGESIZE +# endif +# endif +# ifdef _SC_PAGE_SIZE +# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +# else +# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +# define malloc_getpagesize getpagesize() +# else +# ifdef WIN32 /* use supplied emulation of getpagesize */ +# define malloc_getpagesize getpagesize() +# else +# ifndef LACKS_SYS_PARAM_H +# include +# endif +# ifdef EXEC_PAGESIZE +# define malloc_getpagesize EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define malloc_getpagesize NBPG +# else +# define malloc_getpagesize (NBPG * CLSIZE) +# endif +# else +# ifdef NBPC +# define malloc_getpagesize NBPC +# else +# ifdef PAGESIZE +# define malloc_getpagesize PAGESIZE +# else /* just guess */ +# define malloc_getpagesize ((size_t)4096U) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif #endif /* ------------------- size_t and alignment properties -------------------- */ /* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) /* Some constants coerced to size_t */ /* Annoying but necessary to avoid errors on some platforms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define SIZE_T_FOUR ((size_t)4) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE << 1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE << 2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES + TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define SIZE_T_FOUR ((size_t)4) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) /* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) /* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) /* the number of bytes to offset an address to align it */ -#define align_offset(A) \ - ((((size_t)(A)&CHUNK_ALIGN_MASK) == 0) \ - ? 0 \ - : ((MALLOC_ALIGNMENT - ((size_t)(A)&CHUNK_ALIGN_MASK)) & \ - CHUNK_ALIGN_MASK)) +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) /* -------------------------- MMAP preliminaries ------------------------- */ @@ -1669,202 +1637,193 @@ extern size_t getpagesize(); using so many "#if"s. */ + /* MORECORE and MMAP must return MFAIL on failure */ -#define MFAIL ((void *)(MAX_SIZE_T)) -#define CMFAIL ((char *)(MFAIL)) /* defined for convenience */ +#define MFAIL ((void*)(MAX_SIZE_T)) +#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ #if HAVE_MMAP - #ifndef WIN32 - #define MMAP_PROT (PROT_READ | PROT_WRITE) - #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) - #define MAP_ANONYMOUS MAP_ANON - #endif /* MAP_ANON */ - #ifdef MAP_ANONYMOUS - - #define MMAP_FLAGS (MAP_PRIVATE | MAP_ANONYMOUS) +#ifndef WIN32 +#define MMAP_PROT (PROT_READ|PROT_WRITE) +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANON */ +#ifdef MAP_ANONYMOUS -static FORCEINLINE void *unixmmap(size_t size) { +#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) - void *result; +static FORCEINLINE void* unixmmap(size_t size) { + void* result; result = mmap(0, size, MMAP_PROT, MMAP_FLAGS, -1, 0); - if (result == MFAIL) return MFAIL; + if (result == MFAIL) + return MFAIL; return result; - } -static FORCEINLINE int unixmunmap(void *ptr, size_t size) { - +static FORCEINLINE int unixmunmap(void* ptr, size_t size) { int result; result = munmap(ptr, size); - if (result != 0) return result; + if (result != 0) + return result; return result; - } - #define MMAP_DEFAULT(s) unixmmap(s) - #define MUNMAP_DEFAULT(a, s) unixmunmap((a), (s)) +#define MMAP_DEFAULT(s) unixmmap(s) +#define MUNMAP_DEFAULT(a, s) unixmunmap((a), (s)) - #else /* MAP_ANONYMOUS */ - /* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. - */ - #define MMAP_FLAGS (MAP_PRIVATE) -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ - #define MMAP_DEFAULT(s) \ - ((dev_zero_fd < 0) \ - ? (dev_zero_fd = open("/dev/zero", O_RDWR), \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) \ - : mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) - #define MUNMAP_DEFAULT(a, s) munmap((a), (s)) - #endif /* MAP_ANONYMOUS */ +#else /* MAP_ANONYMOUS */ +/* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. +*/ +#define MMAP_FLAGS (MAP_PRIVATE) +static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ + (dev_zero_fd = open("/dev/zero", O_RDWR), \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) +#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) +#endif /* MAP_ANONYMOUS */ - #define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) +#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) - #else /* WIN32 */ +#else /* WIN32 */ /* Win32 MMAP via VirtualAlloc */ -static FORCEINLINE void *win32mmap(size_t size) { - - void *ptr; +static FORCEINLINE void* win32mmap(size_t size) { + void* ptr; - ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (ptr == 0) return MFAIL; + ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if (ptr == 0) + return MFAIL; return ptr; - } /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static FORCEINLINE void *win32direct_mmap(size_t size) { - - void *ptr; +static FORCEINLINE void* win32direct_mmap(size_t size) { + void* ptr; - ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, - PAGE_READWRITE); - if (ptr == 0) return MFAIL; + ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, + PAGE_READWRITE); + if (ptr == 0) + return MFAIL; return ptr; - } /* This function supports releasing coalesed segments */ -static FORCEINLINE int win32munmap(void *ptr, size_t size) { - +static FORCEINLINE int win32munmap(void* ptr, size_t size) { MEMORY_BASIC_INFORMATION minfo; - char *cptr = (char *)ptr; + char* cptr = (char*)ptr; while (size) { - - if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) return -1; + if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) + return -1; if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || minfo.State != MEM_COMMIT || minfo.RegionSize > size) return -1; - if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) return -1; + if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) + return -1; cptr += minfo.RegionSize; size -= minfo.RegionSize; - } return 0; - } - #define MMAP_DEFAULT(s) win32mmap(s) - #define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) - #define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) - #endif /* WIN32 */ -#endif /* HAVE_MMAP */ +#define MMAP_DEFAULT(s) win32mmap(s) +#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) +#endif /* WIN32 */ +#endif /* HAVE_MMAP */ #if HAVE_MREMAP - #ifndef WIN32 - -static FORCEINLINE void *dlmremap(void *old_address, size_t old_size, - size_t new_size, int flags) { +#ifndef WIN32 - void *result; +static FORCEINLINE void* dlmremap(void* old_address, size_t old_size, size_t new_size, int flags) { + void* result; result = mremap(old_address, old_size, new_size, flags); - if (result == MFAIL) return MFAIL; + if (result == MFAIL) + return MFAIL; return result; - } - #define MREMAP_DEFAULT(addr, osz, nsz, mv) \ - dlmremap((addr), (osz), (nsz), (mv)) - #endif /* WIN32 */ -#endif /* HAVE_MREMAP */ +#define MREMAP_DEFAULT(addr, osz, nsz, mv) dlmremap((addr), (osz), (nsz), (mv)) +#endif /* WIN32 */ +#endif /* HAVE_MREMAP */ /** * Define CALL_MORECORE */ #if HAVE_MORECORE - #ifdef MORECORE - #define CALL_MORECORE(S) MORECORE(S) - #else /* MORECORE */ - #define CALL_MORECORE(S) MORECORE_DEFAULT(S) - #endif /* MORECORE */ -#else /* HAVE_MORECORE */ - #define CALL_MORECORE(S) MFAIL -#endif /* HAVE_MORECORE */ + #ifdef MORECORE + #define CALL_MORECORE(S) MORECORE(S) + #else /* MORECORE */ + #define CALL_MORECORE(S) MORECORE_DEFAULT(S) + #endif /* MORECORE */ +#else /* HAVE_MORECORE */ + #define CALL_MORECORE(S) MFAIL +#endif /* HAVE_MORECORE */ /** * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP */ #if HAVE_MMAP - #define USE_MMAP_BIT (SIZE_T_ONE) - - #ifdef MMAP - #define CALL_MMAP(s) MMAP(s) - #else /* MMAP */ - #define CALL_MMAP(s) MMAP_DEFAULT(s) - #endif /* MMAP */ - #ifdef MUNMAP - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) - #else /* MUNMAP */ - #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) - #endif /* MUNMAP */ - #ifdef DIRECT_MMAP - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #else /* DIRECT_MMAP */ - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) - #endif /* DIRECT_MMAP */ -#else /* HAVE_MMAP */ - #define USE_MMAP_BIT (SIZE_T_ZERO) - - #define MMAP(s) MFAIL - #define MUNMAP(a, s) (-1) - #define DIRECT_MMAP(s) MFAIL - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #define CALL_MMAP(s) MMAP(s) - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) -#endif /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ONE) + + #ifdef MMAP + #define CALL_MMAP(s) MMAP(s) + #else /* MMAP */ + #define CALL_MMAP(s) MMAP_DEFAULT(s) + #endif /* MMAP */ + #ifdef MUNMAP + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) + #else /* MUNMAP */ + #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) + #endif /* MUNMAP */ + #ifdef DIRECT_MMAP + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #else /* DIRECT_MMAP */ + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) + #endif /* DIRECT_MMAP */ +#else /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ZERO) + + #define MMAP(s) MFAIL + #define MUNMAP(a, s) (-1) + #define DIRECT_MMAP(s) MFAIL + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #define CALL_MMAP(s) MMAP(s) + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) +#endif /* HAVE_MMAP */ /** * Define CALL_MREMAP */ #if HAVE_MMAP && HAVE_MREMAP - #ifdef MREMAP - #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) - #else /* MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) \ - MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) - #endif /* MREMAP */ -#else /* HAVE_MMAP && HAVE_MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ + #ifdef MREMAP + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) + #else /* MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) + #endif /* MREMAP */ +#else /* HAVE_MMAP && HAVE_MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ /* mstate bit set if continguous morecore disabled or failed */ #define USE_NONCONTIGUOUS_BIT (4U) /* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) +#define EXTERN_BIT (8U) + /* --------------------------- Lock preliminaries ------------------------ */ @@ -1897,284 +1856,247 @@ static FORCEINLINE void *dlmremap(void *old_address, size_t old_size, */ #if !USE_LOCKS - #define USE_LOCK_BIT (0U) - #define INITIAL_LOCK(l) (0) - #define DESTROY_LOCK(l) (0) - #define ACQUIRE_MALLOC_GLOBAL_LOCK() - #define RELEASE_MALLOC_GLOBAL_LOCK() +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) (0) +#define DESTROY_LOCK(l) (0) +#define ACQUIRE_MALLOC_GLOBAL_LOCK() +#define RELEASE_MALLOC_GLOBAL_LOCK() #else - #if USE_LOCKS > 1 - /* ----------------------- User-defined locks ------------------------ */ - /* Define your own lock implementation here */ - /* #define INITIAL_LOCK(lk) ... */ - /* #define DESTROY_LOCK(lk) ... */ - /* #define ACQUIRE_LOCK(lk) ... */ - /* #define RELEASE_LOCK(lk) ... */ - /* #define TRY_LOCK(lk) ... */ - /* static MLOCK_T malloc_global_mutex = ... */ - - #elif USE_SPIN_LOCKS - - /* First, define CAS_LOCK and CLEAR_LOCK on ints */ - /* Note CAS_LOCK defined to return 0 on success */ - - #if defined(__GNUC__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) - #define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) - #define CLEAR_LOCK(sl) __sync_lock_release(sl) - - #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +#if USE_LOCKS > 1 +/* ----------------------- User-defined locks ------------------------ */ +/* Define your own lock implementation here */ +/* #define INITIAL_LOCK(lk) ... */ +/* #define DESTROY_LOCK(lk) ... */ +/* #define ACQUIRE_LOCK(lk) ... */ +/* #define RELEASE_LOCK(lk) ... */ +/* #define TRY_LOCK(lk) ... */ +/* static MLOCK_T malloc_global_mutex = ... */ + +#elif USE_SPIN_LOCKS + +/* First, define CAS_LOCK and CLEAR_LOCK on ints */ +/* Note CAS_LOCK defined to return 0 on success */ + +#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) +#define CLEAR_LOCK(sl) __sync_lock_release(sl) + +#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) /* Custom spin locks for older gcc on x86 */ static FORCEINLINE int x86_cas_lock(int *sl) { - int ret; int val = 1; int cmp = 0; - __asm__ __volatile__("lock; cmpxchgl %1, %2" - : "=a"(ret) - : "r"(val), "m"(*(sl)), "0"(cmp) - : "memory", "cc"); + __asm__ __volatile__ ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (val), "m" (*(sl)), "0"(cmp) + : "memory", "cc"); return ret; - } -static FORCEINLINE void x86_clear_lock(int *sl) { - +static FORCEINLINE void x86_clear_lock(int* sl) { assert(*sl != 0); int prev = 0; int ret; - __asm__ __volatile__("lock; xchgl %0, %1" - : "=r"(ret) - : "m"(*(sl)), "0"(prev) - : "memory"); - + __asm__ __volatile__ ("lock; xchgl %0, %1" + : "=r" (ret) + : "m" (*(sl)), "0"(prev) + : "memory"); } - #define CAS_LOCK(sl) x86_cas_lock(sl) - #define CLEAR_LOCK(sl) x86_clear_lock(sl) - - #else /* Win32 MSC */ - #define CAS_LOCK(sl) interlockedexchange((volatile LONG *)sl, (LONG)1) - #define CLEAR_LOCK(sl) interlockedexchange((volatile LONG *)sl, (LONG)0) - - #endif /* ... gcc spins locks ... */ - - /* How to yield for a spin lock */ - #define SPINS_PER_YIELD 63 - #if defined(_MSC_VER) - #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ - #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) - #elif defined(__SVR4) && defined(__sun) /* solaris */ - #define SPIN_LOCK_YIELD thr_yield(); - #elif !defined(LACKS_SCHED_H) - #define SPIN_LOCK_YIELD sched_yield(); - #else - #define SPIN_LOCK_YIELD - #endif /* ... yield ... */ - - #if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 +#define CAS_LOCK(sl) x86_cas_lock(sl) +#define CLEAR_LOCK(sl) x86_clear_lock(sl) + +#else /* Win32 MSC */ +#define CAS_LOCK(sl) interlockedexchange((volatile LONG *)sl, (LONG)1) +#define CLEAR_LOCK(sl) interlockedexchange((volatile LONG *)sl, (LONG)0) + +#endif /* ... gcc spins locks ... */ + +/* How to yield for a spin lock */ +#define SPINS_PER_YIELD 63 +#if defined(_MSC_VER) +#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ +#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) +#elif defined (__SVR4) && defined (__sun) /* solaris */ +#define SPIN_LOCK_YIELD thr_yield(); +#elif !defined(LACKS_SCHED_H) +#define SPIN_LOCK_YIELD sched_yield(); +#else +#define SPIN_LOCK_YIELD +#endif /* ... yield ... */ + +#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 /* Plain spin locks use single word (embedded in malloc_states) */ static int spin_acquire_lock(int *sl) { - int spins = 0; while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { - - if ((++spins & SPINS_PER_YIELD) == 0) { SPIN_LOCK_YIELD; } - + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } } - return 0; - } - #define MLOCK_T int - #define TRY_LOCK(sl) !CAS_LOCK(sl) - #define RELEASE_LOCK(sl) CLEAR_LOCK(sl) - #define ACQUIRE_LOCK(sl) (CAS_LOCK(sl) ? spin_acquire_lock(sl) : 0) - #define INITIAL_LOCK(sl) (*sl = 0) - #define DESTROY_LOCK(sl) (0) +#define MLOCK_T int +#define TRY_LOCK(sl) !CAS_LOCK(sl) +#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) +#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) +#define INITIAL_LOCK(sl) (*sl = 0) +#define DESTROY_LOCK(sl) (0) static MLOCK_T malloc_global_mutex = 0; - #else /* USE_RECURSIVE_LOCKS */ - /* types for lock owners */ - #ifdef WIN32 - #define THREAD_ID_T DWORD - #define CURRENT_THREAD GetCurrentThreadId() - #define EQ_OWNER(X, Y) ((X) == (Y)) - #else - /* - Note: the following assume that pthread_t is a type that can be - initialized to (casted) zero. If this is not the case, you will need - to somehow redefine these or not use spin locks. - */ - #define THREAD_ID_T pthread_t - #define CURRENT_THREAD pthread_self() - #define EQ_OWNER(X, Y) pthread_equal(X, Y) - #endif +#else /* USE_RECURSIVE_LOCKS */ +/* types for lock owners */ +#ifdef WIN32 +#define THREAD_ID_T DWORD +#define CURRENT_THREAD GetCurrentThreadId() +#define EQ_OWNER(X,Y) ((X) == (Y)) +#else +/* + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need to + somehow redefine these or not use spin locks. +*/ +#define THREAD_ID_T pthread_t +#define CURRENT_THREAD pthread_self() +#define EQ_OWNER(X,Y) pthread_equal(X, Y) +#endif struct malloc_recursive_lock { - - int sl; + int sl; unsigned int c; - THREAD_ID_T threadid; - + THREAD_ID_T threadid; }; - #define MLOCK_T struct malloc_recursive_lock -static MLOCK_T malloc_global_mutex = {0, 0, (THREAD_ID_T)0}; +#define MLOCK_T struct malloc_recursive_lock +static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { - assert(lk->sl != 0); - if (--lk->c == 0) { CLEAR_LOCK(&lk->sl); } - + if (--lk->c == 0) { + CLEAR_LOCK(&lk->sl); + } } static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { - THREAD_ID_T mythreadid = CURRENT_THREAD; - int spins = 0; + int spins = 0; for (;;) { - if (*((volatile int *)(&lk->sl)) == 0) { - if (!CAS_LOCK(&lk->sl)) { - lk->threadid = mythreadid; lk->c = 1; return 0; - } - - } else if (EQ_OWNER(lk->threadid, mythreadid)) { - + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { ++lk->c; return 0; - } - - if ((++spins & SPINS_PER_YIELD) == 0) { SPIN_LOCK_YIELD; } - + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } } - } static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { - THREAD_ID_T mythreadid = CURRENT_THREAD; if (*((volatile int *)(&lk->sl)) == 0) { - if (!CAS_LOCK(&lk->sl)) { - lk->threadid = mythreadid; lk->c = 1; return 1; - } - - } else if (EQ_OWNER(lk->threadid, mythreadid)) { - + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { ++lk->c; return 1; - } - return 0; - } - #define RELEASE_LOCK(lk) recursive_release_lock(lk) - #define TRY_LOCK(lk) recursive_try_lock(lk) - #define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) - #define INITIAL_LOCK(lk) \ - ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) - #define DESTROY_LOCK(lk) (0) - #endif /* USE_RECURSIVE_LOCKS */ - - #elif defined(WIN32) /* Win32 critical sections */ - #define MLOCK_T CRITICAL_SECTION - #define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) - #define RELEASE_LOCK(lk) LeaveCriticalSection(lk) - #define TRY_LOCK(lk) TryEnterCriticalSection(lk) - #define INITIAL_LOCK(lk) \ - (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000 | 4000)) - #define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) - #define NEED_GLOBAL_LOCK_INIT - -static MLOCK_T malloc_global_mutex; +#define RELEASE_LOCK(lk) recursive_release_lock(lk) +#define TRY_LOCK(lk) recursive_try_lock(lk) +#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) +#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) +#define DESTROY_LOCK(lk) (0) +#endif /* USE_RECURSIVE_LOCKS */ + +#elif defined(WIN32) /* Win32 critical sections */ +#define MLOCK_T CRITICAL_SECTION +#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) +#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) +#define TRY_LOCK(lk) TryEnterCriticalSection(lk) +#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) +#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) +#define NEED_GLOBAL_LOCK_INIT + +static MLOCK_T malloc_global_mutex; static volatile LONG malloc_global_mutex_status; /* Use spin loop to initialize global lock */ static void init_malloc_global_mutex() { - for (;;) { - long stat = malloc_global_mutex_status; - if (stat > 0) return; + if (stat > 0) + return; /* transition to < 0 while initializing, then to > 0) */ - if (stat == 0 && interlockedcompareexchange(&malloc_global_mutex_status, - (LONG)-1, (LONG)0) == 0) { - + if (stat == 0 && + interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) { InitializeCriticalSection(&malloc_global_mutex); interlockedexchange(&malloc_global_mutex_status, (LONG)1); return; - } - SleepEx(0, FALSE); - } - } - #else /* pthreads-based locks */ - #define MLOCK_T pthread_mutex_t - #define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) - #define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) - #define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) - #define INITIAL_LOCK(lk) pthread_init_lock(lk) - #define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) +#else /* pthreads-based locks */ +#define MLOCK_T pthread_mutex_t +#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) +#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) +#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) +#define INITIAL_LOCK(lk) pthread_init_lock(lk) +#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) - #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && \ - defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) /* Cope with old-style linux recursive lock initialization by adding */ /* skipped internal declaration from pthread.h */ -extern int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t * __attr, - int __kind)); - #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP - #define pthread_mutexattr_settype(x, y) pthread_mutexattr_setkind_np(x, y) - #endif /* USE_RECURSIVE_LOCKS ... */ +extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, + int __kind)); +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) +#endif /* USE_RECURSIVE_LOCKS ... */ static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; -static int pthread_init_lock(MLOCK_T *lk) { - +static int pthread_init_lock (MLOCK_T *lk) { pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr)) return 1; - #if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; - #endif +#endif if (pthread_mutex_init(lk, &attr)) return 1; if (pthread_mutexattr_destroy(&attr)) return 1; return 0; - } - #endif /* ... lock types ... */ +#endif /* ... lock types ... */ - /* Common code for all lock types */ - #define USE_LOCK_BIT (2U) +/* Common code for all lock types */ +#define USE_LOCK_BIT (2U) - #ifndef ACQUIRE_MALLOC_GLOBAL_LOCK - #define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); - #endif +#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK +#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); +#endif - #ifndef RELEASE_MALLOC_GLOBAL_LOCK - #define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); - #endif +#ifndef RELEASE_MALLOC_GLOBAL_LOCK +#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); +#endif -#endif /* USE_LOCKS */ +#endif /* USE_LOCKS */ /* ----------------------- Chunk representations ------------------------ */ @@ -2314,56 +2236,56 @@ static int pthread_init_lock(MLOCK_T *lk) { */ struct malloc_chunk { - - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk *fd; /* double links -- used only if free. */ - struct malloc_chunk *bk; - + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; }; typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk *mchunkptr; -typedef struct malloc_chunk *sbinptr; /* The type of bins of chunks */ -typedef unsigned int bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ -typedef unsigned int flag_t; /* The type of various bit flag sets */ +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef unsigned int bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ /* ------------------- Chunks sizes and alignments ----------------------- */ -#define MCHUNK_SIZE (sizeof(mchunk)) +#define MCHUNK_SIZE (sizeof(mchunk)) #if FOOTERS - #define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -#else /* FOOTERS */ - #define CHUNK_OVERHEAD (SIZE_T_SIZE) -#endif /* FOOTERS */ +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ /* MMapped chunks need a second word of overhead ... */ #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) /* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) +#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) /* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) /* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void *)((char *)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char *)(mem)-TWO_SIZE_T_SIZES)) +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) /* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) /* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) /* pad request bytes into a usable size */ #define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) /* pad request, checking for minimum (but not maximum) */ #define request2size(req) \ - (((req) < MIN_REQUEST) ? MIN_CHUNK_SIZE : pad_request(req)) + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + /* ------------------ Operations on head and foot fields ----------------- */ @@ -2375,60 +2297,61 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ FLAG4_BIT is not used by this malloc, but might be useful in extensions. */ -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define FLAG4_BIT (SIZE_T_FOUR) -#define INUSE_BITS (PINUSE_BIT | CINUSE_BIT) -#define FLAG_BITS (PINUSE_BIT | CINUSE_BIT | FLAG4_BIT) +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define FLAG4_BIT (SIZE_T_FOUR) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) +#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) /* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS | SIZE_T_SIZE) +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) /* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define flag4inuse(p) ((p)->head & FLAG4_BIT) -#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) -#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define flag4inuse(p) ((p)->head & FLAG4_BIT) +#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) +#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) -#define chunksize(p) ((p)->head & ~(FLAG_BITS)) +#define chunksize(p) ((p)->head & ~(FLAG_BITS)) -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) -#define set_flag4(p) ((p)->head |= FLAG4_BIT) -#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define set_flag4(p) ((p)->head |= FLAG4_BIT) +#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) /* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char *)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char *)(p)) - (s))) +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) /* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)(((char *)(p)) + ((p)->head & ~FLAG_BITS))) -#define prev_chunk(p) ((mchunkptr)(((char *)(p)) - ((p)->prev_foot))) +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) /* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) /* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char *)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char *)(p) + (s)))->prev_foot = (s)) +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) /* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s) \ - ((p)->head = (s | PINUSE_BIT), set_foot(p, s)) +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) /* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n) \ +#define set_free_with_pinuse(p, s, n)\ (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) /* Get the internal overhead associated with chunk p */ -#define overhead_for(p) (is_mmapped(p) ? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) +#define overhead_for(p)\ + (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) /* Return true if malloced space is not necessarily cleared */ #if MMAP_CLEARS - #define calloc_must_clear(p) (!is_mmapped(p)) -#else /* MMAP_CLEARS */ - #define calloc_must_clear(p) (1) -#endif /* MMAP_CLEARS */ +#define calloc_must_clear(p) (!is_mmapped(p)) +#else /* MMAP_CLEARS */ +#define calloc_must_clear(p) (1) +#endif /* MMAP_CLEARS */ /* ---------------------- Overlaid data structures ----------------------- */ @@ -2522,25 +2445,23 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ size_t prev_foot; size_t head; - struct malloc_tree_chunk *fd; - struct malloc_tree_chunk *bk; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; - struct malloc_tree_chunk *child[2]; - struct malloc_tree_chunk *parent; + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; bindex_t index; - }; typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk *tchunkptr; -typedef struct malloc_tree_chunk *tbinptr; /* The type of bins of trees */ +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ /* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0 ? (t)->child[0] : (t)->child[1]) +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) /* ----------------------------- Segments -------------------------------- */ @@ -2600,19 +2521,17 @@ typedef struct malloc_tree_chunk *tbinptr; /* The type of bins of trees */ */ struct malloc_segment { - - char * base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment *next; /* ptr to next segment */ - flag_t sflags; /* mmap and extern flag */ - + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ + flag_t sflags; /* mmap and extern flag */ }; -#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) -#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) +#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) +#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) typedef struct malloc_segment msegment; -typedef struct malloc_segment *msegmentptr; +typedef struct malloc_segment* msegmentptr; /* ---------------------------- malloc_state ----------------------------- */ @@ -2702,43 +2621,41 @@ typedef struct malloc_segment *msegmentptr; */ /* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) struct malloc_state { - - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char * least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t release_checks; - size_t magic; - mchunkptr smallbins[(NSMALLBINS + 1) * 2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - size_t footprint_limit; /* zero means no limit */ - flag_t mflags; + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t trim_check; + size_t release_checks; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + size_t footprint_limit; /* zero means no limit */ + flag_t mflags; #if USE_LOCKS - MLOCK_T mutex; /* locate lock among fields that rarely change */ -#endif /* USE_LOCKS */ - msegment seg; - void * extp; /* Unused but available for extensions */ - size_t exts; - + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; + void* extp; /* Unused but available for extensions */ + size_t exts; }; -typedef struct malloc_state *mstate; +typedef struct malloc_state* mstate; /* ------------- Global malloc_state and malloc_params ------------------- */ @@ -2750,14 +2667,12 @@ typedef struct malloc_state *mstate; */ struct malloc_params { - size_t magic; size_t page_size; size_t granularity; size_t mmap_threshold; size_t trim_threshold; flag_t default_mflags; - }; static struct malloc_params mparams; @@ -2769,108 +2684,106 @@ static struct malloc_params mparams; /* The global malloc_state used for all non-"mspace" calls */ static struct malloc_state _gm_; - #define gm (&_gm_) - #define is_global(M) ((M) == &_gm_) +#define gm (&_gm_) +#define is_global(M) ((M) == &_gm_) -#endif /* !ONLY_MSPACES */ +#endif /* !ONLY_MSPACES */ -#define is_initialized(M) ((M)->top != 0) +#define is_initialized(M) ((M)->top != 0) /* -------------------------- system alloc setup ------------------------- */ /* Operations on mflags */ -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) #if USE_LOCKS - #define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) #else - #define disable_lock(M) +#define disable_lock(M) #endif -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) +#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) #if HAVE_MMAP - #define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) +#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) #else - #define disable_mmap(M) +#define disable_mmap(M) #endif -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) +#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) +#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) -#define set_lock(M, L) \ - ((M)->mflags = \ - (L) ? ((M)->mflags | USE_LOCK_BIT) : ((M)->mflags & ~USE_LOCK_BIT)) +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) /* page-align a size */ -#define page_align(S) \ - (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) +#define page_align(S)\ + (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) /* granularity-align a size */ -#define granularity_align(S) \ - (((S) + (mparams.granularity - SIZE_T_ONE)) & \ - ~(mparams.granularity - SIZE_T_ONE)) +#define granularity_align(S)\ + (((S) + (mparams.granularity - SIZE_T_ONE))\ + & ~(mparams.granularity - SIZE_T_ONE)) + /* For mmap, use granularity alignment on windows, else page-align */ #ifdef WIN32 - #define mmap_align(S) granularity_align(S) +#define mmap_align(S) granularity_align(S) #else - #define mmap_align(S) page_align(S) +#define mmap_align(S) page_align(S) #endif /* For sys_alloc, enough padding to ensure can malloc request on success */ #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) -#define is_page_aligned(S) \ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S) \ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) /* True if segment S holds address A */ -#define segment_holds(S, A) \ - ((char *)(A) >= S->base && (char *)(A) < S->base + S->size) +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) /* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char *addr) { - +static msegmentptr segment_holding(mstate m, char* addr) { msegmentptr sp = &m->seg; for (;;) { - - if (addr >= sp->base && addr < sp->base + sp->size) return sp; - if ((sp = sp->next) == 0) return 0; - + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; } - } /* Return true if segment contains a segment link */ static int has_segment_link(mstate m, msegmentptr ss) { - msegmentptr sp = &m->seg; for (;;) { - - if ((char *)sp >= ss->base && (char *)sp < ss->base + ss->size) return 1; - if ((sp = sp->next) == 0) return 0; - + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; } - } #ifndef MORECORE_CANNOT_TRIM - #define should_trim(M, s) ((s) > (M)->trim_check) -#else /* MORECORE_CANNOT_TRIM */ - #define should_trim(M, s) (0) -#endif /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) ((s) > (M)->trim_check) +#else /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) (0) +#endif /* MORECORE_CANNOT_TRIM */ /* TOP_FOOT_SIZE is padding at the end of a segment, including space that may be needed to place segment records and fenceposts when new noncontiguous segments are added. */ -#define TOP_FOOT_SIZE \ - (align_offset(chunk2mem(0)) + pad_request(sizeof(struct malloc_segment)) + \ - MIN_CHUNK_SIZE) +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + /* ------------------------------- Hooks -------------------------------- */ @@ -2881,24 +2794,19 @@ static int has_segment_link(mstate m, msegmentptr ss) { */ #if USE_LOCKS - #define PREACTION(M) ((use_lock(M)) ? ACQUIRE_LOCK(&(M)->mutex) : 0) - #define POSTACTION(M) \ - { \ - \ - if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); \ - \ - } -#else /* USE_LOCKS */ +#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ - #ifndef PREACTION - #define PREACTION(M) (0) - #endif /* PREACTION */ +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ - #ifndef POSTACTION - #define POSTACTION(M) - #endif /* POSTACTION */ +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ -#endif /* USE_LOCKS */ +#endif /* USE_LOCKS */ /* CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. @@ -2916,180 +2824,164 @@ int malloc_corruption_error_count; /* default corruption action */ static void reset_on_error(mstate m); - #define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) - #define USAGE_ERROR_ACTION(m, p) +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) -#else /* PROCEED_ON_ERROR */ +#else /* PROCEED_ON_ERROR */ - #ifndef CORRUPTION_ERROR_ACTION - #define CORRUPTION_ERROR_ACTION(m) ABORT - #endif /* CORRUPTION_ERROR_ACTION */ +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT +#endif /* CORRUPTION_ERROR_ACTION */ - #ifndef USAGE_ERROR_ACTION - #define USAGE_ERROR_ACTION(m, p) ABORT - #endif /* USAGE_ERROR_ACTION */ +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ -#endif /* PROCEED_ON_ERROR */ /* -------------------------- Debugging setup ---------------------------- */ -#if !DEBUG +#if ! DEBUG - #define check_free_chunk(M, P) - #define check_inuse_chunk(M, P) - #define check_malloced_chunk(M, P, N) - #define check_mmapped_chunk(M, P) - #define check_malloc_state(M) - #define check_top_chunk(M, P) +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) +#define check_malloc_state(M) +#define check_top_chunk(M,P) -#else /* DEBUG */ - #define check_free_chunk(M, P) do_check_free_chunk(M, P) - #define check_inuse_chunk(M, P) do_check_inuse_chunk(M, P) - #define check_top_chunk(M, P) do_check_top_chunk(M, P) - #define check_malloced_chunk(M, P, N) do_check_malloced_chunk(M, P, N) - #define check_mmapped_chunk(M, P) do_check_mmapped_chunk(M, P) - #define check_malloc_state(M) do_check_malloc_state(M) +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) +#define check_malloc_state(M) do_check_malloc_state(M) static void do_check_any_chunk(mstate m, mchunkptr p); static void do_check_top_chunk(mstate m, mchunkptr p); static void do_check_mmapped_chunk(mstate m, mchunkptr p); static void do_check_inuse_chunk(mstate m, mchunkptr p); static void do_check_free_chunk(mstate m, mchunkptr p); -static void do_check_malloced_chunk(mstate m, void *mem, size_t s); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); static void do_check_tree(mstate m, tchunkptr t); static void do_check_treebin(mstate m, bindex_t i); static void do_check_smallbin(mstate m, bindex_t i); static void do_check_malloc_state(mstate m); static int bin_find(mstate m, mchunkptr x); static size_t traverse_and_check(mstate m); -#endif /* DEBUG */ +#endif /* DEBUG */ /* ---------------------------- Indexing Bins ---------------------------- */ -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) /* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char *)&((M)->smallbins[(i) << 1]))) -#define treebin_at(M, i) (&((M)->treebins[i])) +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) /* assign tree index for size S to variable I. Use x86 asm if possible */ #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - #define compute_tree_index(S, I) \ - { \ - \ - unsigned int X = S >> TREEBIN_SHIFT; \ - if (X == 0) \ - I = 0; \ - else if (X > 0xFFFF) \ - I = NTREEBINS - 1; \ - else { \ - \ - unsigned int K = (unsigned)sizeof(X) * __CHAR_BIT__ - 1 - \ - (unsigned)__builtin_clz(X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT - 1)) & 1))); \ - \ - } \ - \ - } +#define compute_tree_index(S, I)\ +{\ + unsigned int X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} -#elif defined(__INTEL_COMPILER) - #define compute_tree_index(S, I) \ - { \ - \ - size_t X = S >> TREEBIN_SHIFT; \ - if (X == 0) \ - I = 0; \ - else if (X > 0xFFFF) \ - I = NTREEBINS - 1; \ - else { \ - \ - unsigned int K = _bit_scan_reverse(X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT - 1)) & 1))); \ - \ - } \ - \ - } +#elif defined (__INTEL_COMPILER) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = _bit_scan_reverse (X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} -#elif defined(_MSC_VER) && _MSC_VER >= 1300 - #define compute_tree_index(S, I) \ - { \ - \ - size_t X = S >> TREEBIN_SHIFT; \ - if (X == 0) \ - I = 0; \ - else if (X > 0xFFFF) \ - I = NTREEBINS - 1; \ - else { \ - \ - unsigned int K; \ - _BitScanReverse((DWORD *)&K, (DWORD)X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT - 1)) & 1))); \ - \ - } \ - \ - } +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + _BitScanReverse((DWORD *) &K, (DWORD) X);\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} -#else /* GNUC */ - #define compute_tree_index(S, I) \ - { \ - \ - size_t X = S >> TREEBIN_SHIFT; \ - if (X == 0) \ - I = 0; \ - else if (X > 0xFFFF) \ - I = NTREEBINS - 1; \ - else { \ - \ - unsigned int Y = (unsigned int)X; \ - unsigned int N = ((Y - 0x100) >> 16) & 8; \ - unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4; \ - N += K; \ - N += K = (((Y <<= K) - 0x4000) >> 16) & 2; \ - K = 14 - N + ((Y <<= K) >> 15); \ - I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT - 1)) & 1)); \ - \ - } \ - \ - } -#endif /* GNUC */ +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ /* Bit representing maximum resolved size in a treebin at i */ #define bit_for_tree_index(i) \ - (i == NTREEBINS - 1) ? (SIZE_T_BITSIZE - 1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) /* Shift placing maximum resolved bit in a treebin at i as sign bit */ #define leftshift_for_tree_index(i) \ - ((i == NTREEBINS - 1) \ - ? 0 \ - : ((SIZE_T_BITSIZE - SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) /* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i)&SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + /* ------------------------ Operations on bin maps ----------------------- */ /* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) +#define idx2bit(i) ((binmap_t)(1) << (i)) /* Mark/Clear bits with given index */ -#define mark_smallmap(M, i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M, i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M, i) ((M)->smallmap & idx2bit(i)) +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) -#define mark_treemap(M, i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M, i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M, i) ((M)->treemap & idx2bit(i)) +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) /* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) +#define least_bit(x) ((x) & -(x)) /* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x << 1) | -(x << 1)) +#define left_bits(x) ((x<<1) | -(x<<1)) /* mask with all bits to left of or equal to least bit of x on */ #define same_or_left_bits(x) ((x) | -(x)) @@ -3097,58 +2989,46 @@ static size_t traverse_and_check(mstate m); /* index corresponding to given bit. Use x86 asm if possible */ #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - #define compute_bit2idx(X, I) \ - { \ - \ - unsigned int J; \ - J = __builtin_ctz(X); \ - I = (bindex_t)J; \ - \ - } +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = __builtin_ctz(X); \ + I = (bindex_t)J;\ +} -#elif defined(__INTEL_COMPILER) - #define compute_bit2idx(X, I) \ - { \ - \ - unsigned int J; \ - J = _bit_scan_forward(X); \ - I = (bindex_t)J; \ - \ - } +#elif defined (__INTEL_COMPILER) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = _bit_scan_forward (X); \ + I = (bindex_t)J;\ +} -#elif defined(_MSC_VER) && _MSC_VER >= 1300 - #define compute_bit2idx(X, I) \ - { \ - \ - unsigned int J; \ - _BitScanForward((DWORD *)&J, X); \ - I = (bindex_t)J; \ - \ - } +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + _BitScanForward((DWORD *) &J, X);\ + I = (bindex_t)J;\ +} #elif USE_BUILTIN_FFS - #define compute_bit2idx(X, I) I = ffs(X) - 1 +#define compute_bit2idx(X, I) I = ffs(X)-1 #else - #define compute_bit2idx(X, I) \ - { \ - \ - unsigned int Y = X - 1; \ - unsigned int K = Y >> (16 - 4) & 16; \ - unsigned int N = K; \ - Y >>= K; \ - N += K = Y >> (8 - 3) & 8; \ - Y >>= K; \ - N += K = Y >> (4 - 2) & 4; \ - Y >>= K; \ - N += K = Y >> (2 - 1) & 2; \ - Y >>= K; \ - N += K = Y >> (1 - 0) & 1; \ - Y >>= K; \ - I = (bindex_t)(N + Y); \ - \ - } -#endif /* GNUC */ +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* GNUC */ + /* ----------------------- Runtime Check Support ------------------------- */ @@ -3179,141 +3059,121 @@ static size_t traverse_and_check(mstate m); */ #if !INSECURE - /* Check if address a is at least as high as any from MORECORE or MMAP */ - #define ok_address(M, a) ((char *)(a) >= (M)->least_addr) - /* Check if address of next chunk n is higher than base chunk p */ - #define ok_next(p, n) ((char *)(p) < (char *)(n)) - /* Check if p has inuse status */ - #define ok_inuse(p) is_inuse(p) - /* Check if p has its pinuse bit on */ - #define ok_pinuse(p) pinuse(p) - -#else /* !INSECURE */ - #define ok_address(M, a) (1) - #define ok_next(b, n) (1) - #define ok_inuse(p) (1) - #define ok_pinuse(p) (1) -#endif /* !INSECURE */ +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has inuse status */ +#define ok_inuse(p) is_inuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_inuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ #if (FOOTERS && !INSECURE) - /* Check if (alleged) mstate m has expected magic field */ - #define ok_magic(M) ((M)->magic == mparams.magic) -#else /* (FOOTERS && !INSECURE) */ - #define ok_magic(M) (1) -#endif /* (FOOTERS && !INSECURE) */ +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ /* In gcc, use __builtin_expect to minimize impact of checks */ #if !INSECURE - #if defined(__GNUC__) && __GNUC__ >= 3 - #define RTCHECK(e) __builtin_expect(e, 1) - #else /* GNUC */ - #define RTCHECK(e) (e) - #endif /* GNUC */ -#else /* !INSECURE */ - #define RTCHECK(e) (1) -#endif /* !INSECURE */ +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ /* macros to set up inuse chunks with or without footers */ #if !FOOTERS - #define mark_inuse_foot(M, p, s) +#define mark_inuse_foot(M,p,s) - /* Macros for setting head/foot of non-mmapped chunks */ +/* Macros for setting head/foot of non-mmapped chunks */ - /* Set cinuse bit and pinuse bit of next chunk */ - #define set_inuse(M, p, s) \ - ((p)->head = (((p)->head & PINUSE_BIT) | s | CINUSE_BIT), \ - ((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT) +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - /* Set cinuse and pinuse of this chunk and pinuse of next chunk */ - #define set_inuse_and_pinuse(M, p, s) \ - ((p)->head = (s | PINUSE_BIT | CINUSE_BIT), \ - ((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT) +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - /* Set size, cinuse and pinuse bit of this chunk */ - #define set_size_and_pinuse_of_inuse_chunk(M, p, s) \ - ((p)->head = (s | PINUSE_BIT | CINUSE_BIT)) +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) -#else /* FOOTERS */ +#else /* FOOTERS */ - /* Set foot of inuse chunk to be xor of mstate and seed */ - #define mark_inuse_foot(M, p, s) \ - (((mchunkptr)((char *)(p) + (s)))->prev_foot = \ - ((size_t)(M) ^ mparams.magic)) +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) - #define get_mstate_for(p) \ - ((mstate)(((mchunkptr)((char *)(p) + (chunksize(p))))->prev_foot ^ \ - mparams.magic)) +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) - #define set_inuse(M, p, s) \ - ((p)->head = (((p)->head & PINUSE_BIT) | s | CINUSE_BIT), \ - (((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M, p, s)) +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) - #define set_inuse_and_pinuse(M, p, s) \ - ((p)->head = (s | PINUSE_BIT | CINUSE_BIT), \ - (((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M, p, s)) +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) - #define set_size_and_pinuse_of_inuse_chunk(M, p, s) \ - ((p)->head = (s | PINUSE_BIT | CINUSE_BIT), mark_inuse_foot(M, p, s)) +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) -#endif /* !FOOTERS */ +#endif /* !FOOTERS */ /* ---------------------------- setting mparams -------------------------- */ #if LOCK_AT_FORK -static void pre_fork(void) { - - ACQUIRE_LOCK(&(gm)->mutex); - -} - -static void post_fork_parent(void) { - - RELEASE_LOCK(&(gm)->mutex); - -} - -static void post_fork_child(void) { - - INITIAL_LOCK(&(gm)->mutex); - -} - -#endif /* LOCK_AT_FORK */ +static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); } +static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); } +static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); } +#endif /* LOCK_AT_FORK */ /* Initialize mparams */ static int init_mparams(void) { - #ifdef NEED_GLOBAL_LOCK_INIT - if (malloc_global_mutex_status <= 0) init_malloc_global_mutex(); + if (malloc_global_mutex_status <= 0) + init_malloc_global_mutex(); #endif ACQUIRE_MALLOC_GLOBAL_LOCK(); if (mparams.magic == 0) { - size_t magic; size_t psize; size_t gsize; #ifndef WIN32 psize = malloc_getpagesize; - gsize = ((DEFAULT_GRANULARITY != 0) ? DEFAULT_GRANULARITY : psize); -#else /* WIN32 */ + gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); +#else /* WIN32 */ { - SYSTEM_INFO system_info; GetSystemInfo(&system_info); psize = system_info.dwPageSize; - gsize = - ((DEFAULT_GRANULARITY != 0) ? DEFAULT_GRANULARITY - : system_info.dwAllocationGranularity); - + gsize = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); } - -#endif /* WIN32 */ +#endif /* WIN32 */ /* Sanity-check configuration: size_t must be unsigned and as wide as pointer type. @@ -3321,23 +3181,24 @@ static int init_mparams(void) { alignment must be at least 8. Alignment, min chunk size, and page size must all be powers of 2. */ - if ((sizeof(size_t) != sizeof(char *)) || (MAX_SIZE_T < MIN_CHUNK_SIZE) || - (sizeof(int) < 4) || (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT - SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE - SIZE_T_ONE)) != 0) || - ((gsize & (gsize - SIZE_T_ONE)) != 0) || - ((psize & (psize - SIZE_T_ONE)) != 0)) + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((gsize & (gsize-SIZE_T_ONE)) != 0) || + ((psize & (psize-SIZE_T_ONE)) != 0)) ABORT; mparams.granularity = gsize; mparams.page_size = psize; mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; #if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT | USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = - USE_LOCK_BIT | USE_MMAP_BIT | USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ #if !ONLY_MSPACES /* Set up lock for main malloc area */ @@ -3349,69 +3210,57 @@ static int init_mparams(void) { #endif { - #if USE_DEV_RANDOM - int fd; + int fd; unsigned char buf[sizeof(size_t)]; /* Try to use /dev/urandom, else fall back on using time */ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && read(fd, buf, sizeof(buf)) == sizeof(buf)) { - - magic = *((size_t *)buf); + magic = *((size_t *) buf); close(fd); - - } else - -#endif /* USE_DEV_RANDOM */ + } + else +#endif /* USE_DEV_RANDOM */ #ifdef WIN32 - magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); + magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); #elif defined(LACKS_TIME_H) magic = (size_t)&magic ^ (size_t)0x55555555U; #else magic = (size_t)(time(0) ^ (size_t)0x55555555U); #endif - magic |= (size_t)8U; /* ensure nonzero */ - magic &= ~(size_t)7U; /* improve chances of fault for bad values */ + magic |= (size_t)8U; /* ensure nonzero */ + magic &= ~(size_t)7U; /* improve chances of fault for bad values */ /* Until memory modes commonly available, use volatile-write */ (*(volatile size_t *)(&(mparams.magic))) = magic; - } - } RELEASE_MALLOC_GLOBAL_LOCK(); return 1; - } /* support for mallopt */ static int change_mparam(int param_number, int value) { - size_t val; ensure_initialization(); - val = (value == -1) ? MAX_SIZE_T : (size_t)value; - switch (param_number) { - - case M_TRIM_THRESHOLD: - mparams.trim_threshold = val; - return 1; - case M_GRANULARITY: - if (val >= mparams.page_size && ((val & (val - 1)) == 0)) { - - mparams.granularity = val; - return 1; - - } else - - return 0; - case M_MMAP_THRESHOLD: - mparams.mmap_threshold = val; + val = (value == -1)? MAX_SIZE_T : (size_t)value; + switch(param_number) { + case M_TRIM_THRESHOLD: + mparams.trim_threshold = val; + return 1; + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; return 1; - default: + } + else return 0; - + case M_MMAP_THRESHOLD: + mparams.mmap_threshold = val; + return 1; + default: + return 0; } - } #if DEBUG @@ -3419,118 +3268,100 @@ static int change_mparam(int param_number, int value) { /* Check properties of any chunk, whether free, inuse, mmapped etc */ static void do_check_any_chunk(mstate m, mchunkptr p) { - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); assert(ok_address(m, p)); - } /* Check properties of top chunk */ static void do_check_top_chunk(mstate m, mchunkptr p) { - - msegmentptr sp = segment_holding(m, (char *)p); - size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ assert(sp != 0); assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); assert(ok_address(m, p)); assert(sz == m->topsize); assert(sz > 0); - assert(sz == ((sp->base + sp->size) - (char *)p) - TOP_FOOT_SIZE); + assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); assert(pinuse(p)); assert(!pinuse(chunk_plus_offset(p, sz))); - } /* Check properties of (inuse) mmapped chunks */ static void do_check_mmapped_chunk(mstate m, mchunkptr p) { - - size_t sz = chunksize(p); + size_t sz = chunksize(p); size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); assert(is_mmapped(p)); assert(use_mmap(m)); assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); assert(ok_address(m, p)); assert(!is_small(sz)); - assert((len & (mparams.page_size - SIZE_T_ONE)) == 0); + assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); - assert(chunk_plus_offset(p, sz + SIZE_T_SIZE)->head == 0); - + assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); } /* Check properties of inuse chunks */ static void do_check_inuse_chunk(mstate m, mchunkptr p) { - do_check_any_chunk(m, p); assert(is_inuse(p)); assert(next_pinuse(p)); /* If not pinuse and not mmapped, previous chunk has OK offset */ assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); - if (is_mmapped(p)) do_check_mmapped_chunk(m, p); - + if (is_mmapped(p)) + do_check_mmapped_chunk(m, p); } /* Check properties of free chunks */ static void do_check_free_chunk(mstate m, mchunkptr p) { - - size_t sz = chunksize(p); + size_t sz = chunksize(p); mchunkptr next = chunk_plus_offset(p, sz); do_check_any_chunk(m, p); assert(!is_inuse(p)); assert(!next_pinuse(p)); - assert(!is_mmapped(p)); + assert (!is_mmapped(p)); if (p != m->dv && p != m->top) { - if (sz >= MIN_CHUNK_SIZE) { - assert((sz & CHUNK_ALIGN_MASK) == 0); assert(is_aligned(chunk2mem(p))); assert(next->prev_foot == sz); assert(pinuse(p)); - assert(next == m->top || is_inuse(next)); + assert (next == m->top || is_inuse(next)); assert(p->fd->bk == p); assert(p->bk->fd == p); - - } else /* markers are always of size SIZE_T_SIZE */ - + } + else /* markers are always of size SIZE_T_SIZE */ assert(sz == SIZE_T_SIZE); - } - } /* Check properties of malloced chunks at the point they are malloced */ -static void do_check_malloced_chunk(mstate m, void *mem, size_t s) { - +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~INUSE_BITS; + size_t sz = p->head & ~INUSE_BITS; do_check_inuse_chunk(m, p); assert((sz & CHUNK_ALIGN_MASK) == 0); assert(sz >= MIN_CHUNK_SIZE); assert(sz >= s); /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); - } - } /* Check a tree and its subtrees. */ static void do_check_tree(mstate m, tchunkptr t) { - tchunkptr head = 0; tchunkptr u = t; - bindex_t tindex = t->index; - size_t tsize = chunksize(t); - bindex_t idx; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; compute_tree_index(tsize, idx); assert(tindex == idx); assert(tsize >= MIN_LARGE_SIZE); assert(tsize >= minsize_for_tree_index(idx)); - assert((idx == NTREEBINS - 1) || (tsize < minsize_for_tree_index((idx + 1)))); + assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); - do { /* traverse through chain of same-sized nodes */ + do { /* traverse through chain of same-sized nodes */ do_check_any_chunk(m, ((mchunkptr)u)); assert(u->index == tindex); assert(chunksize(u) == tsize); @@ -3539,72 +3370,56 @@ static void do_check_tree(mstate m, tchunkptr t) { assert(u->fd->bk == u); assert(u->bk->fd == u); if (u->parent == 0) { - assert(u->child[0] == 0); assert(u->child[1] == 0); - - } else { - - assert(head == 0); /* only one node on chain has parent */ + } + else { + assert(head == 0); /* only one node on chain has parent */ head = u; assert(u->parent != u); - assert(u->parent->child[0] == u || u->parent->child[1] == u || - *((tbinptr *)(u->parent)) == u); + assert (u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); if (u->child[0] != 0) { - assert(u->child[0]->parent == u); assert(u->child[0] != u); do_check_tree(m, u->child[0]); - } - if (u->child[1] != 0) { - assert(u->child[1]->parent == u); assert(u->child[1] != u); do_check_tree(m, u->child[1]); - } - if (u->child[0] != 0 && u->child[1] != 0) { - assert(chunksize(u->child[0]) < chunksize(u->child[1])); - } - } - u = u->fd; - } while (u != t); - assert(head != 0); - } /* Check all the chunks in a treebin. */ static void do_check_treebin(mstate m, bindex_t i) { - - tbinptr * tb = treebin_at(m, i); + tbinptr* tb = treebin_at(m, i); tchunkptr t = *tb; - int empty = (m->treemap & (1U << i)) == 0; - if (t == 0) assert(empty); - if (!empty) do_check_tree(m, t); - + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(empty); + if (!empty) + do_check_tree(m, t); } /* Check all the chunks in a smallbin. */ static void do_check_smallbin(mstate m, bindex_t i) { - - sbinptr b = smallbin_at(m, i); - mchunkptr p = b->bk; + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; unsigned int empty = (m->smallmap & (1U << i)) == 0; - if (p == b) assert(empty); + if (p == b) + assert(empty); if (!empty) { - for (; p != b; p = p->bk) { - - size_t size = chunksize(p); + size_t size = chunksize(p); mchunkptr q; /* each chunk claims to be free */ do_check_free_chunk(m, p); @@ -3613,249 +3428,185 @@ static void do_check_smallbin(mstate m, bindex_t i) { assert(p->bk == b || chunksize(p->bk) == chunksize(p)); /* chunk is followed by an inuse chunk */ q = next_chunk(p); - if (q->head != FENCEPOST_HEAD) do_check_inuse_chunk(m, q); - + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); } - } - } /* Find x in a bin. Used in other check functions. */ static int bin_find(mstate m, mchunkptr x) { - size_t size = chunksize(x); if (is_small(size)) { - bindex_t sidx = small_index(size); - sbinptr b = smallbin_at(m, sidx); + sbinptr b = smallbin_at(m, sidx); if (smallmap_is_marked(m, sidx)) { - mchunkptr p = b; do { - - if (p == x) return 1; - + if (p == x) + return 1; } while ((p = p->fd) != b); - } - - } else { - + } + else { bindex_t tidx; compute_tree_index(size, tidx); if (treemap_is_marked(m, tidx)) { - tchunkptr t = *treebin_at(m, tidx); - size_t sizebits = size << leftshift_for_tree_index(tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); while (t != 0 && chunksize(t) != size) { - - t = t->child[(sizebits >> (SIZE_T_BITSIZE - SIZE_T_ONE)) & 1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; sizebits <<= 1; - } - if (t != 0) { - tchunkptr u = t; do { - - if (u == (tchunkptr)x) return 1; - + if (u == (tchunkptr)x) + return 1; } while ((u = u->fd) != t); - } - } - } - return 0; - } /* Traverse each chunk and check it; return total */ static size_t traverse_and_check(mstate m) { - size_t sum = 0; if (is_initialized(m)) { - msegmentptr s = &m->seg; sum += m->topsize + TOP_FOOT_SIZE; while (s != 0) { - mchunkptr q = align_as_chunk(s->base); mchunkptr lastq = 0; assert(pinuse(q)); - while (segment_holds(s, q) && q != m->top && q->head != FENCEPOST_HEAD) { - + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { sum += chunksize(q); if (is_inuse(q)) { - assert(!bin_find(m, q)); do_check_inuse_chunk(m, q); - - } else { - + } + else { assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ + assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ do_check_free_chunk(m, q); - } - lastq = q; q = next_chunk(q); - } - s = s->next; - } - } - return sum; - } + /* Check all properties of malloc_state. */ static void do_check_malloc_state(mstate m) { - bindex_t i; - size_t total; + size_t total; /* check bins */ for (i = 0; i < NSMALLBINS; ++i) do_check_smallbin(m, i); for (i = 0; i < NTREEBINS; ++i) do_check_treebin(m, i); - if (m->dvsize != 0) { /* check dv chunk */ + if (m->dvsize != 0) { /* check dv chunk */ do_check_any_chunk(m, m->dv); assert(m->dvsize == chunksize(m->dv)); assert(m->dvsize >= MIN_CHUNK_SIZE); assert(bin_find(m, m->dv) == 0); - } - if (m->top != 0) { /* check top chunk */ + if (m->top != 0) { /* check top chunk */ do_check_top_chunk(m, m->top); /*assert(m->topsize == chunksize(m->top)); redundant */ assert(m->topsize > 0); assert(bin_find(m, m->top) == 0); - } total = traverse_and_check(m); assert(total <= m->footprint); assert(m->footprint <= m->max_footprint); - } - -#endif /* DEBUG */ +#endif /* DEBUG */ /* ----------------------------- statistics ------------------------------ */ #if !NO_MALLINFO static struct mallinfo internal_mallinfo(mstate m) { - - struct mallinfo nm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ensure_initialization(); if (!PREACTION(m)) { - check_malloc_state(m); if (is_initialized(m)) { - - size_t nfree = SIZE_T_ONE; /* top always free */ - size_t mfree = m->topsize + TOP_FOOT_SIZE; - size_t sum = mfree; + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; msegmentptr s = &m->seg; while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && q != m->top && - q->head != FENCEPOST_HEAD) { - + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { size_t sz = chunksize(q); sum += sz; if (!is_inuse(q)) { - mfree += sz; ++nfree; - } - q = next_chunk(q); - } - s = s->next; - } - nm.arena = sum; - nm.ordblks = nfree; - nm.hblkhd = m->footprint - sum; - nm.usmblks = m->max_footprint; + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; nm.uordblks = m->footprint - mfree; nm.fordblks = mfree; nm.keepcost = m->topsize; - } POSTACTION(m); - } - return nm; - } - -#endif /* !NO_MALLINFO */ +#endif /* !NO_MALLINFO */ #if !NO_MALLOC_STATS static void internal_malloc_stats(mstate m) { - ensure_initialization(); if (!PREACTION(m)) { - size_t maxfp = 0; size_t fp = 0; size_t used = 0; check_malloc_state(m); if (is_initialized(m)) { - msegmentptr s = &m->seg; maxfp = m->max_footprint; fp = m->footprint; used = fp - (m->topsize + TOP_FOOT_SIZE); while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && q != m->top && - q->head != FENCEPOST_HEAD) { - - if (!is_inuse(q)) used -= chunksize(q); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!is_inuse(q)) + used -= chunksize(q); q = next_chunk(q); - } - s = s->next; - } - } - - POSTACTION(m); /* drop lock */ + POSTACTION(m); /* drop lock */ fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - } - } - -#endif /* NO_MALLOC_STATS */ +#endif /* NO_MALLOC_STATS */ /* ----------------------- Operations on smallbins ----------------------- */ @@ -3867,181 +3618,134 @@ static void internal_malloc_stats(mstate m) { */ /* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) \ - { \ - \ - bindex_t I = small_index(S); \ - mchunkptr B = smallbin_at(M, I); \ - mchunkptr F = B; \ - assert(S >= MIN_CHUNK_SIZE); \ - if (!smallmap_is_marked(M, I)) \ - mark_smallmap(M, I); \ - else if (RTCHECK(ok_address(M, B->fd))) \ - F = B->fd; \ - else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - B->fd = P; \ - F->bk = P; \ - P->fd = F; \ - P->bk = B; \ - \ - } +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert(S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} /* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) \ - { \ - \ - mchunkptr F = P->fd; \ - mchunkptr B = P->bk; \ - bindex_t I = small_index(S); \ - assert(P != B); \ - assert(P != F); \ - assert(chunksize(P) == small_index2size(I)); \ - if (RTCHECK(F == smallbin_at(M, I) || (ok_address(M, F) && F->bk == P))) { \ - \ - if (B == F) { \ - \ - clear_smallmap(M, I); \ - \ - } else if (RTCHECK(B == smallbin_at(M, I) || \ - \ - \ - (ok_address(M, B) && B->fd == P))) { \ - \ - F->bk = B; \ - B->fd = F; \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(B == smallbin_at(M,I) ||\ + (ok_address(M, B) && B->fd == P))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} /* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) \ - { \ - \ - mchunkptr F = P->fd; \ - assert(P != B); \ - assert(P != F); \ - assert(chunksize(P) == small_index2size(I)); \ - if (B == F) { \ - \ - clear_smallmap(M, I); \ - \ - } else if (RTCHECK(ok_address(M, F) && F->bk == P)) { \ - \ - F->bk = B; \ - B->fd = F; \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} /* Replace dv node, binning the old one */ /* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) \ - { \ - \ - size_t DVS = M->dvsize; \ - assert(is_small(DVS)); \ - if (DVS != 0) { \ - \ - mchunkptr DV = M->dv; \ - insert_small_chunk(M, DV, DVS); \ - \ - } \ - M->dvsize = S; \ - M->dv = P; \ - \ - } +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + assert(is_small(DVS));\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} /* ------------------------- Operations on trees ------------------------- */ /* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) \ - { \ - \ - tbinptr *H; \ - bindex_t I; \ - compute_tree_index(S, I); \ - H = treebin_at(M, I); \ - X->index = I; \ - X->child[0] = X->child[1] = 0; \ - if (!treemap_is_marked(M, I)) { \ - \ - mark_treemap(M, I); \ - *H = X; \ - X->parent = (tchunkptr)H; \ - X->fd = X->bk = X; \ - \ - } else { \ - \ - tchunkptr T = *H; \ - size_t K = S << leftshift_for_tree_index(I); \ - for (;;) { \ - \ - if (chunksize(T) != S) { \ - \ - tchunkptr *C = \ - &(T->child[(K >> (SIZE_T_BITSIZE - SIZE_T_ONE)) & 1]); \ - K <<= 1; \ - if (*C != 0) \ - T = *C; \ - else if (RTCHECK(ok_address(M, C))) { \ - \ - *C = X; \ - X->parent = T; \ - X->fd = X->bk = X; \ - break; \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - break; \ - \ - } \ - \ - } else { \ - \ - tchunkptr F = T->fd; \ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) { \ - \ - T->fd = F->bk = X; \ - X->fd = F; \ - X->bk = T; \ - X->parent = 0; \ - break; \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - break; \ - \ - } \ - \ - } \ - \ - } \ - \ - } \ - \ - } +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} /* Unlink steps: @@ -4060,149 +3764,104 @@ static void internal_malloc_stats(mstate m) { x's parent and children to x's replacement (or null if none). */ -#define unlink_large_chunk(M, X) \ - { \ - \ - tchunkptr XP = X->parent; \ - tchunkptr R; \ - if (X->bk != X) { \ - \ - tchunkptr F = X->fd; \ - R = X->bk; \ - if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) { \ - \ - F->bk = R; \ - R->fd = F; \ - \ - } else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } else { \ - \ - tchunkptr *RP; \ - if (((R = *(RP = &(X->child[1]))) != 0) || \ - ((R = *(RP = &(X->child[0]))) != 0)) { \ - \ - tchunkptr *CP; \ - while ((*(CP = &(R->child[1])) != 0) || \ - (*(CP = &(R->child[0])) != 0)) { \ - \ - R = *(RP = CP); \ - \ - } \ - if (RTCHECK(ok_address(M, RP))) \ - *RP = 0; \ - else { \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } \ - \ - } \ - if (XP != 0) { \ - \ - tbinptr *H = treebin_at(M, X->index); \ - if (X == *H) { \ - \ - if ((*H = R) == 0) clear_treemap(M, X->index); \ - \ - } else if (RTCHECK(ok_address(M, XP))) { \ - \ - if (XP->child[0] == X) \ - XP->child[0] = R; \ - else \ - XP->child[1] = R; \ - \ - } else \ - \ - \ - CORRUPTION_ERROR_ACTION(M); \ - if (R != 0) { \ - \ - if (RTCHECK(ok_address(M, R))) { \ - \ - tchunkptr C0, C1; \ - R->parent = XP; \ - if ((C0 = X->child[0]) != 0) { \ - \ - if (RTCHECK(ok_address(M, C0))) { \ - \ - R->child[0] = C0; \ - C0->parent = R; \ - \ - } else \ - \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - if ((C1 = X->child[1]) != 0) { \ - \ - if (RTCHECK(ok_address(M, C1))) { \ - \ - R->child[1] = C1; \ - C1->parent = R; \ - \ - } else \ - \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } else \ - \ - \ - CORRUPTION_ERROR_ACTION(M); \ - \ - } \ - \ - } \ - \ - } +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} /* Relays to large vs small bin operations */ -#define insert_chunk(M, P, S) \ - if (is_small(S)) insert_small_chunk(M, P, S) else { \ - \ - tchunkptr TP = (tchunkptr)(P); \ - insert_large_chunk(M, TP, S); \ - \ - } +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } -#define unlink_chunk(M, P, S) \ - if (is_small(S)) unlink_small_chunk(M, P, S) else { \ - \ - tchunkptr TP = (tchunkptr)(P); \ - unlink_large_chunk(M, TP); \ - \ - } /* Relays to internal calls to malloc/free from realloc, memalign etc */ #if ONLY_MSPACES - #define internal_malloc(m, b) mspace_malloc(m, b) - #define internal_free(m, mem) mspace_free(m, mem); -#else /* ONLY_MSPACES */ - #if MSPACES - #define internal_malloc(m, b) \ - ((m == gm) ? dlmalloc(b) : mspace_malloc(m, b)) - #define internal_free(m, mem) \ - if (m == gm) \ - dlfree(mem); \ - else \ - mspace_free(m, mem); - #else /* MSPACES */ - #define internal_malloc(m, b) dlmalloc(b) - #define internal_free(m, mem) dlfree(mem) - #endif /* MSPACES */ -#endif /* ONLY_MSPACES */ +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); +#else /* ONLY_MSPACES */ +#if MSPACES +#define internal_malloc(m, b)\ + ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) +#define internal_free(m, mem)\ + if (m == gm) dlfree(mem); else mspace_free(m,mem); +#else /* MSPACES */ +#define internal_malloc(m, b) dlmalloc(b) +#define internal_free(m, mem) dlfree(mem) +#endif /* MSPACES */ +#endif /* ONLY_MSPACES */ /* ----------------------- Direct-mmapping chunks ----------------------- */ @@ -4215,93 +3874,80 @@ static void internal_malloc_stats(mstate m) { */ /* Malloc using mmap */ -static void *mmap_alloc(mstate m, size_t nb) { - +static void* mmap_alloc(mstate m, size_t nb) { size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); if (m->footprint_limit != 0) { - size_t fp = m->footprint + mmsize; - if (fp <= m->footprint || fp > m->footprint_limit) return 0; - + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; } - - if (mmsize > nb) { /* Check for wrap around 0 */ - char *mm = (char *)(CALL_DIRECT_MMAP(mmsize)); + if (mmsize > nb) { /* Check for wrap around 0 */ + char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); if (mm != CMFAIL) { - - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; + size_t offset = align_offset(chunk2mem(mm)); + size_t psize = mmsize - offset - MMAP_FOOT_PAD; mchunkptr p = (mchunkptr)(mm + offset); p->prev_foot = offset; p->head = psize; mark_inuse_foot(m, p, psize); chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize + SIZE_T_SIZE)->head = 0; + chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - if (m->least_addr == 0 || mm < m->least_addr) m->least_addr = mm; + if (m->least_addr == 0 || mm < m->least_addr) + m->least_addr = mm; if ((m->footprint += mmsize) > m->max_footprint) m->max_footprint = m->footprint; assert(is_aligned(chunk2mem(p))); check_mmapped_chunk(m, p); return chunk2mem(p); - } - } - return 0; - } /* Realloc using mmap */ static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { - size_t oldsize = chunksize(oldp); - (void)flags; /* placate people compiling -Wunused */ - if (is_small(nb)) /* Can't shrink mmap regions below small size */ + (void)flags; /* placate people compiling -Wunused */ + if (is_small(nb)) /* Can't shrink mmap regions below small size */ return 0; /* Keep old chunk if big enough but not too big */ if (oldsize >= nb + SIZE_T_SIZE && (oldsize - nb) <= (mparams.granularity << 1)) return oldp; else { - size_t offset = oldp->prev_foot; size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - char * cp = - (char *)CALL_MREMAP((char *)oldp - offset, oldmmsize, newmmsize, flags); + char* cp = (char*)CALL_MREMAP((char*)oldp - offset, + oldmmsize, newmmsize, flags); if (cp != CMFAIL) { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; + size_t psize = newmmsize - offset - MMAP_FOOT_PAD; newp->head = psize; mark_inuse_foot(m, newp, psize); chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize + SIZE_T_SIZE)->head = 0; + chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - if (cp < m->least_addr) m->least_addr = cp; + if (cp < m->least_addr) + m->least_addr = cp; if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) m->max_footprint = m->footprint; check_mmapped_chunk(m, newp); return newp; - } - } - return 0; - } + /* -------------------------- mspace management -------------------------- */ /* Initialize top chunk and its size */ static void init_top(mstate m, mchunkptr p, size_t psize) { - /* Ensure alignment */ size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char *)p + offset); + p = (mchunkptr)((char*)p + offset); psize -= offset; m->top = p; @@ -4309,29 +3955,23 @@ static void init_top(mstate m, mchunkptr p, size_t psize) { p->head = psize | PINUSE_BIT; /* set size of fake trailing chunk holding overhead space only once */ chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ - + m->trim_check = mparams.trim_threshold; /* reset on each update */ } /* Initialize bins for a new mstate that is otherwise zeroed out */ static void init_bins(mstate m) { - /* Establish circular links for smallbins */ bindex_t i; for (i = 0; i < NSMALLBINS; ++i) { - - sbinptr bin = smallbin_at(m, i); + sbinptr bin = smallbin_at(m,i); bin->fd = bin->bk = bin; - } - } #if PROCEED_ON_ERROR /* default corruption action */ static void reset_on_error(mstate m) { - int i; ++malloc_corruption_error_count; /* Reinitialize fields to forget about all memory */ @@ -4344,78 +3984,67 @@ static void reset_on_error(mstate m) { for (i = 0; i < NTREEBINS; ++i) *treebin_at(m, i) = 0; init_bins(m); - } - -#endif /* PROCEED_ON_ERROR */ +#endif /* PROCEED_ON_ERROR */ /* Allocate chunk and prepend remainder with chunk in successor base. */ -static void *prepend_alloc(mstate m, char *newbase, char *oldbase, size_t nb) { - +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { mchunkptr p = align_as_chunk(newbase); mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char *)oldfirst - (char *)p; + size_t psize = (char*)oldfirst - (char*)p; mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; + size_t qsize = psize - nb; set_size_and_pinuse_of_inuse_chunk(m, p, nb); - assert((char *)oldfirst > (char *)q); + assert((char*)oldfirst > (char*)q); assert(pinuse(oldfirst)); assert(qsize >= MIN_CHUNK_SIZE); /* consolidate remainder with first chunk of old base */ if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; m->top = q; q->head = tsize | PINUSE_BIT; check_top_chunk(m, q); - - } else if (oldfirst == m->dv) { - + } + else if (oldfirst == m->dv) { size_t dsize = m->dvsize += qsize; m->dv = q; set_size_and_pinuse_of_free_chunk(q, dsize); - - } else { - + } + else { if (!is_inuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); unlink_chunk(m, oldfirst, nsize); oldfirst = chunk_plus_offset(oldfirst, nsize); qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); insert_chunk(m, q, qsize); check_free_chunk(m, q); - } check_malloced_chunk(m, chunk2mem(p), nb); return chunk2mem(p); - } /* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char *tbase, size_t tsize, flag_t mmapped) { - +static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { /* Determine locations and sizes of segment, fenceposts, old top */ - char * old_top = (char *)m->top; + char* old_top = (char*)m->top; msegmentptr oldsp = segment_holding(m, old_top); - char * old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char * rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char * asp = rawsp + offset; - char * csp = (asp < (old_top + MIN_CHUNK_SIZE)) ? old_top : asp; - mchunkptr sp = (mchunkptr)csp; + char* old_end = oldsp->base + oldsp->size; + size_t ssize = pad_request(sizeof(struct malloc_segment)); + char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t offset = align_offset(chunk2mem(rawsp)); + char* asp = rawsp + offset; + char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; + mchunkptr sp = (mchunkptr)csp; msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; + mchunkptr tnext = chunk_plus_offset(sp, ssize); + mchunkptr p = tnext; + int nfences = 0; /* reset top to new space */ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); @@ -4423,7 +4052,7 @@ static void add_segment(mstate m, char *tbase, size_t tsize, flag_t mmapped) { /* Set up segment record */ assert(is_aligned(ss)); set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ + *ss = m->seg; /* Push current record */ m->seg.base = tbase; m->seg.size = tsize; m->seg.sflags = mmapped; @@ -4431,61 +4060,53 @@ static void add_segment(mstate m, char *tbase, size_t tsize, flag_t mmapped) { /* Insert trailing fenceposts */ for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); p->head = FENCEPOST_HEAD; ++nfences; - if ((char *)(&(nextp->head)) < old_end) + if ((char*)(&(nextp->head)) < old_end) p = nextp; else break; - } - assert(nfences >= 2); /* Insert the rest of old top into a bin as an ordinary free chunk */ if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; + size_t psize = csp - old_top; mchunkptr tn = chunk_plus_offset(q, psize); set_free_with_pinuse(q, psize, tn); insert_chunk(m, q, psize); - } check_top_chunk(m, m->top); - } /* -------------------------- System allocation -------------------------- */ /* Get memory from system using MORECORE or MMAP */ -static void *sys_alloc(mstate m, size_t nb) { - - char * tbase = CMFAIL; +static void* sys_alloc(mstate m, size_t nb) { + char* tbase = CMFAIL; size_t tsize = 0; flag_t mmap_flag = 0; - size_t asize; /* allocation size */ + size_t asize; /* allocation size */ ensure_initialization(); /* Directly map large chunks, but only if already initialized */ if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { - - void *mem = mmap_alloc(m, nb); - if (mem != 0) return mem; - + void* mem = mmap_alloc(m, nb); + if (mem != 0) + return mem; } asize = granularity_align(nb + SYS_ALLOC_PADDING); - if (asize <= nb) return 0; /* wraparound */ + if (asize <= nb) + return 0; /* wraparound */ if (m->footprint_limit != 0) { - size_t fp = m->footprint + asize; - if (fp <= m->footprint || fp > m->footprint_limit) return 0; - + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; } /* @@ -4511,119 +4132,91 @@ static void *sys_alloc(mstate m, size_t nb) { */ if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { - - char * br = CMFAIL; - size_t ssize = asize; /* sbrk call size */ - msegmentptr ss = (m->top == 0) ? 0 : segment_holding(m, (char *)m->top); + char* br = CMFAIL; + size_t ssize = asize; /* sbrk call size */ + msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); ACQUIRE_MALLOC_GLOBAL_LOCK(); - if (ss == 0) { /* First time through or recovery */ - char *base = (char *)CALL_MORECORE(0); + if (ss == 0) { /* First time through or recovery */ + char* base = (char*)CALL_MORECORE(0); if (base != CMFAIL) { - size_t fp; /* Adjust to end on a page boundary */ if (!is_page_aligned(base)) ssize += (page_align((size_t)base) - (size_t)base); - fp = m->footprint + ssize; /* recheck limits */ + fp = m->footprint + ssize; /* recheck limits */ if (ssize > nb && ssize < HALF_MAX_SIZE_T && (m->footprint_limit == 0 || (fp > m->footprint && fp <= m->footprint_limit)) && - (br = (char *)(CALL_MORECORE(ssize))) == base) { - + (br = (char*)(CALL_MORECORE(ssize))) == base) { tbase = base; tsize = ssize; - } - } - - } else { - + } + else { /* Subtract out existing available top space from MORECORE request. */ ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); /* Use mem here only if it did continuously extend old space */ if (ssize < HALF_MAX_SIZE_T && - (br = (char *)(CALL_MORECORE(ssize))) == ss->base + ss->size) { - + (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) { tbase = br; tsize = ssize; - } - } - if (tbase == CMFAIL) { /* Cope with partial failure */ - if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (ssize < HALF_MAX_SIZE_T && ssize < nb + SYS_ALLOC_PADDING) { - + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (ssize < HALF_MAX_SIZE_T && + ssize < nb + SYS_ALLOC_PADDING) { size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize); if (esize < HALF_MAX_SIZE_T) { - - char *end = (char *)CALL_MORECORE(esize); + char* end = (char*)CALL_MORECORE(esize); if (end != CMFAIL) ssize += esize; - else { /* Can't use; try to release */ - (void)CALL_MORECORE(-ssize); + else { /* Can't use; try to release */ + (void) CALL_MORECORE(-ssize); br = CMFAIL; - } - } - } - } - - if (br != CMFAIL) { /* Use the space we did get */ + if (br != CMFAIL) { /* Use the space we did get */ tbase = br; tsize = ssize; - - } else - - disable_contiguous(m); /* Don't try contiguous path in the future */ - + } + else + disable_contiguous(m); /* Don't try contiguous path in the future */ } RELEASE_MALLOC_GLOBAL_LOCK(); - } - if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - char *mp = (char *)(CALL_MMAP(asize)); + if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ + char* mp = (char*)(CALL_MMAP(asize)); if (mp != CMFAIL) { - tbase = mp; tsize = asize; mmap_flag = USE_MMAP_BIT; - } - } - if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ + if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ if (asize < HALF_MAX_SIZE_T) { - - char *br = CMFAIL; - char *end = CMFAIL; + char* br = CMFAIL; + char* end = CMFAIL; ACQUIRE_MALLOC_GLOBAL_LOCK(); - br = (char *)(CALL_MORECORE(asize)); - end = (char *)(CALL_MORECORE(0)); + br = (char*)(CALL_MORECORE(asize)); + end = (char*)(CALL_MORECORE(0)); RELEASE_MALLOC_GLOBAL_LOCK(); if (br != CMFAIL && end != CMFAIL && br < end) { - size_t ssize = end - br; if (ssize > nb + TOP_FOOT_SIZE) { - tbase = br; tsize = ssize; - } - } - } - } if (tbase != CMFAIL) { @@ -4631,8 +4224,9 @@ static void *sys_alloc(mstate m, size_t nb) { if ((m->footprint += tsize) > m->max_footprint) m->max_footprint = m->footprint; - if (!is_initialized(m)) { /* first-time initialization */ - if (m->least_addr == 0 || tbase < m->least_addr) m->least_addr = tbase; + if (!is_initialized(m)) { /* first-time initialization */ + if (m->least_addr == 0 || tbase < m->least_addr) + m->least_addr = tbase; m->seg.base = tbase; m->seg.size = tsize; m->seg.sflags = mmap_flag; @@ -4645,52 +4239,46 @@ static void *sys_alloc(mstate m, size_t nb) { else #endif { - /* Offset top by embedded malloc_state */ mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char *)mn) - TOP_FOOT_SIZE); - + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); } - } else { - /* Try to merge with an existing segment */ msegmentptr sp = &m->seg; /* Only consider most recent segment if traversal suppressed */ while (sp != 0 && tbase != sp->base + sp->size) sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && !is_extern_segment(sp) && + if (sp != 0 && + !is_extern_segment(sp) && (sp->sflags & USE_MMAP_BIT) == mmap_flag && - segment_holds(sp, m->top)) { /* append */ + segment_holds(sp, m->top)) { /* append */ sp->size += tsize; init_top(m, m->top, m->topsize + tsize); - - } else { - - if (tbase < m->least_addr) m->least_addr = tbase; + } + else { + if (tbase < m->least_addr) + m->least_addr = tbase; sp = &m->seg; while (sp != 0 && sp->base != tbase + tsize) sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && !is_extern_segment(sp) && + if (sp != 0 && + !is_extern_segment(sp) && (sp->sflags & USE_MMAP_BIT) == mmap_flag) { - - char *oldbase = sp->base; + char* oldbase = sp->base; sp->base = tbase; sp->size += tsize; return prepend_alloc(m, tbase, oldbase, nb); - - } else - + } + else add_segment(m, tbase, tsize, mmap_flag); - } - } - if (nb < m->topsize) { /* Allocate from new or extended top space */ - size_t rsize = m->topsize -= nb; + if (nb < m->topsize) { /* Allocate from new or extended top space */ + size_t rsize = m->topsize -= nb; mchunkptr p = m->top; mchunkptr r = m->top = chunk_plus_offset(p, nb); r->head = rsize | PINUSE_BIT; @@ -4698,421 +4286,313 @@ static void *sys_alloc(mstate m, size_t nb) { check_top_chunk(m, m->top); check_malloced_chunk(m, chunk2mem(p), nb); return chunk2mem(p); - } - } MALLOC_FAILURE_ACTION; return 0; - } /* ----------------------- system deallocation -------------------------- */ /* Unmap and unlink any mmapped segments that don't contain used chunks */ static size_t release_unused_segments(mstate m) { - - size_t released = 0; - int nsegs = 0; + size_t released = 0; + int nsegs = 0; msegmentptr pred = &m->seg; msegmentptr sp = pred->next; while (sp != 0) { - - char * base = sp->base; - size_t size = sp->size; + char* base = sp->base; + size_t size = sp->size; msegmentptr next = sp->next; ++nsegs; if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); + size_t psize = chunksize(p); /* Can unmap if first chunk holds entire segment and not pinned */ - if (!is_inuse(p) && (char *)p + psize >= base + size - TOP_FOOT_SIZE) { - + if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char *)sp)); + assert(segment_holds(sp, (char*)sp)); if (p == m->dv) { - m->dv = 0; m->dvsize = 0; - - } else { - + } + else { unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) { - released += size; m->footprint -= size; /* unlink obsoleted record */ sp = pred; sp->next = next; - - } else { /* back out if cannot unmap */ - + } + else { /* back out if cannot unmap */ insert_large_chunk(m, tp, psize); - } - } - } - - if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ + if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ break; pred = sp; sp = next; - } - /* Reset check counter */ - m->release_checks = (((size_t)nsegs > (size_t)MAX_RELEASE_CHECK_RATE) - ? (size_t)nsegs - : (size_t)MAX_RELEASE_CHECK_RATE); + m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? + (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE); return released; - } static int sys_trim(mstate m, size_t pad) { - size_t released = 0; ensure_initialization(); if (pad < MAX_REQUEST && is_initialized(m)) { - - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ + pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ if (m->topsize > pad) { - /* Shrink top space in granularity-size units, keeping at least one */ size_t unit = mparams.granularity; - size_t extra = - ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char *)m->top); + size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - + SIZE_T_ONE) * unit; + msegmentptr sp = segment_holding(m, (char*)m->top); if (!is_extern_segment(sp)) { - if (is_mmapped_segment(sp)) { - - if (HAVE_MMAP && sp->size >= extra && - !has_segment_link(m, sp)) { /* can't shrink if pinned */ + if (HAVE_MMAP && + sp->size >= extra && + !has_segment_link(m, sp)) { /* can't shrink if pinned */ size_t newsize = sp->size - extra; - (void)newsize; /* placate people compiling -Wunused-variable */ + (void)newsize; /* placate people compiling -Wunused-variable */ /* Prefer mremap, fall back to munmap */ if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { - released = extra; - } - } - - } else if (HAVE_MORECORE) { - - if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ + } + else if (HAVE_MORECORE) { + if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; ACQUIRE_MALLOC_GLOBAL_LOCK(); { - /* Make sure end of memory is where we last set it. */ - char *old_br = (char *)(CALL_MORECORE(0)); + char* old_br = (char*)(CALL_MORECORE(0)); if (old_br == sp->base + sp->size) { - - char *rel_br = (char *)(CALL_MORECORE(-extra)); - char *new_br = (char *)(CALL_MORECORE(0)); + char* rel_br = (char*)(CALL_MORECORE(-extra)); + char* new_br = (char*)(CALL_MORECORE(0)); if (rel_br != CMFAIL && new_br < old_br) released = old_br - new_br; - } - } - RELEASE_MALLOC_GLOBAL_LOCK(); - } - } if (released != 0) { - sp->size -= released; m->footprint -= released; init_top(m, m->top, m->topsize - released); check_top_chunk(m, m->top); - } - } /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) released += release_unused_segments(m); + if (HAVE_MMAP) + released += release_unused_segments(m); /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0 && m->topsize > m->trim_check) m->trim_check = MAX_SIZE_T; - + if (released == 0 && m->topsize > m->trim_check) + m->trim_check = MAX_SIZE_T; } - return (released != 0) ? 1 : 0; - + return (released != 0)? 1 : 0; } /* Consolidate and bin a chunk. Differs from exported versions of free mainly in that the chunk need not be marked as inuse. */ static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { - mchunkptr next = chunk_plus_offset(p, psize); if (!pinuse(p)) { - mchunkptr prev; - size_t prevsize = p->prev_foot; + size_t prevsize = p->prev_foot; if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char *)p - prevsize, psize) == 0) m->footprint -= psize; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + m->footprint -= psize; return; - } - prev = chunk_minus_offset(p, prevsize); psize += prevsize; p = prev; - if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ + if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ if (p != m->dv) { - unlink_chunk(m, p, prevsize); - - } else if ((next->head & INUSE_BITS) == INUSE_BITS) { - + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { m->dvsize = psize; set_free_with_pinuse(p, psize, next); return; - } - - } else { - + } + else { CORRUPTION_ERROR_ACTION(m); return; - } - } - if (RTCHECK(ok_address(m, next))) { - - if (!cinuse(next)) { /* consolidate forward */ + if (!cinuse(next)) { /* consolidate forward */ if (next == m->top) { - size_t tsize = m->topsize += psize; m->top = p; p->head = tsize | PINUSE_BIT; if (p == m->dv) { - m->dv = 0; m->dvsize = 0; - } - return; - - } else if (next == m->dv) { - + } + else if (next == m->dv) { size_t dsize = m->dvsize += psize; m->dv = p; set_size_and_pinuse_of_free_chunk(p, dsize); return; - - } else { - + } + else { size_t nsize = chunksize(next); psize += nsize; unlink_chunk(m, next, nsize); set_size_and_pinuse_of_free_chunk(p, psize); if (p == m->dv) { - m->dvsize = psize; return; - } - } - - } else { - + } + else { set_free_with_pinuse(p, psize, next); - } - insert_chunk(m, p, psize); - - } else { - + } + else { CORRUPTION_ERROR_ACTION(m); - } - } /* ---------------------------- malloc --------------------------- */ /* allocate a large request from the best fitting chunk in a treebin */ -static void *tmalloc_large(mstate m, size_t nb) { - +static void* tmalloc_large(mstate m, size_t nb) { tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ + size_t rsize = -nb; /* Unsigned negation */ tchunkptr t; - bindex_t idx; + bindex_t idx; compute_tree_index(nb, idx); if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; + size_t trem = chunksize(t) - nb; if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) break; - + if ((rsize = trem) == 0) + break; } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE - SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) rst = rt; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; if (t == 0) { - - t = rst; /* set t to least subtree holding sizes > nb */ + t = rst; /* set t to least subtree holding sizes > nb */ break; - } - sizebits <<= 1; - } - } - - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; if (leftbits != 0) { - bindex_t i; binmap_t leastbit = least_bit(leftbits); compute_bit2idx(leastbit, i); t = *treebin_at(m, i); - } - } - while (t != 0) { /* find smallest of tree or subtree */ + while (t != 0) { /* find smallest of tree or subtree */ size_t trem = chunksize(t) - nb; if (trem < rsize) { - rsize = trem; v = t; - } - t = leftmost_child(t); - } /* If dv is a better fit, return 0 so malloc will use it */ if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - - if (RTCHECK(ok_address(m, v))) { /* split */ + if (RTCHECK(ok_address(m, v))) { /* split */ mchunkptr r = chunk_plus_offset(v, nb); assert(chunksize(v) == rsize + nb); if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); if (rsize < MIN_CHUNK_SIZE) set_inuse_and_pinuse(m, v, (rsize + nb)); else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); set_size_and_pinuse_of_free_chunk(r, rsize); insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; - } /* allocate a small request from the best fitting chunk in a treebin */ -static void *tmalloc_small(mstate m, size_t nb) { - +static void* tmalloc_small(mstate m, size_t nb) { tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); compute_bit2idx(leastbit, i); v = t = *treebin_at(m, i); rsize = chunksize(t) - nb; while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; if (trem < rsize) { - rsize = trem; v = t; - } - } if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); assert(chunksize(v) == rsize + nb); if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); if (rsize < MIN_CHUNK_SIZE) set_inuse_and_pinuse(m, v, (rsize + nb)); else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); set_size_and_pinuse_of_free_chunk(r, rsize); replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } CORRUPTION_ERROR_ACTION(m); return 0; - } #if !ONLY_MSPACES -void *dlmalloc(size_t bytes) { - +void* dlmalloc(size_t bytes) { /* Basic algorithm: If a small request (< 256 bytes minus per-chunk overhead): @@ -5136,25 +4616,23 @@ void *dlmalloc(size_t bytes) { The ugly goto's here ensure that postaction occurs along all paths. */ - #if USE_LOCKS - ensure_initialization(); /* initialize in sys_alloc if not using locks */ - #endif +#if USE_LOCKS + ensure_initialization(); /* initialize in sys_alloc if not using locks */ +#endif if (!PREACTION(gm)) { - - void * mem; + void* mem; size_t nb; if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; binmap_t smallbits; - nb = (bytes < MIN_REQUEST) ? MIN_CHUNK_SIZE : pad_request(bytes); + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); idx = small_index(nb); smallbits = gm->smallmap >> idx; - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ + idx += ~smallbits & 1; /* Uses next bin if idx empty */ b = smallbin_at(gm, idx); p = b->fd; assert(chunksize(p) == small_index2size(idx)); @@ -5163,17 +4641,15 @@ void *dlmalloc(size_t bytes) { mem = chunk2mem(p); check_malloced_chunk(gm, mem, nb); goto postaction; - } else if (nb > gm->dvsize) { - - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); compute_bit2idx(leastbit, i); b = smallbin_at(gm, i); p = b->fd; @@ -5184,71 +4660,54 @@ void *dlmalloc(size_t bytes) { if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) set_inuse_and_pinuse(gm, p, small_index2size(i)); else { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); r = chunk_plus_offset(p, nb); set_size_and_pinuse_of_free_chunk(r, rsize); replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); check_malloced_chunk(gm, mem, nb); goto postaction; - } else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); goto postaction; - } - } - - } else if (bytes >= MAX_REQUEST) - + } + else if (bytes >= MAX_REQUEST) nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ else { - nb = pad_request(bytes); if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); goto postaction; - } - } if (nb <= gm->dvsize) { - - size_t rsize = gm->dvsize - nb; + size_t rsize = gm->dvsize - nb; mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ mchunkptr r = gm->dv = chunk_plus_offset(p, nb); gm->dvsize = rsize; set_size_and_pinuse_of_free_chunk(r, rsize); set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - - } else { /* exhaust dv */ - + } + else { /* exhaust dv */ size_t dvs = gm->dvsize; gm->dvsize = 0; gm->dv = 0; set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); check_malloced_chunk(gm, mem, nb); goto postaction; - } - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; + else if (nb < gm->topsize) { /* Split top */ + size_t rsize = gm->topsize -= nb; mchunkptr p = gm->top; mchunkptr r = gm->top = chunk_plus_offset(p, nb); r->head = rsize | PINUSE_BIT; @@ -5257,7 +4716,6 @@ void *dlmalloc(size_t bytes) { check_top_chunk(gm, gm->top); check_malloced_chunk(gm, mem, nb); goto postaction; - } mem = sys_alloc(gm, nb); @@ -5265,17 +4723,14 @@ void *dlmalloc(size_t bytes) { postaction: POSTACTION(gm); return mem; - } return 0; - } /* ---------------------------- free --------------------------- */ -void dlfree(void *mem) { - +void dlfree(void* mem) { /* Consolidate freed chunks with preceeding or succeeding bordering free chunks, if they exist, and then place in a bin. Intermixed @@ -5283,216 +4738,164 @@ void dlfree(void *mem) { */ if (mem != 0) { - - mchunkptr p = mem2chunk(mem); - #if FOOTERS + mchunkptr p = mem2chunk(mem); +#if FOOTERS mstate fm = get_mstate_for(p); if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); return; - } - - #else /* FOOTERS */ - #define fm gm - #endif /* FOOTERS */ +#else /* FOOTERS */ +#define fm gm +#endif /* FOOTERS */ if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - - size_t psize = chunksize(p); + size_t psize = chunksize(p); mchunkptr next = chunk_plus_offset(p, psize); if (!pinuse(p)) { - size_t prevsize = p->prev_foot; if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char *)p - prevsize, psize) == 0) + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) fm->footprint -= psize; goto postaction; - - } else { - + } + else { mchunkptr prev = chunk_minus_offset(p, prevsize); psize += prevsize; p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - - } else if ((next->head & INUSE_BITS) == INUSE_BITS) { - + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { fm->dvsize = psize; set_free_with_pinuse(p, psize, next); goto postaction; - } - - } else - + } + else goto erroraction; - } - } if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - - if (!cinuse(next)) { /* consolidate forward */ + if (!cinuse(next)) { /* consolidate forward */ if (next == fm->top) { - size_t tsize = fm->topsize += psize; fm->top = p; p->head = tsize | PINUSE_BIT; if (p == fm->dv) { - fm->dv = 0; fm->dvsize = 0; - } - - if (should_trim(fm, tsize)) sys_trim(fm, 0); + if (should_trim(fm, tsize)) + sys_trim(fm, 0); goto postaction; - - } else if (next == fm->dv) { - + } + else if (next == fm->dv) { size_t dsize = fm->dvsize += psize; fm->dv = p; set_size_and_pinuse_of_free_chunk(p, dsize); goto postaction; - - } else { - + } + else { size_t nsize = chunksize(next); psize += nsize; unlink_chunk(fm, next, nsize); set_size_and_pinuse_of_free_chunk(p, psize); if (p == fm->dv) { - fm->dvsize = psize; goto postaction; - } - } - - } else - + } + else set_free_with_pinuse(p, psize, next); if (is_small(psize)) { - insert_small_chunk(fm, p, psize); check_free_chunk(fm, p); - - } else { - + } + else { tchunkptr tp = (tchunkptr)p; insert_large_chunk(fm, tp, psize); check_free_chunk(fm, p); - if (--fm->release_checks == 0) release_unused_segments(fm); - + if (--fm->release_checks == 0) + release_unused_segments(fm); } - goto postaction; - } - } - erroraction: USAGE_ERROR_ACTION(fm, p); postaction: POSTACTION(fm); - } - } - - #if !FOOTERS - #undef fm - #endif /* FOOTERS */ - +#if !FOOTERS +#undef fm +#endif /* FOOTERS */ } -void *dlcalloc(size_t n_elements, size_t elem_size) { - - void * mem; +void* dlcalloc(size_t n_elements, size_t elem_size) { + void* mem; size_t req = 0; if (n_elements != 0) { - req = n_elements * elem_size; if (((n_elements | elem_size) & ~(size_t)0xffff) && (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - + req = MAX_SIZE_T; /* force downstream failure on overflow */ } - mem = dlmalloc(req); if (mem != 0 && calloc_must_clear(mem2chunk(mem))) __builtin_memset(mem, 0, req); return mem; - } -#endif /* !ONLY_MSPACES */ +#endif /* !ONLY_MSPACES */ /* ------------ Internal support for realloc, memalign, etc -------------- */ /* Try to realloc; only in-place unless can_move true */ static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, int can_move) { - mchunkptr newp = 0; - size_t oldsize = chunksize(p); + size_t oldsize = chunksize(p); mchunkptr next = chunk_plus_offset(p, oldsize); - if (RTCHECK(ok_address(m, p) && ok_inuse(p) && ok_next(p, next) && - ok_pinuse(next))) { - + if (RTCHECK(ok_address(m, p) && ok_inuse(p) && + ok_next(p, next) && ok_pinuse(next))) { if (is_mmapped(p)) { - newp = mmap_resize(m, p, nb, can_move); - - } else if (oldsize >= nb) { /* already big enough */ - + } + else if (oldsize >= nb) { /* already big enough */ size_t rsize = oldsize - nb; - if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ + if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ mchunkptr r = chunk_plus_offset(p, nb); set_inuse(m, p, nb); set_inuse(m, r, rsize); dispose_chunk(m, r, rsize); - } - newp = p; - - } else if (next == m->top) { /* extend into top */ - + } + else if (next == m->top) { /* extend into top */ if (oldsize + m->topsize > nb) { - - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; mchunkptr newtop = chunk_plus_offset(p, nb); set_inuse(m, p, nb); - newtop->head = newtopsize | PINUSE_BIT; + newtop->head = newtopsize |PINUSE_BIT; m->top = newtop; m->topsize = newtopsize; newp = p; - } - - } else if (next == m->dv) { /* extend into dv */ - + } + else if (next == m->dv) { /* extend into dv */ size_t dvs = m->dvsize; if (oldsize + dvs >= nb) { - size_t dsize = oldsize + dvs - nb; if (dsize >= MIN_CHUNK_SIZE) { - mchunkptr r = chunk_plus_offset(p, nb); mchunkptr n = chunk_plus_offset(r, dsize); set_inuse(m, p, nb); @@ -5500,87 +4903,64 @@ static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, clear_pinuse(n); m->dvsize = dsize; m->dv = r; - - } else { /* exhaust dv */ - + } + else { /* exhaust dv */ size_t newsize = oldsize + dvs; set_inuse(m, p, newsize); m->dvsize = 0; m->dv = 0; - } - newp = p; - } - - } else if (!cinuse(next)) { /* extend into next free chunk */ - + } + else if (!cinuse(next)) { /* extend into next free chunk */ size_t nextsize = chunksize(next); if (oldsize + nextsize >= nb) { - size_t rsize = oldsize + nextsize - nb; unlink_chunk(m, next, nextsize); if (rsize < MIN_CHUNK_SIZE) { - size_t newsize = oldsize + nextsize; set_inuse(m, p, newsize); - - } else { - + } + else { mchunkptr r = chunk_plus_offset(p, nb); set_inuse(m, p, nb); set_inuse(m, r, rsize); dispose_chunk(m, r, rsize); - } - newp = p; - } - } - - } else { - + } + else { USAGE_ERROR_ACTION(m, chunk2mem(p)); - } - return newp; - } -static void *internal_memalign(mstate m, size_t alignment, size_t bytes) { - - void *mem = 0; - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment - SIZE_T_ONE)) != 0) { /* Ensure a power of 2 */ + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) - a <<= 1; + while (a < alignment) a <<= 1; alignment = a; - } - if (bytes >= MAX_REQUEST - alignment) { - - if (m != 0) { /* Test isn't needed but avoids compiler warning */ + if (m != 0) { /* Test isn't needed but avoids compiler warning */ MALLOC_FAILURE_ACTION; - } - - } else { - + } + else { size_t nb = request2size(bytes); size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; mem = internal_malloc(m, req); if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + if (PREACTION(m)) + return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ /* Find an aligned spot inside chunk. Since we need to give back leading space in a chunk of at least MIN_CHUNK_SIZE, if @@ -5589,59 +4969,47 @@ static void *internal_memalign(mstate m, size_t alignment, size_t bytes) { We've allocated enough total room so that this is always possible. */ - char * br = (char *)mem2chunk((size_t)( - ((size_t)((char *)mem + alignment - SIZE_T_ONE)) & -alignment)); - char * pos = ((size_t)(br - (char *)(p)) >= MIN_CHUNK_SIZE) - ? br - : br + alignment; + char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char *)(p); - size_t newsize = chunksize(p) - leadsize; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ newp->prev_foot = p->prev_foot + leadsize; newp->head = newsize; - - } else { /* Otherwise, give back leader, use the rest */ - + } + else { /* Otherwise, give back leader, use the rest */ set_inuse(m, newp, newsize); set_inuse(m, p, leadsize); dispose_chunk(m, p, leadsize); - } - p = newp; - } /* Give back spare room at the end */ if (!is_mmapped(p)) { - size_t size = chunksize(p); if (size > nb + MIN_CHUNK_SIZE) { - - size_t remainder_size = size - nb; + size_t remainder_size = size - nb; mchunkptr remainder = chunk_plus_offset(p, nb); set_inuse(m, p, nb); set_inuse(m, remainder, remainder_size); dispose_chunk(m, remainder, remainder_size); - } - } mem = chunk2mem(p); - assert(chunksize(p) >= nb); + assert (chunksize(p) >= nb); assert(((size_t)mem & (alignment - 1)) == 0); check_inuse_chunk(m, p); POSTACTION(m); - } - } - return mem; - } /* @@ -5651,50 +5019,50 @@ static void *internal_memalign(mstate m, size_t alignment, size_t bytes) { bit 0 set if all elements are same size (using sizes[0]) bit 1 set if elements should be zeroed */ -static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts, - void *chunks[]) { - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void * mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void ** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ size_t size; size_t i; ensure_initialization(); /* compute array length, if needed */ if (chunks != 0) { - - if (n_elements == 0) return chunks; /* nothing to do */ + if (n_elements == 0) + return chunks; /* nothing to do */ marray = chunks; array_size = 0; - - } else { - + } + else { /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) return (void **)internal_malloc(m, 0); + if (n_elements == 0) + return (void**)internal_malloc(m, 0); marray = 0; - array_size = request2size(n_elements * (sizeof(void *))); - + array_size = request2size(n_elements * (sizeof(void*))); } /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ + if (opts & 0x1) { /* all-same-size */ element_size = request2size(*sizes); contents_size = n_elements * element_size; - - } else { /* add up all the sizes */ - + } + else { /* add up all the sizes */ element_size = 0; contents_size = 0; for (i = 0; i != n_elements; ++i) contents_size += request2size(sizes[i]); - } size = contents_size + array_size; @@ -5707,8 +5075,10 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts, was_enabled = use_mmap(m); disable_mmap(m); mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) enable_mmap(m); - if (mem == 0) return 0; + if (was_enabled) + enable_mmap(m); + if (mem == 0) + return 0; if (PREACTION(m)) return 0; p = mem2chunk(mem); @@ -5716,30 +5086,24 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts, assert(!is_mmapped(p)); - if (opts & 0x2) { /* optionally clear the elements */ - __builtin_memset((size_t *)mem, 0, - remainder_size - SIZE_T_SIZE - array_size); - + if (opts & 0x2) { /* optionally clear the elements */ + __builtin_memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); } /* If not provided, allocate the pointer array as final part of chunk */ if (marray == 0) { - - size_t array_chunk_size; + size_t array_chunk_size; array_chunk = chunk_plus_offset(p, contents_size); array_chunk_size = remainder_size - contents_size; - marray = (void **)(chunk2mem(array_chunk)); + marray = (void**) (chunk2mem(array_chunk)); set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); remainder_size = contents_size; - } /* split out elements */ - for (i = 0;; ++i) { - + for (i = 0; ; ++i) { marray[i] = chunk2mem(p); - if (i != n_elements - 1) { - + if (i != n_elements-1) { if (element_size != 0) size = element_size; else @@ -5747,42 +5111,31 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts, remainder_size -= size; set_size_and_pinuse_of_inuse_chunk(m, p, size); p = chunk_plus_offset(p, size); - - } else { /* the final element absorbs any overallocation slop */ - + } + else { /* the final element absorbs any overallocation slop */ set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); break; - } - } #if DEBUG if (marray != chunks) { - /* final element must have exactly exhausted chunk */ if (element_size != 0) { - assert(remainder_size == element_size); - - } else { - + } + else { assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) check_inuse_chunk(m, mem2chunk(marray[i])); -#endif /* DEBUG */ +#endif /* DEBUG */ POSTACTION(m); return marray; - } /* Try to free all pointers in the given array. @@ -5792,431 +5145,316 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts, chunks before freeing, which will occur often if allocated with ialloc or the array is sorted. */ -static size_t internal_bulk_free(mstate m, void *array[], size_t nelem) { - +static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { size_t unfreed = 0; if (!PREACTION(m)) { - - void **a; - void **fence = &(array[nelem]); + void** a; + void** fence = &(array[nelem]); for (a = array; a != fence; ++a) { - - void *mem = *a; + void* mem = *a; if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t psize = chunksize(p); + size_t psize = chunksize(p); #if FOOTERS if (get_mstate_for(p) != m) { - ++unfreed; continue; - } - #endif check_inuse_chunk(m, p); *a = 0; if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { - - void ** b = a + 1; /* try to merge with next chunk */ + void ** b = a + 1; /* try to merge with next chunk */ mchunkptr next = next_chunk(p); if (b != fence && *b == chunk2mem(next)) { - size_t newsize = chunksize(next) + psize; set_inuse(m, p, newsize); *b = chunk2mem(p); - - } else - + } + else dispose_chunk(m, p, psize); - - } else { - + } + else { CORRUPTION_ERROR_ACTION(m); break; - } - } - } - - if (should_trim(m, m->topsize)) sys_trim(m, 0); + if (should_trim(m, m->topsize)) + sys_trim(m, 0); POSTACTION(m); - } - return unfreed; - } /* Traversal */ #if MALLOC_INSPECT_ALL static void internal_inspect_all(mstate m, - void (*handler)(void *start, void *end, - size_t used_bytes, - void * callback_arg), - void *arg) { - + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { if (is_initialized(m)) { - - mchunkptr top = m->top; + mchunkptr top = m->top; msegmentptr s; for (s = &m->seg; s != 0; s = s->next) { - mchunkptr q = align_as_chunk(s->base); while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { - mchunkptr next = next_chunk(q); - size_t sz = chunksize(q); - size_t used; - void * start; + size_t sz = chunksize(q); + size_t used; + void* start; if (is_inuse(q)) { - - used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ + used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ start = chunk2mem(q); - - } else { - + } + else { used = 0; - if (is_small(sz)) { /* offset by possible bookkeeping */ - start = (void *)((char *)q + sizeof(struct malloc_chunk)); - - } else { - - start = (void *)((char *)q + sizeof(struct malloc_tree_chunk)); - + if (is_small(sz)) { /* offset by possible bookkeeping */ + start = (void*)((char*)q + sizeof(struct malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(struct malloc_tree_chunk)); } - } - - if (start < (void *)next) /* skip if all space is bookkeeping */ + if (start < (void*)next) /* skip if all space is bookkeeping */ handler(start, next, used, arg); - if (q == top) break; + if (q == top) + break; q = next; - } - } - } - } - -#endif /* MALLOC_INSPECT_ALL */ +#endif /* MALLOC_INSPECT_ALL */ /* ------------------ Exported realloc, memalign, etc -------------------- */ #if !ONLY_MSPACES -void *dlrealloc(void *oldmem, size_t bytes) { - - void *mem = 0; +void* dlrealloc(void* oldmem, size_t bytes) { + void* mem = 0; if (oldmem == 0) { - mem = dlmalloc(bytes); - - } else if (bytes >= MAX_REQUEST) { - + } + else if (bytes >= MAX_REQUEST) { MALLOC_FAILURE_ACTION; - } - - #ifdef REALLOC_ZERO_BYTES_FREES +#ifdef REALLOC_ZERO_BYTES_FREES else if (bytes == 0) { - dlfree(oldmem); - } - - #endif /* REALLOC_ZERO_BYTES_FREES */ +#endif /* REALLOC_ZERO_BYTES_FREES */ else { - - size_t nb = request2size(bytes); + size_t nb = request2size(bytes); mchunkptr oldp = mem2chunk(oldmem); - #if !FOOTERS +#if ! FOOTERS mstate m = gm; - #else /* FOOTERS */ +#else /* FOOTERS */ mstate m = get_mstate_for(oldp); if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); return 0; - } - - #endif /* FOOTERS */ +#endif /* FOOTERS */ if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); POSTACTION(m); if (newp != 0) { - check_inuse_chunk(m, newp); mem = chunk2mem(newp); - - } else { - + } + else { mem = internal_malloc(m, bytes); if (mem != 0) { - size_t oc = chunksize(oldp) - overhead_for(oldp); - __builtin_memcpy(mem, oldmem, (oc < bytes) ? oc : bytes); + __builtin_memcpy(mem, oldmem, (oc < bytes)? oc : bytes); internal_free(m, oldmem); - } - } - } - } - return mem; - } -void *dlrealloc_in_place(void *oldmem, size_t bytes) { - - void *mem = 0; +void* dlrealloc_in_place(void* oldmem, size_t bytes) { + void* mem = 0; if (oldmem != 0) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - - } else { - - size_t nb = request2size(bytes); + } + else { + size_t nb = request2size(bytes); mchunkptr oldp = mem2chunk(oldmem); - #if !FOOTERS +#if ! FOOTERS mstate m = gm; - #else /* FOOTERS */ +#else /* FOOTERS */ mstate m = get_mstate_for(oldp); if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); return 0; - } - - #endif /* FOOTERS */ +#endif /* FOOTERS */ if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); POSTACTION(m); if (newp == oldp) { - check_inuse_chunk(m, newp); mem = oldmem; - } - } - } - } - return mem; - } -void *dlmemalign(size_t alignment, size_t bytes) { - - if (alignment <= MALLOC_ALIGNMENT) { return dlmalloc(bytes); } +void* dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) { + return dlmalloc(bytes); + } return internal_memalign(gm, alignment, bytes); - } -int dlposix_memalign(void **pp, size_t alignment, size_t bytes) { - - void *mem = 0; +int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { + void* mem = 0; if (alignment == MALLOC_ALIGNMENT) mem = dlmalloc(bytes); else { - - size_t d = alignment / sizeof(void *); - size_t r = alignment % sizeof(void *); - if (r != 0 || d == 0 || (d & (d - SIZE_T_ONE)) != 0) + size_t d = alignment / sizeof(void*); + size_t r = alignment % sizeof(void*); + if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) return EINVAL; else if (bytes <= MAX_REQUEST - alignment) { - - if (alignment < MIN_CHUNK_SIZE) alignment = MIN_CHUNK_SIZE; + if (alignment < MIN_CHUNK_SIZE) + alignment = MIN_CHUNK_SIZE; mem = internal_memalign(gm, alignment, bytes); - } - } - if (mem == 0) return ENOMEM; else { - *pp = mem; return 0; - } - } -void *dlvalloc(size_t bytes) { - +void* dlvalloc(size_t bytes) { size_t pagesz; ensure_initialization(); pagesz = mparams.page_size; return dlmemalign(pagesz, bytes); - } -void *dlpvalloc(size_t bytes) { - +void* dlpvalloc(size_t bytes) { size_t pagesz; ensure_initialization(); pagesz = mparams.page_size; - return dlmemalign(pagesz, - (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); - + return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); } -void **dlindependent_calloc(size_t n_elements, size_t elem_size, - void *chunks[]) { - - size_t sz = elem_size; /* serves as 1-element array */ +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ return ialloc(gm, n_elements, &sz, 3, chunks); - } -void **dlindependent_comalloc(size_t n_elements, size_t sizes[], - void *chunks[]) { - +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { return ialloc(gm, n_elements, sizes, 0, chunks); - } -size_t dlbulk_free(void *array[], size_t nelem) { - +size_t dlbulk_free(void* array[], size_t nelem) { return internal_bulk_free(gm, array, nelem); - } - #if MALLOC_INSPECT_ALL -void dlmalloc_inspect_all(void (*handler)(void *start, void *end, - size_t used_bytes, - void * callback_arg), - void *arg) { - +#if MALLOC_INSPECT_ALL +void dlmalloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { ensure_initialization(); if (!PREACTION(gm)) { - internal_inspect_all(gm, handler, arg); POSTACTION(gm); - } - } - - #endif /* MALLOC_INSPECT_ALL */ +#endif /* MALLOC_INSPECT_ALL */ int dlmalloc_trim(size_t pad) { - int result = 0; ensure_initialization(); if (!PREACTION(gm)) { - result = sys_trim(gm, pad); POSTACTION(gm); - } - return result; - } size_t dlmalloc_footprint(void) { - return gm->footprint; - } size_t dlmalloc_max_footprint(void) { - return gm->max_footprint; - } size_t dlmalloc_footprint_limit(void) { - size_t maf = gm->footprint_limit; return maf == 0 ? MAX_SIZE_T : maf; - } size_t dlmalloc_set_footprint_limit(size_t bytes) { - - size_t result; /* invert sense of 0 */ - if (bytes == 0) result = granularity_align(1); /* Use minimal size */ + size_t result; /* invert sense of 0 */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ if (bytes == MAX_SIZE_T) - result = 0; /* disable */ + result = 0; /* disable */ else result = granularity_align(bytes); return gm->footprint_limit = result; - } - #if !NO_MALLINFO +#if !NO_MALLINFO struct mallinfo dlmallinfo(void) { - return internal_mallinfo(gm); - } +#endif /* NO_MALLINFO */ - #endif /* NO_MALLINFO */ - - #if !NO_MALLOC_STATS +#if !NO_MALLOC_STATS void dlmalloc_stats() { - internal_malloc_stats(gm); - } - - #endif /* NO_MALLOC_STATS */ +#endif /* NO_MALLOC_STATS */ int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); - } -size_t dlmalloc_usable_size(void *mem) { - +size_t dlmalloc_usable_size(void* mem) { if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) return chunksize(p) - overhead_for(p); - + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); } - return 0; - } -#endif /* !ONLY_MSPACES */ +#endif /* !ONLY_MSPACES */ /* ----------------------------- user mspaces ---------------------------- */ #if MSPACES -static mstate init_user_mstate(char *tbase, size_t tsize) { - - size_t msize = pad_request(sizeof(struct malloc_state)); +static mstate init_user_mstate(char* tbase, size_t tsize) { + size_t msize = pad_request(sizeof(struct malloc_state)); mchunkptr mn; mchunkptr msp = align_as_chunk(tbase); - mstate m = (mstate)(chunk2mem(msp)); + mstate m = (mstate)(chunk2mem(msp)); __builtin_memset(m, 0, msize); (void)INITIAL_LOCK(&m->mutex); - msp->head = (msize | INUSE_BITS); + msp->head = (msize|INUSE_BITS); m->seg.base = m->least_addr = tbase; m->seg.size = m->footprint = m->max_footprint = tsize; m->magic = mparams.magic; @@ -6227,111 +5465,82 @@ static mstate init_user_mstate(char *tbase, size_t tsize) { disable_contiguous(m); init_bins(m); mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char *)mn) - TOP_FOOT_SIZE); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); check_top_chunk(m, m->top); return m; - } mspace create_mspace(size_t capacity, int locked) { - mstate m = 0; size_t msize; ensure_initialization(); msize = pad_request(sizeof(struct malloc_state)); - if (capacity < (size_t) - (msize + TOP_FOOT_SIZE + mparams.page_size)) { - - size_t rs = ((capacity == 0) ? mparams.granularity - : (capacity + TOP_FOOT_SIZE + msize)); + if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + size_t rs = ((capacity == 0)? mparams.granularity : + (capacity + TOP_FOOT_SIZE + msize)); size_t tsize = granularity_align(rs); - char * tbase = (char *)(CALL_MMAP(tsize)); + char* tbase = (char*)(CALL_MMAP(tsize)); if (tbase != CMFAIL) { - m = init_user_mstate(tbase, tsize); m->seg.sflags = USE_MMAP_BIT; set_lock(m, locked); - } - } - return (mspace)m; - } -mspace create_mspace_with_base(void *base, size_t capacity, int locked) { - +mspace create_mspace_with_base(void* base, size_t capacity, int locked) { mstate m = 0; size_t msize; ensure_initialization(); msize = pad_request(sizeof(struct malloc_state)); if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) - (msize + TOP_FOOT_SIZE + mparams.page_size)) { - - m = init_user_mstate((char *)base, capacity); + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity); m->seg.sflags = EXTERN_BIT; set_lock(m, locked); - } - return (mspace)m; - } int mspace_track_large_chunks(mspace msp, int enable) { - - int ret = 0; + int ret = 0; mstate ms = (mstate)msp; if (!PREACTION(ms)) { - - if (!use_mmap(ms)) { ret = 1; } + if (!use_mmap(ms)) { + ret = 1; + } if (!enable) { - enable_mmap(ms); - } else { - disable_mmap(ms); - } - POSTACTION(ms); - } - return ret; - } size_t destroy_mspace(mspace msp) { - size_t freed = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - msegmentptr sp = &ms->seg; - (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ + (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ while (sp != 0) { - - char * base = sp->base; + char* base = sp->base; size_t size = sp->size; flag_t flag = sp->sflags; - (void)base; /* placate people compiling -Wunused-variable */ + (void)base; /* placate people compiling -Wunused-variable */ sp = sp->next; if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && CALL_MUNMAP(base, size) == 0) freed += size; - } - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return freed; - } /* @@ -6339,31 +5548,25 @@ size_t destroy_mspace(mspace msp) { versions. This is not so nice but better than the alternatives. */ -void *mspace_malloc(mspace msp, size_t bytes) { - +void* mspace_malloc(mspace msp, size_t bytes) { mstate ms = (mstate)msp; if (!ok_magic(ms)) { - - USAGE_ERROR_ACTION(ms, ms); + USAGE_ERROR_ACTION(ms,ms); return 0; - } - if (!PREACTION(ms)) { - - void * mem; + void* mem; size_t nb; if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; binmap_t smallbits; - nb = (bytes < MIN_REQUEST) ? MIN_CHUNK_SIZE : pad_request(bytes); + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); idx = small_index(nb); smallbits = ms->smallmap >> idx; - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ + idx += ~smallbits & 1; /* Uses next bin if idx empty */ b = smallbin_at(ms, idx); p = b->fd; assert(chunksize(p) == small_index2size(idx)); @@ -6372,17 +5575,15 @@ void *mspace_malloc(mspace msp, size_t bytes) { mem = chunk2mem(p); check_malloced_chunk(ms, mem, nb); goto postaction; - } else if (nb > ms->dvsize) { - - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); compute_bit2idx(leastbit, i); b = smallbin_at(ms, i); p = b->fd; @@ -6393,71 +5594,54 @@ void *mspace_malloc(mspace msp, size_t bytes) { if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) set_inuse_and_pinuse(ms, p, small_index2size(i)); else { - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); r = chunk_plus_offset(p, nb); set_size_and_pinuse_of_free_chunk(r, rsize); replace_dv(ms, r, rsize); - } - mem = chunk2mem(p); check_malloced_chunk(ms, mem, nb); goto postaction; - } else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); goto postaction; - } - } - - } else if (bytes >= MAX_REQUEST) - + } + else if (bytes >= MAX_REQUEST) nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ else { - nb = pad_request(bytes); if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); goto postaction; - } - } if (nb <= ms->dvsize) { - - size_t rsize = ms->dvsize - nb; + size_t rsize = ms->dvsize - nb; mchunkptr p = ms->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ mchunkptr r = ms->dv = chunk_plus_offset(p, nb); ms->dvsize = rsize; set_size_and_pinuse_of_free_chunk(r, rsize); set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - - } else { /* exhaust dv */ - + } + else { /* exhaust dv */ size_t dvs = ms->dvsize; ms->dvsize = 0; ms->dv = 0; set_inuse_and_pinuse(ms, p, dvs); - } - mem = chunk2mem(p); check_malloced_chunk(ms, mem, nb); goto postaction; - } - else if (nb < ms->topsize) { /* Split top */ - size_t rsize = ms->topsize -= nb; + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; mchunkptr p = ms->top; mchunkptr r = ms->top = chunk_plus_offset(p, nb); r->head = rsize | PINUSE_BIT; @@ -6466,7 +5650,6 @@ void *mspace_malloc(mspace msp, size_t bytes) { check_top_chunk(ms, ms->top); check_malloced_chunk(ms, mem, nb); goto postaction; - } mem = sys_alloc(ms, nb); @@ -6474,519 +5657,372 @@ void *mspace_malloc(mspace msp, size_t bytes) { postaction: POSTACTION(ms); return mem; - } return 0; - } -void mspace_free(mspace msp, void *mem) { - +void mspace_free(mspace msp, void* mem) { if (mem != 0) { - - mchunkptr p = mem2chunk(mem); - #if FOOTERS + mchunkptr p = mem2chunk(mem); +#if FOOTERS mstate fm = get_mstate_for(p); - (void)msp; /* placate people compiling -Wunused */ - #else /* FOOTERS */ + (void)msp; /* placate people compiling -Wunused */ +#else /* FOOTERS */ mstate fm = (mstate)msp; - #endif /* FOOTERS */ +#endif /* FOOTERS */ if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); return; - } - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - - size_t psize = chunksize(p); + size_t psize = chunksize(p); mchunkptr next = chunk_plus_offset(p, psize); if (!pinuse(p)) { - size_t prevsize = p->prev_foot; if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char *)p - prevsize, psize) == 0) + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) fm->footprint -= psize; goto postaction; - - } else { - + } + else { mchunkptr prev = chunk_minus_offset(p, prevsize); psize += prevsize; p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - - } else if ((next->head & INUSE_BITS) == INUSE_BITS) { - + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { fm->dvsize = psize; set_free_with_pinuse(p, psize, next); goto postaction; - } - - } else - + } + else goto erroraction; - } - } if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - - if (!cinuse(next)) { /* consolidate forward */ + if (!cinuse(next)) { /* consolidate forward */ if (next == fm->top) { - size_t tsize = fm->topsize += psize; fm->top = p; p->head = tsize | PINUSE_BIT; if (p == fm->dv) { - fm->dv = 0; fm->dvsize = 0; - } - - if (should_trim(fm, tsize)) sys_trim(fm, 0); + if (should_trim(fm, tsize)) + sys_trim(fm, 0); goto postaction; - - } else if (next == fm->dv) { - + } + else if (next == fm->dv) { size_t dsize = fm->dvsize += psize; fm->dv = p; set_size_and_pinuse_of_free_chunk(p, dsize); goto postaction; - - } else { - + } + else { size_t nsize = chunksize(next); psize += nsize; unlink_chunk(fm, next, nsize); set_size_and_pinuse_of_free_chunk(p, psize); if (p == fm->dv) { - fm->dvsize = psize; goto postaction; - } - } - - } else - + } + else set_free_with_pinuse(p, psize, next); if (is_small(psize)) { - insert_small_chunk(fm, p, psize); check_free_chunk(fm, p); - - } else { - + } + else { tchunkptr tp = (tchunkptr)p; insert_large_chunk(fm, tp, psize); check_free_chunk(fm, p); - if (--fm->release_checks == 0) release_unused_segments(fm); - + if (--fm->release_checks == 0) + release_unused_segments(fm); } - goto postaction; - } - } - erroraction: USAGE_ERROR_ACTION(fm, p); postaction: POSTACTION(fm); - } - } - } -void *mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { - - void * mem; +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; size_t req = 0; mstate ms = (mstate)msp; if (!ok_magic(ms)) { - - USAGE_ERROR_ACTION(ms, ms); + USAGE_ERROR_ACTION(ms,ms); return 0; - } - if (n_elements != 0) { - req = n_elements * elem_size; if (((n_elements | elem_size) & ~(size_t)0xffff) && (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - + req = MAX_SIZE_T; /* force downstream failure on overflow */ } - mem = internal_malloc(ms, req); if (mem != 0 && calloc_must_clear(mem2chunk(mem))) __builtin_memset(mem, 0, req); return mem; - } -void *mspace_realloc(mspace msp, void *oldmem, size_t bytes) { - - void *mem = 0; +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; if (oldmem == 0) { - mem = mspace_malloc(msp, bytes); - - } else if (bytes >= MAX_REQUEST) { - + } + else if (bytes >= MAX_REQUEST) { MALLOC_FAILURE_ACTION; - } - - #ifdef REALLOC_ZERO_BYTES_FREES +#ifdef REALLOC_ZERO_BYTES_FREES else if (bytes == 0) { - mspace_free(msp, oldmem); - } - - #endif /* REALLOC_ZERO_BYTES_FREES */ +#endif /* REALLOC_ZERO_BYTES_FREES */ else { - - size_t nb = request2size(bytes); + size_t nb = request2size(bytes); mchunkptr oldp = mem2chunk(oldmem); - #if !FOOTERS +#if ! FOOTERS mstate m = (mstate)msp; - #else /* FOOTERS */ +#else /* FOOTERS */ mstate m = get_mstate_for(oldp); if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); return 0; - } - - #endif /* FOOTERS */ +#endif /* FOOTERS */ if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); POSTACTION(m); if (newp != 0) { - check_inuse_chunk(m, newp); mem = chunk2mem(newp); - - } else { - + } + else { mem = mspace_malloc(m, bytes); if (mem != 0) { - size_t oc = chunksize(oldp) - overhead_for(oldp); - __builtin_memcpy(mem, oldmem, (oc < bytes) ? oc : bytes); + __builtin_memcpy(mem, oldmem, (oc < bytes)? oc : bytes); mspace_free(m, oldmem); - } - } - } - } - return mem; - } -void *mspace_realloc_in_place(mspace msp, void *oldmem, size_t bytes) { - - void *mem = 0; +void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; if (oldmem != 0) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - - } else { - - size_t nb = request2size(bytes); + } + else { + size_t nb = request2size(bytes); mchunkptr oldp = mem2chunk(oldmem); - #if !FOOTERS +#if ! FOOTERS mstate m = (mstate)msp; - #else /* FOOTERS */ +#else /* FOOTERS */ mstate m = get_mstate_for(oldp); - (void)msp; /* placate people compiling -Wunused */ + (void)msp; /* placate people compiling -Wunused */ if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); return 0; - } - - #endif /* FOOTERS */ +#endif /* FOOTERS */ if (!PREACTION(m)) { - mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); POSTACTION(m); if (newp == oldp) { - check_inuse_chunk(m, newp); mem = oldmem; - } - } - } - } - return mem; - } -void *mspace_memalign(mspace msp, size_t alignment, size_t bytes) { - +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { mstate ms = (mstate)msp; if (!ok_magic(ms)) { - - USAGE_ERROR_ACTION(ms, ms); + USAGE_ERROR_ACTION(ms,ms); return 0; - } - - if (alignment <= MALLOC_ALIGNMENT) return mspace_malloc(msp, bytes); + if (alignment <= MALLOC_ALIGNMENT) + return mspace_malloc(msp, bytes); return internal_memalign(ms, alignment, bytes); - } -void **mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void *chunks[]) { - - size_t sz = elem_size; /* serves as 1-element array */ +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ mstate ms = (mstate)msp; if (!ok_magic(ms)) { - - USAGE_ERROR_ACTION(ms, ms); + USAGE_ERROR_ACTION(ms,ms); return 0; - } - return ialloc(ms, n_elements, &sz, 3, chunks); - } -void **mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void *chunks[]) { - +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]) { mstate ms = (mstate)msp; if (!ok_magic(ms)) { - - USAGE_ERROR_ACTION(ms, ms); + USAGE_ERROR_ACTION(ms,ms); return 0; - } - return ialloc(ms, n_elements, sizes, 0, chunks); - } -size_t mspace_bulk_free(mspace msp, void *array[], size_t nelem) { - +size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { return internal_bulk_free((mstate)msp, array, nelem); - } - #if MALLOC_INSPECT_ALL +#if MALLOC_INSPECT_ALL void mspace_inspect_all(mspace msp, - void (*handler)(void *start, void *end, - size_t used_bytes, void *callback_arg), - void *arg) { - + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { mstate ms = (mstate)msp; if (ok_magic(ms)) { - if (!PREACTION(ms)) { - internal_inspect_all(ms, handler, arg); POSTACTION(ms); - } - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } } - - #endif /* MALLOC_INSPECT_ALL */ +#endif /* MALLOC_INSPECT_ALL */ int mspace_trim(mspace msp, size_t pad) { - - int result = 0; + int result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - if (!PREACTION(ms)) { - result = sys_trim(ms, pad); POSTACTION(ms); - } - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; - } - #if !NO_MALLOC_STATS +#if !NO_MALLOC_STATS void mspace_malloc_stats(mspace msp) { - mstate ms = (mstate)msp; if (ok_magic(ms)) { - internal_malloc_stats(ms); - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } } - - #endif /* NO_MALLOC_STATS */ +#endif /* NO_MALLOC_STATS */ size_t mspace_footprint(mspace msp) { - size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - result = ms->footprint; - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; - } size_t mspace_max_footprint(mspace msp) { - size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - result = ms->max_footprint; - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; - } size_t mspace_footprint_limit(mspace msp) { - size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - size_t maf = ms->footprint_limit; result = (maf == 0) ? MAX_SIZE_T : maf; - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; - } size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { - size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { - - if (bytes == 0) result = granularity_align(1); /* Use minimal size */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ if (bytes == MAX_SIZE_T) - result = 0; /* disable */ + result = 0; /* disable */ else result = granularity_align(bytes); ms->footprint_limit = result; - - } else { - - USAGE_ERROR_ACTION(ms, ms); - } - + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; - } - #if !NO_MALLINFO +#if !NO_MALLINFO struct mallinfo mspace_mallinfo(mspace msp) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { USAGE_ERROR_ACTION(ms, ms); } + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } return internal_mallinfo(ms); - } +#endif /* NO_MALLINFO */ - #endif /* NO_MALLINFO */ - -size_t mspace_usable_size(const void *mem) { - +size_t mspace_usable_size(const void* mem) { if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) return chunksize(p) - overhead_for(p); - + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); } - return 0; - } int mspace_mallopt(int param_number, int value) { - return change_mparam(param_number, value); - } -#endif /* MSPACES */ +#endif /* MSPACES */ + /* -------------------- Alternative MORECORE functions ------------------- */ @@ -7031,48 +6067,35 @@ int mspace_mallopt(int param_number, int value) { void *osMoreCore(int size) { - void *ptr = 0; static void *sbrk_top = 0; if (size > 0) { - if (size < MINIMUM_MORECORE_SIZE) size = MINIMUM_MORECORE_SIZE; if (CurrentExecutionLevel() == kTaskLevel) ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); if (ptr == 0) { - return (void *) MFAIL; - } - // save ptrs so they can be freed during cleanup our_os_pools[next_os_pool] = ptr; next_os_pool++; ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); sbrk_top = (char *) ptr + size; return ptr; - } - else if (size < 0) { - // we don't currently support shrink behavior return (void *) MFAIL; - } - else { - return sbrk_top; - } - } // cleanup any allocated memory pools @@ -7080,22 +6103,19 @@ int mspace_mallopt(int param_number, int value) { void osCleanupMem(void) { - void **ptr; for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) if (*ptr) { - PoolDeallocate(*ptr); *ptr = 0; - } - } */ + /* ----------------------------------------------------------------------- History: v2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea @@ -7315,3 +6335,4 @@ History: */ +#endif // __GLIBC__ diff --git a/qemu_mode/libqasan/malloc.c b/qemu_mode/libqasan/malloc.c index f8237826..54c1096a 100644 --- a/qemu_mode/libqasan/malloc.c +++ b/qemu_mode/libqasan/malloc.c @@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ #include "libqasan.h" +#include #include #include #include @@ -50,9 +51,9 @@ typedef struct { struct chunk_begin { size_t requested_size; - void * aligned_orig; // NULL if not aligned - struct chunk_begin *next; - struct chunk_begin *prev; + void* aligned_orig; // NULL if not aligned + struct chunk_begin* next; + struct chunk_begin* prev; char redzone[REDZONE_SIZE]; }; @@ -65,30 +66,47 @@ struct chunk_struct { }; +#ifdef __GLIBC__ + +void* (*__lq_libc_malloc)(size_t); +void (*__lq_libc_free)(void*); +#define backend_malloc __lq_libc_malloc +#define backend_free __lq_libc_free + +#define TMP_ZONE_SIZE 4096 +static int __tmp_alloc_zone_idx; +static unsigned char __tmp_alloc_zone[TMP_ZONE_SIZE]; + +#else + // From dlmalloc.c -void *dlmalloc(size_t); -void dlfree(void *); +void* dlmalloc(size_t); +void dlfree(void*); +#define backend_malloc dlmalloc +#define backend_free dlfree + +#endif int __libqasan_malloc_initialized; -static struct chunk_begin *quarantine_top; -static struct chunk_begin *quarantine_end; +static struct chunk_begin* quarantine_top; +static struct chunk_begin* quarantine_end; static size_t quarantine_bytes; #ifdef __BIONIC__ -static pthread_mutex_t quarantine_lock; - #define LOCK_TRY pthread_mutex_trylock - #define LOCK_INIT pthread_mutex_init - #define LOCK_UNLOCK pthread_mutex_unlock +static pthread_mutex_t quarantine_lock; +#define LOCK_TRY pthread_mutex_trylock +#define LOCK_INIT pthread_mutex_init +#define LOCK_UNLOCK pthread_mutex_unlock #else -static pthread_spinlock_t quarantine_lock; - #define LOCK_TRY pthread_spin_trylock - #define LOCK_INIT pthread_spin_init - #define LOCK_UNLOCK pthread_spin_unlock +static pthread_spinlock_t quarantine_lock; +#define LOCK_TRY pthread_spin_trylock +#define LOCK_INIT pthread_spin_init +#define LOCK_UNLOCK pthread_spin_unlock #endif // need qasan disabled -static int quanratine_push(struct chunk_begin *ck) { +static int quanratine_push(struct chunk_begin* ck) { if (ck->requested_size >= QUARANTINE_MAX_BYTES) return 0; @@ -96,15 +114,15 @@ static int quanratine_push(struct chunk_begin *ck) { while (ck->requested_size + quarantine_bytes >= QUARANTINE_MAX_BYTES) { - struct chunk_begin *tmp = quarantine_end; + struct chunk_begin* tmp = quarantine_end; quarantine_end = tmp->prev; quarantine_bytes -= tmp->requested_size; if (tmp->aligned_orig) - dlfree(tmp->aligned_orig); + backend_free(tmp->aligned_orig); else - dlfree(tmp); + backend_free(tmp); } @@ -122,6 +140,11 @@ void __libqasan_init_malloc(void) { if (__libqasan_malloc_initialized) return; +#ifdef __GLIBC__ + __lq_libc_malloc = dlsym(RTLD_NEXT, "malloc"); + __lq_libc_free = dlsym(RTLD_NEXT, "free"); +#endif + LOCK_INIT(&quarantine_lock, PTHREAD_PROCESS_PRIVATE); __libqasan_malloc_initialized = 1; @@ -131,24 +154,38 @@ void __libqasan_init_malloc(void) { } -size_t __libqasan_malloc_usable_size(void *ptr) { +size_t __libqasan_malloc_usable_size(void* ptr) { - char *p = ptr; + char* p = ptr; p -= sizeof(struct chunk_begin); - return ((struct chunk_begin *)p)->requested_size; + return ((struct chunk_begin*)p)->requested_size; } -void *__libqasan_malloc(size_t size) { +void* __libqasan_malloc(size_t size) { - if (!__libqasan_malloc_initialized) { __libqasan_init_malloc(); } + if (!__libqasan_malloc_initialized) { + + __libqasan_init_malloc(); - if (!__libqasan_malloc_initialized) __libqasan_init_malloc(); +#ifdef __GLIBC__ + void* r = &__tmp_alloc_zone[__tmp_alloc_zone_idx]; + + if (size & (ALLOC_ALIGN_SIZE - 1)) + __tmp_alloc_zone_idx += + (size & ~(ALLOC_ALIGN_SIZE - 1)) + ALLOC_ALIGN_SIZE; + else + __tmp_alloc_zone_idx += size; + + return r; +#endif + + } int state = QASAN_SWAP(QASAN_DISABLED); // disable qasan for this thread - struct chunk_begin *p = dlmalloc(sizeof(struct chunk_struct) + size); + struct chunk_begin* p = backend_malloc(sizeof(struct chunk_struct) + size); QASAN_SWAP(state); @@ -160,14 +197,14 @@ void *__libqasan_malloc(size_t size) { p->aligned_orig = NULL; p->next = p->prev = NULL; - QASAN_ALLOC(&p[1], (char *)&p[1] + size); + QASAN_ALLOC(&p[1], (char*)&p[1] + size); QASAN_POISON(p->redzone, REDZONE_SIZE, ASAN_HEAP_LEFT_RZ); if (size & (ALLOC_ALIGN_SIZE - 1)) - QASAN_POISON((char *)&p[1] + size, + QASAN_POISON((char*)&p[1] + size, (size & ~(ALLOC_ALIGN_SIZE - 1)) + 8 - size + REDZONE_SIZE, ASAN_HEAP_RIGHT_RZ); else - QASAN_POISON((char *)&p[1] + size, REDZONE_SIZE, ASAN_HEAP_RIGHT_RZ); + QASAN_POISON((char*)&p[1] + size, REDZONE_SIZE, ASAN_HEAP_RIGHT_RZ); __builtin_memset(&p[1], 0xff, size); @@ -175,11 +212,17 @@ void *__libqasan_malloc(size_t size) { } -void __libqasan_free(void *ptr) { +void __libqasan_free(void* ptr) { if (!ptr) return; + +#ifdef __GLIBC__ + if (ptr >= (void*)__tmp_alloc_zone && + ptr < ((void*)__tmp_alloc_zone + TMP_ZONE_SIZE)) + return; +#endif - struct chunk_begin *p = ptr; + struct chunk_begin* p = ptr; p -= 1; size_t n = p->requested_size; @@ -190,9 +233,9 @@ void __libqasan_free(void *ptr) { if (!quanratine_push(p)) { if (p->aligned_orig) - dlfree(p->aligned_orig); + backend_free(p->aligned_orig); else - dlfree(p); + backend_free(p); } @@ -206,11 +249,21 @@ void __libqasan_free(void *ptr) { } -void *__libqasan_calloc(size_t nmemb, size_t size) { +void* __libqasan_calloc(size_t nmemb, size_t size) { size *= nmemb; - char *p = __libqasan_malloc(size); +#ifdef __GLIBC__ + if (!__libqasan_malloc_initialized) { + + void* r = &__tmp_alloc_zone[__tmp_alloc_zone_idx]; + __tmp_alloc_zone_idx += size; + return r; + + } +#endif + + char* p = __libqasan_malloc(size); if (!p) return NULL; __builtin_memset(p, 0, size); @@ -219,14 +272,14 @@ void *__libqasan_calloc(size_t nmemb, size_t size) { } -void *__libqasan_realloc(void *ptr, size_t size) { +void* __libqasan_realloc(void* ptr, size_t size) { - char *p = __libqasan_malloc(size); + char* p = __libqasan_malloc(size); if (!p) return NULL; if (!ptr) return p; - size_t n = ((struct chunk_begin *)ptr)[-1].requested_size; + size_t n = ((struct chunk_begin*)ptr)[-1].requested_size; if (size < n) n = size; __builtin_memcpy(p, ptr, n); @@ -236,9 +289,9 @@ void *__libqasan_realloc(void *ptr, size_t size) { } -int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) { +int __libqasan_posix_memalign(void** ptr, size_t align, size_t len) { - if ((align % 2) || (align % sizeof(void *))) return EINVAL; + if ((align % 2) || (align % sizeof(void*))) return EINVAL; if (len == 0) { *ptr = NULL; @@ -252,7 +305,7 @@ int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) { int state = QASAN_SWAP(QASAN_DISABLED); // disable qasan for this thread - char *orig = dlmalloc(sizeof(struct chunk_struct) + size); + char* orig = backend_malloc(sizeof(struct chunk_struct) + size); QASAN_SWAP(state); @@ -260,10 +313,10 @@ int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) { QASAN_UNPOISON(orig, sizeof(struct chunk_struct) + size); - char *data = orig + sizeof(struct chunk_begin); + char* data = orig + sizeof(struct chunk_begin); data += align - ((uintptr_t)data % align); - struct chunk_begin *p = (struct chunk_begin *)data - 1; + struct chunk_begin* p = (struct chunk_begin*)data - 1; p->requested_size = len; p->aligned_orig = orig; @@ -286,9 +339,9 @@ int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) { } -void *__libqasan_memalign(size_t align, size_t len) { +void* __libqasan_memalign(size_t align, size_t len) { - void *ret = NULL; + void* ret = NULL; __libqasan_posix_memalign(&ret, align, len); @@ -296,9 +349,9 @@ void *__libqasan_memalign(size_t align, size_t len) { } -void *__libqasan_aligned_alloc(size_t align, size_t len) { +void* __libqasan_aligned_alloc(size_t align, size_t len) { - void *ret = NULL; + void* ret = NULL; if ((len % align)) return NULL; diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 6ab6bf28..47722f64 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 6ab6bf28decb3e36eee43ffbd4a3bfd052dbbb50 +Subproject commit 47722f64e4c1662bad97dc25f3e4cc63959ff5f3 -- cgit 1.4.1 From 5b2634f711e95b48b6105d3cac659e51706ff4e9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 10 Feb 2021 17:56:27 +0100 Subject: update changelog + ideas --- docs/Changelog.md | 12 ++++++------ docs/ideas.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index f2041917..56137eec 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,8 +16,8 @@ sending a mail to . to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz - - Making AFL_MAP_SIZE obsolete - afl-fuzz now learns on start the - target map size + - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on start + the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). this is costly hence new command line option @@ -27,7 +27,7 @@ sending a mail to . - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now - reloaded and used, thanks to Vimal Joseph for this PR! + reloaded and used, thanks to Vimal Joseph for this patch! - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map @@ -47,8 +47,10 @@ sending a mail to . - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang + - fixed a potential crash in the LAF feature - qemuafl - - ported QASan to qemuafl! see qemu_mode/libqasan/README.md + - QASan (address sanitizer for Qemu) ported to qemuafl! + See qemu_mode/libqasan/README.md - solved some persistent mode bugs (thanks Dil4rd) - solved an issue when dumping the memory maps (thanks wizche) - Android support for QASan @@ -58,8 +60,6 @@ sending a mail to . - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars - - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was - already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) diff --git a/docs/ideas.md b/docs/ideas.md index 7cbe60a5..08cb16ef 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -3,6 +3,40 @@ In the following, we describe a variety of ideas that could be implemented for future AFL++ versions. +# GSoC 2021 + +All GSoC 2021 projects will be in the Rust development language! + +## UI for libaflrs + +Write a user interface to libaflrs, the upcoming backend of afl++. +This might look like the afl-fuzz UI, but you can improve on it - and should! + +## Schedulers for libaflrs + +Schedulers is a mechanism that selects items from the fuzzing corpus based +on strategy and randomness. One scheduler might focus on long paths, +another on rarity of edges disocvered, still another on a combination on +things. Some of the schedulers in afl++ have to be ported, but you are free +to come up with your own if you want to - and see how it performs. + +## Forkserver support for libaflrs + +The current libaflrs implementation fuzzes in-memory, however obviously we +want to support afl instrumented binaries as well. +Hence a forkserver support needs to be implemented - forking off the target +and talking to the target via a socketpair and the communication protocol +within. + +## More Observers for libaflrs + +An observer is measuring functionality that looks at the target being fuzzed +and documents something about it. In traditional fuzzing this is the coverage +in the target, however we want to add various more observers, e.g. stack depth, +heap usage, etc. - this is a topic for an experienced Rust developer. + +# Generic ideas and wishlist + ## Analysis software Currently analysis is done by using afl-plot, which is rather outdated. -- cgit 1.4.1 From dd3f4bb41c47025c490e7687d7bd1f04188f7bc4 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Thu, 11 Feb 2021 20:05:06 +0100 Subject: typos & formatting --- docs/Changelog.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 56137eec..919e2aeb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,18 +20,18 @@ sending a mail to . the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, - arithmetics, etc.). this is costly hence new command line option - -l that sets the intensity (values 1 to 3). recommended is 1 or 2. + arithmetics, etc.). This is costly hence new command line option + `-l` that sets the intensity (values 1 to 3). Recommended is 1 or 2. - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now + - on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now reloaded and used, thanks to Vimal Joseph for this patch! - - if determinstic mode is active (-D, or -M without -d) then we sync + - if deterministic mode is active (`-D`, or `-M` without `-d`) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map - - fix for -Z + - fix for `-Z` - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc @@ -55,7 +55,7 @@ sending a mail to . - solved an issue when dumping the memory maps (thanks wizche) - Android support for QASan - unicornafl - - Substential speed gains in python bindings for certain use cases + - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash -- cgit 1.4.1 From 223bd70f1f1530a0b8331e3deee0de2b20ae061b Mon Sep 17 00:00:00 2001 From: hexcoder Date: Thu, 11 Feb 2021 20:08:28 +0100 Subject: typo --- docs/env_variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index ab56c178..886669ad 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -517,7 +517,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings: - With `AFL_USE_QASAN` you can enable QEMU AddressSanitizer for dynamically linked binaries. - - With `AFL_QEMU_FORCE_DFL` you force QEMU to ignore the registered singal + - With `AFL_QEMU_FORCE_DFL` you force QEMU to ignore the registered signal handlers of the target. ## 6) Settings for afl-cmin -- cgit 1.4.1 From 2ff6e5023f9116c24842e6aee0da644106a61829 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Thu, 11 Feb 2021 20:14:48 +0100 Subject: typos --- docs/rpc_statsd.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/rpc_statsd.md b/docs/rpc_statsd.md index 02f72be6..fb97aa09 100644 --- a/docs/rpc_statsd.md +++ b/docs/rpc_statsd.md @@ -1,6 +1,6 @@ # Remote monitoring with StatsD -StatsD allows you to receive and aggregate metrics from a wide range of application and retransmit them to the backend of your choice. +StatsD allows you to receive and aggregate metrics from a wide range of applications and retransmit them to the backend of your choice. This enables you to create nice and readable dashboards containing all the information you need on your fuzzer instances. No need to write your own statistics parsing system, deploy and maintain it to all your instances, sync with your graph rendering system... @@ -45,7 +45,7 @@ For more information on these env vars, check out `docs/env_variables.md`. The simplest way of using this feature is to use any metric provider and change the host/port of your StatsD daemon, with `AFL_STATSD_HOST` and `AFL_STATSD_PORT`, if required (defaults are `localhost` and port `8125`). -To get started, here are some instruction with free and open source tools. +To get started, here are some instructions with free and open source tools. The following setup is based on Prometheus, statsd_exporter and Grafana. Grafana here is not mandatory, but gives you some nice graphs and features. @@ -131,7 +131,7 @@ mappings: Run `docker-compose up -d`. -Everything should be now setup, you are now able to run your fuzzers with +Everything should now be setup, you are now able to run your fuzzers with ``` AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o ./bin/my-application @@ @@ -139,5 +139,5 @@ AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o ... ``` -This setup may be modified before use in production environment. Depending on your needs: addind passwords, creating volumes for storage, +This setup may be modified before use in a production environment. Depending on your needs: adding passwords, creating volumes for storage, tweaking the metrics gathering to get host metrics (CPU, RAM ...). -- cgit 1.4.1 From 87a607c7d081dac1e4afd7c3cbe5accf62d355e4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 11:17:53 +0100 Subject: update doc --- docs/Changelog.md | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 10 +++++----- unicorn_mode/unicornafl | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 919e2aeb..c59a1a7a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -48,6 +48,7 @@ sending a mail to . support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang - fixed a potential crash in the LAF feature + - workaround for llvm 13 - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! See qemu_mode/libqasan/README.md diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 5d6d6703..80c8f917 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1088,7 +1088,7 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch( } - llvm::sort(Initializers.begin() + 2, Initializers.end(), + llvm::sort(drop_begin(Initializers, 2), [](const Constant *A, const Constant *B) { return cast(A)->getLimitedValue() < @@ -1136,10 +1136,10 @@ void ModuleSanitizerCoverage::InjectTraceForGep( for (auto GEP : GepTraceTargets) { IRBuilder<> IRB(GEP); - for (auto I = GEP->idx_begin(); I != GEP->idx_end(); ++I) - if (!isa(*I) && (*I)->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, - {IRB.CreateIntCast(*I, IntptrTy, true)}); + for (Use &Idx : GEP->indices()) + if (!isa(Idx) && Idx->getType()->isIntegerTy()) + IRB.CreateCall(SanCovTraceGepFunction, + {IRB.CreateIntCast(Idx, IntptrTy, true)}); } diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 80d31ef3..fb2fc9f2 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 80d31ef367f7a1a75fc48e08e129d10f2ffa0498 +Subproject commit fb2fc9f25df32f17f6b6b859e4dbd70f9a857e0c -- cgit 1.4.1 From 6ce9230ed66dbd091001436cdab2fc1718e8e61e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 14:24:21 +0100 Subject: afl-cmin/afl-showmap -f --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index c59a1a7a..895ab845 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -59,6 +59,7 @@ sending a mail to . - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings + - afl-cmin and afl-showmap now support the -f option - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars - added dummy Makefile to instrumentation/ -- cgit 1.4.1 From 9bd1e19d7f004b4da6a610b07e59f99d66bb7ec2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 22:43:56 +0100 Subject: added AFL_IGNORE_UNKNOWN_ENVS --- docs/Changelog.md | 3 ++- docs/env_variables.md | 5 ++++- include/envs.h | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- src/afl-cc.c | 1 + src/afl-common.c | 4 ++-- src/afl-fuzz.c | 1 + src/afl-showmap.c | 5 +++-- 8 files changed, 15 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 895ab845..71ef4c2c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -61,7 +61,8 @@ sending a mail to . - Added a new example harness to compare python, c, and rust bindings - afl-cmin and afl-showmap now support the -f option - changed default: no memory limit for afl-cmin and afl-cmin.bash - - warn on any _AFL and __AFL env vars + - warn on any _AFL and __AFL env vars. + - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) diff --git a/docs/env_variables.md b/docs/env_variables.md index 886669ad..f7745247 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -5,6 +5,10 @@ users or for some types of custom fuzzing setups. See [README.md](README.md) for the general instruction manual. + Note that most tools will warn on any unknown AFL environment variables. + This is for warning on typos that can happen. If you want to disable this + check then set the `AFL_IGNORE_UNKNOWN_ENVS` environment variable. + ## 1) Settings for all compilers Starting with afl++ 3.0 there is only one compiler: afl-cc @@ -18,7 +22,6 @@ To select the different instrumentation modes this can be done by `MODE` can be one of `LTO` (afl-clang-lto*), `LLVM` (afl-clang-fast*), `GCC_PLUGIN` (afl-g*-fast) or `GCC` (afl-gcc/afl-g++). - Because (with the exception of the --afl-MODE command line option) the compile-time tools do not accept afl specific command-line options, they make fairly broad use of environmental variables instead: diff --git a/include/envs.h b/include/envs.h index 210b34a6..4313e053 100644 --- a/include/envs.h +++ b/include/envs.h @@ -61,6 +61,7 @@ static char *afl_environment_variables[] = { "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", + "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 80c8f917..9b1351b0 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1138,7 +1138,7 @@ void ModuleSanitizerCoverage::InjectTraceForGep( IRBuilder<> IRB(GEP); for (Use &Idx : GEP->indices()) if (!isa(Idx) && Idx->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, + IRB.CreateCall(SanCovTraceGepFunction, {IRB.CreateIntCast(Idx, IntptrTy, true)}); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 9d88f262..d41f79a2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1587,6 +1587,7 @@ int main(int argc, char **argv, char **envp) { "libtokencap.so)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" + " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" " AFL_INST_RATIO: percentage of branches to instrument\n" " AFL_QUIET: suppress verbose output\n" " AFL_HARDEN: adds code hardening to catch memory bugs\n" diff --git a/src/afl-common.c b/src/afl-common.c index 1cc7f462..589aac71 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -523,7 +523,7 @@ void check_environment_vars(char **envp) { if (be_quiet) { return; } int index = 0, issue_detected = 0; - char *env, *val; + char *env, *val, *ignore = getenv("AFL_IGNORE_UNKNOWN_ENVS"); while ((env = envp[index++]) != NULL) { if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 || @@ -582,7 +582,7 @@ void check_environment_vars(char **envp) { } - if (match == 0) { + if (match == 0 && !ignore) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e4139857..e0ac8840 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -198,6 +198,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n" "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n" + "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0d2c5ceb..b40527d3 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1168,8 +1168,9 @@ int main(int argc, char **argv_orig, char **envp) { } - stdin_file = at_file ? strdup(at_file) : (char *) - alloc_printf("%s/.afl-showmap-temp-%u", use_dir, (u32)getpid()); + stdin_file = at_file ? strdup(at_file) + : (char *)alloc_printf("%s/.afl-showmap-temp-%u", + use_dir, (u32)getpid()); unlink(stdin_file); atexit(at_exit_handler); fsrv->out_file = stdin_file; -- cgit 1.4.1 From dd2fd8027454acaa5c12beea6f7b721fc8794715 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 15 Feb 2021 12:40:10 +0100 Subject: doc updates --- README.md | 5 +++-- docs/env_variables.md | 1 + qemu_mode/libqasan/README.md | 23 ++++++++++++++++------- qemu_mode/qemuafl | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 0778026c..00095390 100644 --- a/README.md +++ b/README.md @@ -751,6 +751,8 @@ campaigns as these are much shorter runnings. * for CMPLOG targets, 60% for `-l 2`, 40% for `-l 3` 4. Do *not* run any `-M` modes, just running `-S` modes is better for CI fuzzing. + `-M` enables deterministic fuzzing, old queue handling etc. which is good for + a fuzzing campaign but not good for short CI runs. ## Fuzzing binary-only targets @@ -788,8 +790,7 @@ If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your binary, then you can use afl-fuzz normally and it will have twice the speed compared to qemu_mode (but slower than persistent mode). Note that several other binary rewriters exist, all with their advantages and -caveats. As rewriting a binary is much faster than Qemu this is a highly -recommended approach! +caveats. ### Unicorn diff --git a/docs/env_variables.md b/docs/env_variables.md index f7745247..f6ed12d0 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -451,6 +451,7 @@ checks or alter some of the more exotic semantics of the tool: `banner` corresponds to the name of the fuzzer provided through `-M/-S`. `afl_version` corresponds to the currently running afl version (e.g `++3.0c`). Default (empty/non present) will add no tags to the metrics. + See [rpc_statsd.md](rpc_statsd.md) for more information. - Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash. For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting diff --git a/qemu_mode/libqasan/README.md b/qemu_mode/libqasan/README.md index 83fb2442..4a241233 100644 --- a/qemu_mode/libqasan/README.md +++ b/qemu_mode/libqasan/README.md @@ -4,16 +4,25 @@ This library is the injected runtime used by QEMU AddressSanitizer (QASan). The original repository is [here](https://github.com/andreafioraldi/qasan). -The version embedded in qemuafl is an updated version of just the usermode part and this runtime is injected via LD_PRELOAD (so works just for dynamically linked binaries). +The version embedded in qemuafl is an updated version of just the usermode part +and this runtime is injected via LD_PRELOAD (so works just for dynamically +linked binaries). -The usage is super simple, just set the env var `AFL_USE_QASAN=1` when fuzzing in qemu mode (-Q). afl-fuzz will automatically set AFL_PRELOAD to load this library and enable the QASan instrumentation in afl-qemu-trace. +The usage is super simple, just set the env var `AFL_USE_QASAN=1` when fuzzing +in qemu mode (-Q). afl-fuzz will automatically set AFL_PRELOAD to load this +library and enable the QASan instrumentation in afl-qemu-trace. -For debugging purposes, we still suggest to run the original QASan as the stacktrace support for ARM (just a debug feature, it does not affect the bug finding capabilities during fuzzing) is WIP. +For debugging purposes, we still suggest to run the original QASan as the +stacktrace support for ARM (just a debug feature, it does not affect the bug +finding capabilities during fuzzing) is WIP. -### When I should use QASan? +### When should I use QASan? -If your target binary is PIC x86_64, you should also give a try to [retrowrite](https://github.com/HexHive/retrowrite) for static rewriting. +If your target binary is PIC x86_64, you should also give a try to +[retrowrite](https://github.com/HexHive/retrowrite) for static rewriting. -If it fails, or if your binary is for another architecture, or you want to use persistent and snapshot mode, AFL++ QASan mode is what you want/have to use. +If it fails, or if your binary is for another architecture, or you want to use +persistent and snapshot mode, AFL++ QASan mode is what you want/have to use. -Note that the overhead of libdislocator when combined with QEMU mode is much lower but it can catch less bugs. This is a short blanket, take your choice. +Note that the overhead of libdislocator when combined with QEMU mode is much +lower but it can catch less bugs. This is a short blanket, take your choice. diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 213f3b27..9a258d5b 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 213f3b27dd099ef352181c48cd75c0f20a73e3f0 +Subproject commit 9a258d5b7a38c045a6e385fcfcf80a746a60e557 -- cgit 1.4.1 From e3a5c31307f323452dc4b5288e0d19a02b596a33 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 15 Feb 2021 13:25:15 +0100 Subject: llvm bug workaround for lto extint --- docs/Changelog.md | 1 + include/envs.h | 1 + instrumentation/cmplog-instructions-pass.cc | 39 ++++++++++++++++++++++++++--- qemu_mode/libqasan/dlmalloc.c | 5 ++++ src/afl-cc.c | 2 ++ src/afl-fuzz-redqueen.c | 1 + 6 files changed, 45 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 71ef4c2c..e2482f8f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -49,6 +49,7 @@ sending a mail to . CLANG for old afl-clang - fixed a potential crash in the LAF feature - workaround for llvm 13 + - workaround for llvm internal lto bug that lets not bitcast from _ExtInt() - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! See qemu_mode/libqasan/README.md diff --git a/include/envs.h b/include/envs.h index 4313e053..36667ebc 100644 --- a/include/envs.h +++ b/include/envs.h @@ -16,6 +16,7 @@ static char *afl_environment_deprecated[] = { static char *afl_environment_variables[] = { + "_AFL_LTO_COMPILE", "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index b5cc1882..6b071b48 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -113,6 +113,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) { IntegerType *Int64Ty = IntegerType::getInt64Ty(C); IntegerType *Int128Ty = IntegerType::getInt128Ty(C); + char *is_lto = getenv("_AFL_LTO_COMPILE"); + #if LLVM_VERSION_MAJOR < 9 Constant * #else @@ -265,10 +267,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) { unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; unsigned char do_cast = 0; - if (!SI->getNumCases() || max_size < 16 || max_size % 8) { + if (!SI->getNumCases() || max_size < 16) { continue; } + + if (max_size % 8) { + + if (is_lto) { + + continue; // LTO cannot bitcast from _ExtInt() :( + + } else { - // if (!be_quiet) errs() << "skip trivial switch..\n"; - continue; + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } } @@ -285,6 +297,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } + if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( max_size = 128; do_cast = 1; @@ -301,6 +314,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: + if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( cast_size = 128; do_cast = 1; @@ -540,7 +554,22 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (!max_size || max_size % 8 || max_size < 16) { continue; } + if (!max_size || max_size < 16) { continue; } + + if (max_size % 8) { + + if (is_lto) { + + continue; // LTO cannot bitcast from _ExtInt() :( + + } else { + + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } + + } if (max_size > 128) { @@ -552,6 +581,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } + if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( max_size = 128; do_cast = 1; @@ -568,6 +598,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: + if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( cast_size = 128; do_cast = 1; diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index bace0ff6..aff58ad5 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3917,6 +3917,7 @@ static void internal_malloc_stats(mstate m) { \ } else if (RTCHECK(B == smallbin_at(M, I) || \ \ + \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4128,6 +4129,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4144,6 +4146,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4156,12 +4159,14 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-cc.c b/src/afl-cc.c index d41f79a2..959c9a6f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1875,6 +1875,8 @@ int main(int argc, char **argv, char **envp) { edit_params(argc, argv, envp); + if (lto_mode) { setenv("_AFL_LTO_COMPILE", "1", 1); } + if (debug) { DEBUGF("cd '%s';", getthecwd()); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 527feef5..2b01ecad 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1533,6 +1533,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, is_n = 1; } + #endif for (i = 0; i < loggeds; ++i) { -- cgit 1.4.1 From 6caec2169cef890ba8a62715c2c26cc0608626e3 Mon Sep 17 00:00:00 2001 From: Michael Rodler Date: Mon, 15 Feb 2021 19:14:28 +0100 Subject: Revert "llvm bug workaround for lto extint" This reverts commit e3a5c31307f323452dc4b5288e0d19a02b596a33. --- docs/Changelog.md | 1 - include/envs.h | 1 - instrumentation/cmplog-instructions-pass.cc | 39 +++-------------------------- qemu_mode/libqasan/dlmalloc.c | 5 ---- src/afl-cc.c | 2 -- src/afl-fuzz-redqueen.c | 1 - 6 files changed, 4 insertions(+), 45 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index e2482f8f..71ef4c2c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -49,7 +49,6 @@ sending a mail to . CLANG for old afl-clang - fixed a potential crash in the LAF feature - workaround for llvm 13 - - workaround for llvm internal lto bug that lets not bitcast from _ExtInt() - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! See qemu_mode/libqasan/README.md diff --git a/include/envs.h b/include/envs.h index 36667ebc..4313e053 100644 --- a/include/envs.h +++ b/include/envs.h @@ -16,7 +16,6 @@ static char *afl_environment_deprecated[] = { static char *afl_environment_variables[] = { - "_AFL_LTO_COMPILE", "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 9cd99f85..50ade9fd 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -114,8 +114,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { IntegerType *Int64Ty = IntegerType::getInt64Ty(C); IntegerType *Int128Ty = IntegerType::getInt128Ty(C); - char *is_lto = getenv("_AFL_LTO_COMPILE"); - #if LLVM_VERSION_MAJOR < 9 Constant * #else @@ -268,20 +266,10 @@ bool CmpLogInstructions::hookInstrs(Module &M) { unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; unsigned char do_cast = 0; - if (!SI->getNumCases() || max_size < 16) { continue; } - - if (max_size % 8) { - - if (is_lto) { + if (!SI->getNumCases() || max_size < 16 || max_size % 8) { - continue; // LTO cannot bitcast from _ExtInt() :( - - } else { - - max_size = (((max_size / 8) + 1) * 8); - do_cast = 1; - - } + // if (!be_quiet) errs() << "skip trivial switch..\n"; + continue; } @@ -298,7 +286,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( max_size = 128; do_cast = 1; @@ -315,7 +302,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: - if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( cast_size = 128; do_cast = 1; @@ -504,22 +490,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (!max_size || max_size < 16) { continue; } - - if (max_size % 8) { - - if (is_lto) { - - continue; // LTO cannot bitcast from _ExtInt() :( - - } else { - - max_size = (((max_size / 8) + 1) * 8); - do_cast = 1; - - } - - } + if (!max_size || max_size % 8 || max_size < 16) { continue; } if (max_size > 128) { @@ -531,7 +502,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( max_size = 128; do_cast = 1; @@ -548,7 +518,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: - if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( cast_size = 128; do_cast = 1; diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index aff58ad5..bace0ff6 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3917,7 +3917,6 @@ static void internal_malloc_stats(mstate m) { \ } else if (RTCHECK(B == smallbin_at(M, I) || \ \ - \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4129,7 +4128,6 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ - \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4146,7 +4144,6 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ - \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4159,14 +4156,12 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ - \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ \ - \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-cc.c b/src/afl-cc.c index 959c9a6f..d41f79a2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1875,8 +1875,6 @@ int main(int argc, char **argv, char **envp) { edit_params(argc, argv, envp); - if (lto_mode) { setenv("_AFL_LTO_COMPILE", "1", 1); } - if (debug) { DEBUGF("cd '%s';", getthecwd()); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index cf65d3c1..275af9c8 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1547,7 +1547,6 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, is_n = 1; } - #endif for (i = 0; i < loggeds; ++i) { -- cgit 1.4.1 From 80bdbf7be0a1e7bd54b24d4376048d85fb403bf6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 16 Feb 2021 09:54:15 +0100 Subject: minor cmplog fix --- docs/Changelog.md | 1 + instrumentation/cmplog-instructions-pass.cc | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 71ef4c2c..477498d0 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -48,6 +48,7 @@ sending a mail to . support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang - fixed a potential crash in the LAF feature + - workaround for llvm bitcast lto bug - workaround for llvm 13 - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 50ade9fd..dbca9afa 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -266,13 +266,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) { unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; unsigned char do_cast = 0; - if (!SI->getNumCases() || max_size < 16 || max_size % 8) { + if (!SI->getNumCases() || max_size < 16) { // if (!be_quiet) errs() << "skip trivial switch..\n"; continue; } + if (max_size % 8) { + + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } + IRBuilder<> IRB(SI->getParent()); IRB.SetInsertPoint(SI); @@ -310,8 +317,10 @@ bool CmpLogInstructions::hookInstrs(Module &M) { Value *CompareTo = Val; if (do_cast) { + CompareTo = IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false); + } for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; @@ -331,8 +340,10 @@ bool CmpLogInstructions::hookInstrs(Module &M) { Value *new_param = cint; if (do_cast) { + new_param = IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false); + } if (new_param) { @@ -490,7 +501,14 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (!max_size || max_size % 8 || max_size < 16) { continue; } + if (!max_size || max_size < 16) { continue; } + + if (max_size % 8) { + + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } if (max_size > 128) { -- cgit 1.4.1 From a252943236b12c080248747bee06c9c5084b871e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 12:59:01 +0100 Subject: another fix for disabled entries --- docs/Changelog.md | 1 + src/afl-fuzz.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 477498d0..a006fccb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -32,6 +32,7 @@ sending a mail to . after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map - fix for `-Z` + - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e2db029d..24d77cc9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1770,12 +1770,15 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->old_seed_selection)) { afl->current_entry = 0; - while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) { + while (unlikely(afl->current_entry < afl->queued_paths && + afl->queue_buf[afl->current_entry]->disabled)) { ++afl->current_entry; } + if (afl->current_entry >= afl->queued_paths) { afl->current_entry = 0; } + afl->queue_cur = afl->queue_buf[afl->current_entry]; if (unlikely(seek_to)) { -- cgit 1.4.1 From fb2a6b6941ffb6cf575d2a772c6e0d47b49835ee Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 16:56:35 +0100 Subject: minimum sync time --- docs/Changelog.md | 1 + include/afl-fuzz.h | 1 + include/config.h | 5 +++++ src/afl-fuzz-run.c | 2 ++ src/afl-fuzz.c | 15 ++++++++++++--- 5 files changed, 21 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index a006fccb..d8587334 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,6 +35,7 @@ sending a mail to . - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis + - added minimum SYNC_TIME to include/config.h (30 minutes default) - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 10d94fed..e191543a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -570,6 +570,7 @@ typedef struct afl_state { blocks_eff_total, /* Blocks subject to effector maps */ blocks_eff_select, /* Blocks selected as fuzzable */ start_time, /* Unix start time (ms) */ + last_sync_time, /* Time of last sync */ last_path_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ last_hang_time; /* Time for most recent hang (ms) */ diff --git a/include/config.h b/include/config.h index 535ce0d3..083cad23 100644 --- a/include/config.h +++ b/include/config.h @@ -280,6 +280,11 @@ #define SYNC_INTERVAL 8 +/* Sync time (minimum time between syncing in ms, time is halfed for -M main + nodes): */ + +#define SYNC_TIME 18000000LLU /* 18000000 = 30 minutes */ + /* Output directory reuse grace period (minutes): */ #define OUTPUT_GRACE 25 diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 97cb7415..0b84a542 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -707,6 +707,8 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); + afl->last_sync_time = get_cur_time(); + } /* Trim all new test cases to save cycles when doing deterministic checks. The diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9137dc23..f83aac9e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1986,15 +1986,24 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->is_main_node)) { - if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { + if (unlikely(get_cur_time() > + (SYNC_TIME >> 1) + afl->last_sync_time)) { - sync_fuzzers(afl); + if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { + + sync_fuzzers(afl); + + } } } else { - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + if (unlikely(get_cur_time() > SYNC_TIME + afl->last_sync_time)) { + + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + + } } -- cgit 1.4.1 From a090b2013f2ea2da72d64b0bae4a75d57a268c5b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Feb 2021 12:02:44 +0100 Subject: docs --- docs/docs.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/docs.md (limited to 'docs') diff --git a/docs/docs.md b/docs/docs.md new file mode 100644 index 00000000..d4fd939e --- /dev/null +++ b/docs/docs.md @@ -0,0 +1,92 @@ +# Restructure afl++'s documentation + +## About us + +We are dedicated to everything around fuzzing, our main and most well known +contribution is the fuzzer `afl++` which is part of all major Unix +distributions (e.g. Debian, Arch, FreeBSD, etc.) and is deployed on Google's +oss-fuzz and clusterfuzz. It is rated the top fuzzer on Google's fuzzbench. + +We are four individuals from Europe supported by a large community. + +All our tools are open source. + +## About the afl++ fuzzer project + +afl++ inherited it's documentation from the original Google afl project. +Since then it has been massively improved - feature and performance wise - +and although the documenation has likewise been continued it has grown out +of proportion. +The documentation is done by non-natives to the English language, plus +none of us has a writer background. + +We see questions on afl++ usage on mailing lists (e.g. afl-users), discord +channels, web forums and as issues in our repository. + +This only increases as afl++ has been on the top of Google's fuzzbench +statistics (which measures the performance of fuzzers) and is now being +integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix +packaging repositories, e.g. Debian, FreeBSD, etc. + +afl++ now has 44 (!) documentation files with 13k total lines of content. +This is way too much. + +Hence afl++ needs a complete overhaul of it's documentation, both on a +organisation/structural level as well as the content. + +Overall the following actions have to be performed: + * Create a better structure of documentation so it is easier to find the + information that is being looked for, combining and/or splitting up the + existing documents as needed. + * Rewrite some documentation to remove duplication. Several information is + present several times in the documentation. These should be removed to + where needed so that we have as little bloat as possible. + * The documents have been written and modified by a lot of different people, + most of them non-native English speaker. Hence an overall review where + parts should be rewritten has to be performed and then the rewrite done. + * Create a cheat-sheet for a very short best-setup build and run of afl++ + * Pictures explain more than 1000 words. We need at least 4 images that + explain the workflow with afl++: + - the build workflow + - the fuzzing workflow + - the fuzzing campaign management workflow + - the overall workflow that is an overview of the above + - maybe more? where the technical writes seems it necessary for + understanding. + +Requirements: + * Documentation has to be in Markdown format + * Images have to be either in SVG or PNG format. + * All documentation should be (moved) in(to) docs/ + +The project does not require writing new documentation or tutorials beside the +cheat sheet. The technical information for the cheat sheet will be provided by +us. + +## Project Budget + +We have zero experience with technical writers, so this is very hard for us +to calculate. We expect it to be a lot of work though because of the amount +of documentation we have that needs to be restructured and rewritten +(44 documents with 13k total lines of content). + +Technical Writer 10000$ +Volunteer stipends 0$ (waved) +T-Shirts for the top 10 contributors and helpers to this documentation project: + 10 afl++ logo t-shirts 20$ each 200$ + 8 shipping cost of t-shirts 10$ each 80$ + (2 won't need to be shipped) + +Total: 10.280$ + +## Additional Information + +We have participated in Google Summer of Code in 2020 and hope to be selected +again in 2021. + +We have no experience with a technical writer, but we will support that person +with video calls, chats, emails and messaging, provide all necessary information +and write technical contents that is required for the success of this project. +It is clear to us that a technical writer knows how to write, but cannot know +the technical details in a complex tooling like in afl++. This guidance, input, +etc. has to come from us. -- cgit 1.4.1 From cc7c651dc97f5567af33164d396b390d36b46049 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 24 Feb 2021 18:07:08 +0100 Subject: tidied up env suggestions --- docs/Changelog.md | 3 ++- src/afl-common.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index d8587334..1260531e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -36,6 +36,7 @@ sending a mail to . - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - added minimum SYNC_TIME to include/config.h (30 minutes default) + - printing suggestions for mistyped `AFL_` env variables - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a @@ -68,7 +69,7 @@ sending a mail to . - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) + - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b) - @Edznux added a nice documentation on how to use rpc.statsd with afl++ in docs/rpc_statsd.md, thanks! diff --git a/src/afl-common.c b/src/afl-common.c index ce63c262..1628e517 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -529,6 +529,8 @@ static int string_distance_levenshtein(char *s1, char *s2) { s1len = strlen(s1); s2len = strlen(s2); unsigned int column[s1len + 1]; + column[s1len] = 1; + for (y = 1; y <= s1len; y++) column[y] = y; for (x = 1; x <= s2len; x++) { @@ -608,6 +610,8 @@ void print_suggested_envs(char *mispelled_env) { }; + ck_free(reduced); + } if (found) goto cleanup; -- cgit 1.4.1 From e2b4bc93103c1d311315e324833b7cb71d0677cc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 11:02:59 +0100 Subject: update changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 1260531e..9a61fac3 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -64,6 +64,7 @@ sending a mail to . - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings - afl-cmin and afl-showmap now support the -f option + - afl_plot now also generates a graph on the discovered edges - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars. - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. -- cgit 1.4.1 From 7ae7b0f3732cfd9d82cf9403818012d00faa07c3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 11:08:37 +0100 Subject: docs update --- docs/docs.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/docs.md b/docs/docs.md index d4fd939e..0f98bd54 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -67,17 +67,16 @@ us. We have zero experience with technical writers, so this is very hard for us to calculate. We expect it to be a lot of work though because of the amount -of documentation we have that needs to be restructured and rewritten +of documentation we have that needs to be restructured and partially rewritten (44 documents with 13k total lines of content). Technical Writer 10000$ Volunteer stipends 0$ (waved) T-Shirts for the top 10 contributors and helpers to this documentation project: 10 afl++ logo t-shirts 20$ each 200$ - 8 shipping cost of t-shirts 10$ each 80$ - (2 won't need to be shipped) + 10 shipping cost of t-shirts 10$ each 100$ -Total: 10.280$ +Total: 10.300$ ## Additional Information -- cgit 1.4.1 From ee0ca07f3c9f7c5971440f5dca70a2ee6f37584d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 12:19:46 +0100 Subject: changing the -t ...+ meaning to "auto-calculate buth this is the max" --- README.md | 7 ++++++- docs/Changelog.md | 21 +++++++++++++-------- src/afl-fuzz-init.c | 33 ++++++++++++--------------------- src/afl-fuzz-stats.c | 16 ++++++++-------- src/afl-fuzz.c | 33 +++++++++++++++++++++++++++++---- 5 files changed, 68 insertions(+), 42 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 0539752c..119426f6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,12 @@ For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. -## Major changes in afl++ 3.0 +## Major changes in afl++ 3.0 + 3.1 + +With afl++ 3.1 we introduced the following changes from previous behaviours: + * The '+' feature of the '-t' option now means to auto-calculate the timeout + with the value given being the maximum timeout. The original meaning of + "skipping timeouts instead of abort" is now inherent to the -t option. With afl++ 3.0 we introduced changes that break some previous afl and afl++ behaviours and defaults: diff --git a/docs/Changelog.md b/docs/Changelog.md index 9a61fac3..c4347baf 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,26 +16,31 @@ sending a mail to . to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz - - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on start - the target map size + - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on + start the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). This is costly hence new command line option - `-l` that sets the intensity (values 1 to 3). Recommended is 1 or 2. - - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from - `-i` or resumes (as these have most likely already been done) + `-l` that sets the intensity (values 1 to 3). Recommended is 2. + - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial seeds + from `-i` or resumes (these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now reloaded and used, thanks to Vimal Joseph for this patch! - - if deterministic mode is active (`-D`, or `-M` without `-d`) then we sync - after every queue entry as this can take very long time otherwise + - changed the meaning of '+' of the '-t' option, it now means to + auto-calculate the timeout with the value given being the max + timeout. The original meaning of skipping timeouts instead of + abort is now inherent to the -t option. + - if deterministic mode is active (`-D`, or `-M` without `-d`) then + we sync after every queue entry as this can take very long time + otherwise + - added minimum SYNC_TIME to include/config.h (30 minutes default) - better detection if a target needs a large shared map - fix for `-Z` - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - - added minimum SYNC_TIME to include/config.h (30 minutes default) - printing suggestions for mistyped `AFL_` env variables - afl-cc - allow instrumenting LLVMFuzzerTestOneInput diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d85a83e0..3dbc4c65 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -882,32 +882,23 @@ void perform_dry_run(afl_state_t *afl) { if (afl->timeout_given) { - /* The -t nn+ syntax in the command line sets afl->timeout_given to - '2' and instructs afl-fuzz to tolerate but skip queue entries that - time out. */ + /* if we have a timeout but a timeout value was given then always + skip. The '+' meaning has been changed! */ + WARNF("Test case results in a timeout (skipping)"); + ++cal_failures; + q->cal_failed = CAL_CHANCES; + q->disabled = 1; + q->perf_score = 0; - if (afl->timeout_given > 1) { + if (!q->was_fuzzed) { - WARNF("Test case results in a timeout (skipping)"); - q->cal_failed = CAL_CHANCES; - ++cal_failures; - break; + q->was_fuzzed = 1; + --afl->pending_not_fuzzed; + --afl->active_paths; } - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial " - "test cases.\n" - " Usually, the right thing to do is to relax the -t option - " - "or to delete it\n" - " altogether and allow the fuzzer to auto-calibrate. That " - "said, if you know\n" - " what you are doing and want to simply skip the unruly test " - "cases, append\n" - " '+' at the end of the value passed to -t ('-t %u+').\n", - afl->fsrv.exec_tmout, afl->fsrv.exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); + break; } else { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 42c71b05..bd856088 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -388,13 +388,13 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, execs_per_sec, edges_found */ - fprintf( - afl->fsrv.plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %u\n", - get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, - afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, - bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps, - afl->plot_prev_ed, t_bytes); /* ignore errors */ + fprintf(afl->fsrv.plot_file, + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, " + "%u\n", + get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, + afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, + bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, + eps, afl->plot_prev_ed, t_bytes); /* ignore errors */ fflush(afl->fsrv.plot_file); @@ -1219,7 +1219,7 @@ void show_init_stats(afl_state_t *afl) { stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), stringify_int(IB(2), avg_us)); - if (!afl->timeout_given) { + if (afl->timeout_given != 1) { /* Figure out the appropriate timeout. The basic idea is: 5x average or 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5810e9a9..a02eadb2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -103,9 +103,10 @@ static void usage(u8 *argv0, int more_help) { " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-... ms, default " - "%u ms)\n" - " add a '+' to skip over seeds running longer.\n" + " -t msec - timeout for each run (auto-scaled, default %u ms). " + "Add a '+'\n" + " to auto-calculate the timeout, the value being the " + "maximum.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" " -Q - use binary-only instrumentation (QEMU mode)\n" @@ -1453,7 +1454,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!afl->timeout_given) { find_timeout(afl); } + if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL && !afl->in_place_resume) { @@ -1718,6 +1719,30 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->timeout_given == 2) { // -t ...+ option + + if (valid_seeds == 1) { + + WARNF( + "Only one valid seed is present, auto-calculating the timeout is " + "disabled!"); + afl->timeout_given = 1; + + } else { + + u64 max_ms = 0; + + for (entry = 0; entry < afl->queued_paths; ++entry) + if (!afl->queue_buf[entry]->disabled) + if (afl->queue_buf[entry]->exec_us > max_ms) + max_ms = afl->queue_buf[entry]->exec_us; + + afl->fsrv.exec_tmout = max_ms; + + } + + } + show_init_stats(afl); if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl); -- cgit 1.4.1 From a5da9ce42cab1eab93cf80ca744944ae26e6ab58 Mon Sep 17 00:00:00 2001 From: julihoh Date: Sat, 27 Feb 2021 15:05:13 +0100 Subject: custom mutator rust support (#752) * custom mutator rust support * clarify how to view documentation for rust mutators * remove `FuzzResult` hack and clarify lifetimes of CustomMutator::fuzz * rename TErr associated tyep to Error to be more idiomatic * fix warnings * add example for fallible custom mutator * make Fallible Custom Mutator the default and implement it's handle_err method by default * rename CustomMutator::handle_err to handle_error * add example mutator using lain --- custom_mutators/rust/.gitignore | 10 + custom_mutators/rust/Cargo.toml | 7 + custom_mutators/rust/README.md | 9 + custom_mutators/rust/custom_mutator-sys/Cargo.toml | 12 + custom_mutators/rust/custom_mutator-sys/build.rs | 42 ++ custom_mutators/rust/custom_mutator-sys/src/lib.rs | 5 + custom_mutators/rust/custom_mutator-sys/wrapper.h | 4 + custom_mutators/rust/custom_mutator/Cargo.toml | 13 + custom_mutators/rust/custom_mutator/src/lib.rs | 637 +++++++++++++++++++++ custom_mutators/rust/example/Cargo.toml | 13 + custom_mutators/rust/example/src/lib.rs | 50 ++ custom_mutators/rust/example_lain/Cargo.toml | 14 + custom_mutators/rust/example_lain/rust-toolchain | 1 + custom_mutators/rust/example_lain/src/lib.rs | 60 ++ docs/custom_mutators.md | 5 + 15 files changed, 882 insertions(+) create mode 100644 custom_mutators/rust/.gitignore create mode 100644 custom_mutators/rust/Cargo.toml create mode 100644 custom_mutators/rust/README.md create mode 100644 custom_mutators/rust/custom_mutator-sys/Cargo.toml create mode 100644 custom_mutators/rust/custom_mutator-sys/build.rs create mode 100644 custom_mutators/rust/custom_mutator-sys/src/lib.rs create mode 100644 custom_mutators/rust/custom_mutator-sys/wrapper.h create mode 100644 custom_mutators/rust/custom_mutator/Cargo.toml create mode 100644 custom_mutators/rust/custom_mutator/src/lib.rs create mode 100644 custom_mutators/rust/example/Cargo.toml create mode 100644 custom_mutators/rust/example/src/lib.rs create mode 100644 custom_mutators/rust/example_lain/Cargo.toml create mode 100644 custom_mutators/rust/example_lain/rust-toolchain create mode 100644 custom_mutators/rust/example_lain/src/lib.rs (limited to 'docs') diff --git a/custom_mutators/rust/.gitignore b/custom_mutators/rust/.gitignore new file mode 100644 index 00000000..088ba6ba --- /dev/null +++ b/custom_mutators/rust/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/custom_mutators/rust/Cargo.toml b/custom_mutators/rust/Cargo.toml new file mode 100644 index 00000000..003bc58a --- /dev/null +++ b/custom_mutators/rust/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "custom_mutator-sys", + "custom_mutator", + "example", + "example_lain", +] \ No newline at end of file diff --git a/custom_mutators/rust/README.md b/custom_mutators/rust/README.md new file mode 100644 index 00000000..119ac790 --- /dev/null +++ b/custom_mutators/rust/README.md @@ -0,0 +1,9 @@ +Bindings to create custom mutators in Rust. + +These bindings are documented with rustdoc. To view the documentation run +```cargo doc -p custom_mutator --open```. + +A minimal example can be found in `example`. + +An example using [lain](https://github.com/microsoft/lain) can be found in `example_lain`. +Since lain requires a nightly rust toolchain, you need to set one up before you can play with it. diff --git a/custom_mutators/rust/custom_mutator-sys/Cargo.toml b/custom_mutators/rust/custom_mutator-sys/Cargo.toml new file mode 100644 index 00000000..104f7df0 --- /dev/null +++ b/custom_mutators/rust/custom_mutator-sys/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "custom_mutator-sys" +version = "0.1.0" +authors = ["Julius Hohnerlein "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[build-dependencies] +bindgen = "0.56" diff --git a/custom_mutators/rust/custom_mutator-sys/build.rs b/custom_mutators/rust/custom_mutator-sys/build.rs new file mode 100644 index 00000000..3c88a90d --- /dev/null +++ b/custom_mutators/rust/custom_mutator-sys/build.rs @@ -0,0 +1,42 @@ +extern crate bindgen; + +use std::env; +use std::path::PathBuf; + +// this code is largely taken straight from the handbook: https://github.com/fitzgen/bindgen-tutorial-bzip2-sys +fn main() { + // Tell cargo to invalidate the built crate whenever the wrapper changes + println!("cargo:rerun-if-changed=wrapper.h"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header("wrapper.h") + .whitelist_type("afl_state_t") + .blacklist_type(r"u\d+") + .opaque_type(r"_.*") + .opaque_type("FILE") + .opaque_type("in_addr(_t)?") + .opaque_type("in_port(_t)?") + .opaque_type("sa_family(_t)?") + .opaque_type("sockaddr_in(_t)?") + .opaque_type("time_t") + .rustfmt_bindings(true) + .size_t_is_usize(true) + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/custom_mutators/rust/custom_mutator-sys/src/lib.rs b/custom_mutators/rust/custom_mutator-sys/src/lib.rs new file mode 100644 index 00000000..a38a13a8 --- /dev/null +++ b/custom_mutators/rust/custom_mutator-sys/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/custom_mutators/rust/custom_mutator-sys/wrapper.h b/custom_mutators/rust/custom_mutator-sys/wrapper.h new file mode 100644 index 00000000..81cdb90f --- /dev/null +++ b/custom_mutators/rust/custom_mutator-sys/wrapper.h @@ -0,0 +1,4 @@ +#include "../../../include/afl-fuzz.h" +#include "../../../include/common.h" +#include "../../../include/config.h" +#include "../../../include/debug.h" diff --git a/custom_mutators/rust/custom_mutator/Cargo.toml b/custom_mutators/rust/custom_mutator/Cargo.toml new file mode 100644 index 00000000..2d3cdbfa --- /dev/null +++ b/custom_mutators/rust/custom_mutator/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "custom_mutator" +version = "0.1.0" +authors = ["Julius Hohnerlein "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +afl_internals = ["custom_mutator-sys"] + +[dependencies] +custom_mutator-sys = { path = "../custom_mutator-sys", optional=true } diff --git a/custom_mutators/rust/custom_mutator/src/lib.rs b/custom_mutators/rust/custom_mutator/src/lib.rs new file mode 100644 index 00000000..0fb007ab --- /dev/null +++ b/custom_mutators/rust/custom_mutator/src/lib.rs @@ -0,0 +1,637 @@ +//! Somewhat safe and somewhat ergonomic bindings for creating [AFL++](https://github.com/AFLplusplus/AFLplusplus) [custom mutators](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/custom_mutators.md) in Rust. +//! +//! # Usage +//! AFL++ custom mutators are expected to be dynamic libraries which expose a set of symbols. +//! Check out [`CustomMutator`] to see which functions of the API are supported. +//! Then use [`export_mutator`] to export the correct symbols for your mutator. +//! In order to use the mutator, your crate needs to be a library crate and have a `crate-type` of `cdylib`. +//! Putting +//! ```yaml +//! [lib] +//! crate-type = ["cdylib"] +//! ``` +//! into your `Cargo.toml` should do the trick. +//! The final executable can be found in `target/(debug|release)/your_crate_name.so`. +//! # Example +//! See [`export_mutator`] for an example. +//! +//! # On `panic`s +//! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++. +//! +//! # Access to AFL++ internals +//! This crate has an optional feature "afl_internals", which gives access to AFL++'s internal state. +//! The state is passed to [`CustomMutator::init`], when the feature is activated. +//! +//! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._ +use std::{ffi::CStr, fmt::Debug, os::raw::c_uint}; + +#[cfg(feature = "afl_internals")] +#[doc(hidden)] +pub use custom_mutator_sys::afl_state; + +#[allow(unused_variables)] +#[doc(hidden)] +pub trait RawCustomMutator { + #[cfg(feature = "afl_internals")] + fn init(afl: &'static afl_state, seed: c_uint) -> Self + where + Self: Sized; + #[cfg(not(feature = "afl_internals"))] + fn init(seed: c_uint) -> Self + where + Self: Sized; + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Option<&'b [u8]>; + + fn fuzz_count(&mut self, buffer: &[u8]) -> u32 { + 1 + } + + fn queue_new_entry(&mut self, filename_new_queue: &CStr, _filename_orig_queue: Option<&CStr>) {} + + fn queue_get(&mut self, filename: &CStr) -> bool { + true + } + + fn describe(&mut self, max_description: usize) -> Option<&CStr> { + None + } + + fn introspection(&mut self) -> Option<&CStr> { + None + } + + /*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize; + int afl_custom_init_trim(&self, buffer: &[u8]); + size_t afl_custom_trim(&self, unsigned char **out_buf); + int afl_custom_post_trim(&self, unsigned char success); + size_t afl_custom_havoc_mutation(&self, buffer: &[u8], unsigned char **out_buf, size_t max_size); + unsigned char afl_custom_havoc_mutation_probability(&self);*/ +} + +/// Wrappers for the custom mutator which provide the bridging between the C API and CustomMutator. +/// These wrappers are not intended to be used directly, rather export_mutator will use them to publish the custom mutator C API. +#[doc(hidden)] +pub mod wrappers { + #[cfg(feature = "afl_internals")] + use custom_mutator_sys::afl_state; + + use core::slice; + use std::{ + any::Any, + convert::TryInto, + ffi::{c_void, CStr}, + mem::ManuallyDrop, + os::raw::{c_char, c_uint}, + panic::catch_unwind, + process::abort, + ptr::null, + }; + + use crate::RawCustomMutator; + + /// A structure to be used as the data pointer for our custom mutator. This was used as additional storage and is kept for now in case its needed later. + /// Also has some convenience functions for FFI conversions (from and to ptr) and tries to make misuse hard (see [`FFIContext::from`]). + struct FFIContext { + mutator: M, + } + + impl FFIContext { + fn from(ptr: *mut c_void) -> ManuallyDrop> { + assert!(!ptr.is_null()); + ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut Self) }) + } + + fn into_ptr(self: Box) -> *const c_void { + Box::into_raw(self) as *const c_void + } + + #[cfg(feature = "afl_internals")] + fn new(afl: &'static afl_state, seed: c_uint) -> Box { + Box::new(Self { + mutator: M::init(afl, seed), + }) + } + #[cfg(not(feature = "afl_internals"))] + fn new(seed: c_uint) -> Box { + Box::new(Self { + mutator: M::init(seed), + }) + } + } + + /// panic handler called for every panic + fn panic_handler(method: &str, panic_info: Box) -> ! { + use std::ops::Deref; + let cause = panic_info + .downcast_ref::() + .map(String::deref) + .unwrap_or_else(|| { + panic_info + .downcast_ref::<&str>() + .copied() + .unwrap_or("") + }); + eprintln!("A panic occurred at {}: {}", method, cause); + abort() + } + + /// Internal function used in the macro + #[cfg(not(feature = "afl_internals"))] + pub fn afl_custom_init_(seed: c_uint) -> *const c_void { + match catch_unwind(|| FFIContext::::new(seed).into_ptr()) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_init", err), + } + } + + /// Internal function used in the macro + #[cfg(feature = "afl_internals")] + pub fn afl_custom_init_( + afl: Option<&'static afl_state>, + seed: c_uint, + ) -> *const c_void { + match catch_unwind(|| { + let afl = afl.expect("mutator func called with NULL afl"); + FFIContext::::new(afl, seed).into_ptr() + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_init", err), + } + } + + /// Internal function used in the macro + pub unsafe fn afl_custom_fuzz_( + data: *mut c_void, + buf: *mut u8, + buf_size: usize, + out_buf: *mut *const u8, + add_buf: *mut u8, + add_buf_size: usize, + max_size: usize, + ) -> usize { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + if buf.is_null() { + panic!("null buf passed to afl_custom_fuzz") + } + if out_buf.is_null() { + panic!("null out_buf passed to afl_custom_fuzz") + } + let buff_slice = slice::from_raw_parts_mut(buf, buf_size); + let add_buff_slice = if add_buf.is_null() { + None + } else { + Some(slice::from_raw_parts(add_buf, add_buf_size)) + }; + match context + .mutator + .fuzz(buff_slice, add_buff_slice, max_size.try_into().unwrap()) + { + Some(buffer) => { + *out_buf = buffer.as_ptr(); + buffer.len().try_into().unwrap() + } + None => { + // return the input buffer with 0-length to let AFL skip this mutation attempt + *out_buf = buf; + 0 + } + } + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_fuzz", err), + } + } + + /// Internal function used in the macro + pub unsafe fn afl_custom_fuzz_count_( + data: *mut c_void, + buf: *const u8, + buf_size: usize, + ) -> u32 { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + if buf.is_null() { + panic!("null buf passed to afl_custom_fuzz") + } + let buf_slice = slice::from_raw_parts(buf, buf_size); + // see https://doc.rust-lang.org/nomicon/borrow-splitting.html + let ctx = &mut **context; + let mutator = &mut ctx.mutator; + mutator.fuzz_count(buf_slice) + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_fuzz_count", err), + } + } + + /// Internal function used in the macro + pub fn afl_custom_queue_new_entry_( + data: *mut c_void, + filename_new_queue: *const c_char, + filename_orig_queue: *const c_char, + ) { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + if filename_new_queue.is_null() { + panic!("received null filename_new_queue in afl_custom_queue_new_entry"); + } + let filename_new_queue = unsafe { CStr::from_ptr(filename_new_queue) }; + let filename_orig_queue = if !filename_orig_queue.is_null() { + Some(unsafe { CStr::from_ptr(filename_orig_queue) }) + } else { + None + }; + context + .mutator + .queue_new_entry(filename_new_queue, filename_orig_queue); + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_queue_new_entry", err), + } + } + + /// Internal function used in the macro + pub unsafe fn afl_custom_deinit_(data: *mut c_void) { + match catch_unwind(|| { + // drop the context + ManuallyDrop::into_inner(FFIContext::::from(data)); + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_deinit", err), + } + } + + /// Internal function used in the macro + pub fn afl_custom_introspection_(data: *mut c_void) -> *const c_char { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + if let Some(res) = context.mutator.introspection() { + res.as_ptr() + } else { + null() + } + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_introspection", err), + } + } + + /// Internal function used in the macro + pub fn afl_custom_describe_( + data: *mut c_void, + max_description_len: usize, + ) -> *const c_char { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + if let Some(res) = context.mutator.describe(max_description_len) { + res.as_ptr() + } else { + null() + } + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_describe", err), + } + } + + /// Internal function used in the macro + pub fn afl_custom_queue_get_( + data: *mut c_void, + filename: *const c_char, + ) -> u8 { + match catch_unwind(|| { + let mut context = FFIContext::::from(data); + assert!(!filename.is_null()); + + context + .mutator + .queue_get(unsafe { CStr::from_ptr(filename) }) as u8 + }) { + Ok(ret) => ret, + Err(err) => panic_handler("afl_custom_queue_get", err), + } + } +} + +/// exports the given Mutator as a custom mutator as the C interface that AFL++ expects. +/// It is not possible to call this macro multiple times, because it would define the custom mutator symbols multiple times. +/// # Example +/// ``` +/// # #[macro_use] extern crate custom_mutator; +/// # #[cfg(feature = "afl_internals")] +/// # use custom_mutator::afl_state; +/// # use custom_mutator::CustomMutator; +/// # use std::os::raw::c_uint; +/// struct MyMutator; +/// impl CustomMutator for MyMutator { +/// /// ... +/// # type Error = (); +/// # #[cfg(feature = "afl_internals")] +/// # fn init(_afl_state: &afl_state, _seed: c_uint) -> Result {unimplemented!()} +/// # #[cfg(not(feature = "afl_internals"))] +/// # fn init(_seed: c_uint) -> Result {unimplemented!()} +/// # fn fuzz<'b,'s:'b>(&'s mut self, _buffer: &'b mut [u8], _add_buff: Option<&[u8]>, _max_size: usize) -> Result,()> {unimplemented!()} +/// } +/// export_mutator!(MyMutator); +/// ``` +#[macro_export] +macro_rules! export_mutator { + ($mutator_type:ty) => { + #[cfg(feature = "afl_internals")] + #[no_mangle] + pub extern "C" fn afl_custom_init( + afl: ::std::option::Option<&'static $crate::afl_state>, + seed: ::std::os::raw::c_uint, + ) -> *const ::std::os::raw::c_void { + $crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed) + } + + #[cfg(not(feature = "afl_internals"))] + #[no_mangle] + pub extern "C" fn afl_custom_init( + _afl: *const ::std::os::raw::c_void, + seed: ::std::os::raw::c_uint, + ) -> *const ::std::os::raw::c_void { + $crate::wrappers::afl_custom_init_::<$mutator_type>(seed) + } + + #[no_mangle] + pub extern "C" fn afl_custom_fuzz_count( + data: *mut ::std::os::raw::c_void, + buf: *const u8, + buf_size: usize, + ) -> u32 { + unsafe { + $crate::wrappers::afl_custom_fuzz_count_::<$mutator_type>(data, buf, buf_size) + } + } + + #[no_mangle] + pub extern "C" fn afl_custom_fuzz( + data: *mut ::std::os::raw::c_void, + buf: *mut u8, + buf_size: usize, + out_buf: *mut *const u8, + add_buf: *mut u8, + add_buf_size: usize, + max_size: usize, + ) -> usize { + unsafe { + $crate::wrappers::afl_custom_fuzz_::<$mutator_type>( + data, + buf, + buf_size, + out_buf, + add_buf, + add_buf_size, + max_size, + ) + } + } + + #[no_mangle] + pub extern "C" fn afl_custom_queue_new_entry( + data: *mut ::std::os::raw::c_void, + filename_new_queue: *const ::std::os::raw::c_char, + filename_orig_queue: *const ::std::os::raw::c_char, + ) { + $crate::wrappers::afl_custom_queue_new_entry_::<$mutator_type>( + data, + filename_new_queue, + filename_orig_queue, + ) + } + + #[no_mangle] + pub extern "C" fn afl_custom_queue_get( + data: *mut ::std::os::raw::c_void, + filename: *const ::std::os::raw::c_char, + ) -> u8 { + $crate::wrappers::afl_custom_queue_get_::<$mutator_type>(data, filename) + } + + #[no_mangle] + pub extern "C" fn afl_custom_introspection( + data: *mut ::std::os::raw::c_void, + ) -> *const ::std::os::raw::c_char { + $crate::wrappers::afl_custom_introspection_::<$mutator_type>(data) + } + + #[no_mangle] + pub extern "C" fn afl_custom_describe( + data: *mut ::std::os::raw::c_void, + max_description_len: usize, + ) -> *const ::std::os::raw::c_char { + $crate::wrappers::afl_custom_describe_::<$mutator_type>(data, max_description_len) + } + + #[no_mangle] + pub extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) { + unsafe { $crate::wrappers::afl_custom_deinit_::<$mutator_type>(data) } + } + }; +} + +#[cfg(test)] +/// this sanity test is supposed to just find out whether an empty mutator being exported by the macro compiles +mod sanity_test { + use std::os::raw::c_uint; + + #[cfg(feature = "afl_internals")] + use super::afl_state; + + use super::{export_mutator, RawCustomMutator}; + + struct ExampleMutator; + + impl RawCustomMutator for ExampleMutator { + #[cfg(feature = "afl_internals")] + fn init(_afl: &afl_state, _seed: c_uint) -> Self { + unimplemented!() + } + + #[cfg(not(feature = "afl_internals"))] + fn init(_seed: c_uint) -> Self { + unimplemented!() + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + _buffer: &'b mut [u8], + _add_buff: Option<&[u8]>, + _max_size: usize, + ) -> Option<&'b [u8]> { + unimplemented!() + } + } + + export_mutator!(ExampleMutator); +} + +#[allow(unused_variables)] +/// A custom mutator. +/// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`]. +pub trait CustomMutator { + /// The error type. All methods must return the same error type. + type Error: Debug; + + /// The method which handles errors. + /// By default, this method will log the error to stderr if the environment variable "`AFL_CUSTOM_MUTATOR_DEBUG`" is set and non-empty. + /// After logging the error, execution will continue on a best-effort basis. + /// + /// This default behaviour can be customized by implementing this method. + fn handle_error(err: Self::Error) { + if std::env::var("AFL_CUSTOM_MUTATOR_DEBUG") + .map(|v| !v.is_empty()) + .unwrap_or(false) + { + eprintln!("Error in custom mutator: {:?}", err) + } + } + + #[cfg(feature = "afl_internals")] + fn init(afl: &'static afl_state, seed: c_uint) -> Result + where + Self: Sized; + + #[cfg(not(feature = "afl_internals"))] + fn init(seed: c_uint) -> Result + where + Self: Sized; + + fn fuzz_count(&mut self, buffer: &[u8]) -> Result { + Ok(1) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, Self::Error>; + + fn queue_new_entry( + &mut self, + filename_new_queue: &CStr, + filename_orig_queue: Option<&CStr>, + ) -> Result<(), Self::Error> { + Ok(()) + } + + fn queue_get(&mut self, filename: &CStr) -> Result { + Ok(true) + } + + fn describe(&mut self, max_description: usize) -> Result, Self::Error> { + Ok(None) + } + + fn introspection(&mut self) -> Result, Self::Error> { + Ok(None) + } +} + +impl RawCustomMutator for M +where + M: CustomMutator, + M::Error: Debug, +{ + #[cfg(feature = "afl_internals")] + fn init(afl: &'static afl_state, seed: c_uint) -> Self + where + Self: Sized, + { + match Self::init(afl, seed) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + panic!("Error in afl_custom_init") + } + } + } + + #[cfg(not(feature = "afl_internals"))] + fn init(seed: c_uint) -> Self + where + Self: Sized, + { + match Self::init(seed) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + panic!("Error in afl_custom_init") + } + } + } + + fn fuzz_count(&mut self, buffer: &[u8]) -> u32 { + match self.fuzz_count(buffer) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + 0 + } + } + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Option<&'b [u8]> { + match self.fuzz(buffer, add_buff, max_size) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } + + fn queue_new_entry(&mut self, filename_new_queue: &CStr, filename_orig_queue: Option<&CStr>) { + match self.queue_new_entry(filename_new_queue, filename_orig_queue) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + } + } + } + + fn queue_get(&mut self, filename: &CStr) -> bool { + match self.queue_get(filename) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + false + } + } + } + + fn describe(&mut self, max_description: usize) -> Option<&CStr> { + match self.describe(max_description) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } + + fn introspection(&mut self) -> Option<&CStr> { + match self.introspection() { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } +} diff --git a/custom_mutators/rust/example/Cargo.toml b/custom_mutators/rust/example/Cargo.toml new file mode 100644 index 00000000..0c89b200 --- /dev/null +++ b/custom_mutators/rust/example/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "example" +version = "0.1.0" +authors = ["Julius Hohnerlein "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +custom_mutator = { path = "../custom_mutator" } + +[lib] +crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example/src/lib.rs b/custom_mutators/rust/example/src/lib.rs new file mode 100644 index 00000000..4f9345c0 --- /dev/null +++ b/custom_mutators/rust/example/src/lib.rs @@ -0,0 +1,50 @@ +#![allow(unused_variables)] + +use custom_mutator::{export_mutator, CustomMutator}; +use std::os::raw::c_uint; + +struct ExampleMutator; + +impl CustomMutator for ExampleMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + buffer.reverse(); + Ok(Some(buffer)) + } +} + +struct OwnBufferExampleMutator { + own_buffer: Vec, +} + +impl CustomMutator for OwnBufferExampleMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self { + own_buffer: Vec::new(), + }) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + self.own_buffer.reverse(); + Ok(Some(self.own_buffer.as_slice())) + } +} + +export_mutator!(ExampleMutator); diff --git a/custom_mutators/rust/example_lain/Cargo.toml b/custom_mutators/rust/example_lain/Cargo.toml new file mode 100644 index 00000000..1f68c7e0 --- /dev/null +++ b/custom_mutators/rust/example_lain/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "example_lain" +version = "0.1.0" +authors = ["Julius Hohnerlein "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +custom_mutator = { path = "../custom_mutator" } +lain="0.5" + +[lib] +crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example_lain/rust-toolchain b/custom_mutators/rust/example_lain/rust-toolchain new file mode 100644 index 00000000..07ade694 --- /dev/null +++ b/custom_mutators/rust/example_lain/rust-toolchain @@ -0,0 +1 @@ +nightly \ No newline at end of file diff --git a/custom_mutators/rust/example_lain/src/lib.rs b/custom_mutators/rust/example_lain/src/lib.rs new file mode 100644 index 00000000..3336e861 --- /dev/null +++ b/custom_mutators/rust/example_lain/src/lib.rs @@ -0,0 +1,60 @@ +use custom_mutator::{export_mutator, CustomMutator}; +use lain::{ + mutator::Mutator, + prelude::*, + rand::{rngs::StdRng, SeedableRng}, +}; +use std::os::raw::c_uint; + +#[derive(Debug, Mutatable, NewFuzzed, BinarySerialize)] +struct MyStruct { + field_1: u8, + + #[lain(bits = 3)] + field_2: u8, + + #[lain(bits = 5)] + field_3: u8, + + #[lain(min = 5, max = 10000)] + field_4: u32, + + #[lain(ignore)] + ignored_field: u64, +} + +struct LainMutator { + mutator: Mutator, + buffer: Vec, +} + +impl CustomMutator for LainMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self { + mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)), + buffer: Vec::new(), + }) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + _buffer: &'b mut [u8], + _add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + // we just sample an instance of MyStruct, ignoring the current input + let instance = MyStruct::new_fuzzed(&mut self.mutator, None); + let size = instance.serialized_size(); + if size > max_size { + return Err(()); + } + self.buffer.clear(); + self.buffer.reserve(size); + instance.binary_serialize::<_, BigEndian>(&mut self.buffer); + Ok(Some(self.buffer.as_slice())) + } +} + +export_mutator!(LainMutator); diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index a2c544e3..61d711e4 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -4,6 +4,11 @@ This file describes how you can implement custom mutations to be used in AFL. For now, we support C/C++ library and Python module, collectivelly named as the custom mutator. +There is also experimental support for Rust in `custom_mutators/rust`. +Please refer to that directory for documentation. +Run ```cargo doc -p custom_mutator --open``` in that directory to view the +documentation in your web browser. + Implemented by - C/C++ library (`*.so`): Khaled Yakdan from Code Intelligence () - Python module: Christian Holler from Mozilla () -- cgit 1.4.1 From af628b16d1b601f75e46f4b0475a055088019263 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 16:29:29 +0100 Subject: added rust binding reference --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index c4347baf..e434e7d6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -118,6 +118,7 @@ sending a mail to . mutation reproduction on crashing inputs - new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored console output (when configured with USE_COLOR and not ALWAYS_COLORED) + - added Rust bindings for custom mutators (thanks @julihoh) - instrumentation - We received an enhanced gcc_plugin module from AdaCore, thank you very much!! -- cgit 1.4.1 From 8e051fd075e2854930bf828c5d23fe6dc648e1ed Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 16:37:00 +0100 Subject: fixed rust bindings placement --- docs/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index e434e7d6..192d6ee2 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -42,6 +42,7 @@ sending a mail to . - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - printing suggestions for mistyped `AFL_` env variables + - added Rust bindings for custom mutators (thanks @julihoh) - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a @@ -118,7 +119,6 @@ sending a mail to . mutation reproduction on crashing inputs - new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored console output (when configured with USE_COLOR and not ALWAYS_COLORED) - - added Rust bindings for custom mutators (thanks @julihoh) - instrumentation - We received an enhanced gcc_plugin module from AdaCore, thank you very much!! -- cgit 1.4.1 From 5cf0655071a83b1c87490be8399fe2365f087223 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 28 Feb 2021 10:01:35 +0100 Subject: metrics --- docs/docs.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/docs.md b/docs/docs.md index 0f98bd54..ed6ec85e 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -63,6 +63,31 @@ The project does not require writing new documentation or tutorials beside the cheat sheet. The technical information for the cheat sheet will be provided by us. +## Metrics + +afl++ is a the highest performant fuzzer publicly available - but is also the +most feature rich and complex. With the publicity of afl++' success and +deployment in Google projects internally and externally and availability as +a package on most Linux distributions we see more and more issues being +created and help requests on our Discord channel that would not be +necessary if people would have read through all our documentation - which +is unrealistic. + +We expect the the new documenation after this project to be cleaner, easier +accessible and lighter to digest by our users, resulting in much less +help requests. On the other hand the amount of users using afl++ should +increase as well as it will be more accessible which would also increase +questions again - but overall resulting in a reduction of help requests. + +In numbers: we currently have per week on average 5 issues on Github, +10 questions on discord and 1 on mailing lists that would not be necessary +with perfect documentation and perfect people. + +We would consider this project a success if afterwards we only have +2 issues on Github and 3 questions on discord anymore that would be answered +by reading the documentation. The mailing list is usually used by the most +novice users and we don't expect any less questions there. + ## Project Budget We have zero experience with technical writers, so this is very hard for us @@ -70,13 +95,19 @@ to calculate. We expect it to be a lot of work though because of the amount of documentation we have that needs to be restructured and partially rewritten (44 documents with 13k total lines of content). +We assume the daily rate of a very good and experienced technical writer in +times of a pandemic to be ~500$ (according to web research), and calculate +the overall amout of work to be around 20 days for everything incl. the +graphics (but again - this is basically just guessing). + Technical Writer 10000$ Volunteer stipends 0$ (waved) T-Shirts for the top 10 contributors and helpers to this documentation project: 10 afl++ logo t-shirts 20$ each 200$ 10 shipping cost of t-shirts 10$ each 100$ - + Total: 10.300$ +(in the submission form 10.280$ was entered) ## Additional Information -- cgit 1.4.1 From 0c38850f955a608529bdd02cc39dc68713ef8528 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 09:43:35 +0100 Subject: 3.10c release --- README.md | 10 +++++----- docs/Changelog.md | 14 +++++++------- include/config.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 119426f6..800c2121 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ Logo - Release Version: [3.00c](https://github.com/AFLplusplus/AFLplusplus/releases) + Release Version: [3.10c](https://github.com/AFLplusplus/AFLplusplus/releases) - Github Version: 3.01a + Github Version: 3.11a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) @@ -25,14 +25,14 @@ For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. -## Major changes in afl++ 3.0 + 3.1 +## Major changes in afl++ 3.00 + 3.10 -With afl++ 3.1 we introduced the following changes from previous behaviours: +With afl++ 3.10 we introduced the following changes from previous behaviours: * The '+' feature of the '-t' option now means to auto-calculate the timeout with the value given being the maximum timeout. The original meaning of "skipping timeouts instead of abort" is now inherent to the -t option. -With afl++ 3.0 we introduced changes that break some previous afl and afl++ +With afl++ 3.00 we introduced changes that break some previous afl and afl++ behaviours and defaults: * There are no llvm_mode and gcc_plugin subdirectories anymore and there is diff --git a/docs/Changelog.md b/docs/Changelog.md index 192d6ee2..f3e15b6a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++3.01a (dev) +### Version ++3.10c (release) - Mac OS ARM64 support - Android support fixed and updated by Joey Jiaojg - thanks! - New selective instrumentation option with __AFL_COVERAGE_* commands @@ -49,10 +49,10 @@ sending a mail to . comment (thanks to Zherya for reporting) - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit - cmplog/redqueen can now process basic libc++ and libstdc++ - std::string comparisons (though no position or length type variants) - - added support for __afl_coverage_interesting() for LTO and - and our own PCGUARD (llvm 10.0.1+), read more about this function - and selective coverage in instrumentation/README.instrument_list.md + std::string comparisons (no position or length type variants) + - added support for __afl_coverage_interesting() for LTO and our + own PCGUARD (llvm 10.0.1+), read more about this function and + selective coverage in instrumentation/README.instrument_list.md - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang @@ -68,12 +68,12 @@ sending a mail to . - unicornafl - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - - Added a new example harness to compare python, c, and rust bindings + - Added a new example harness to compare python, c and rust bindings - afl-cmin and afl-showmap now support the -f option - afl_plot now also generates a graph on the discovered edges - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars. - - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. + - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b) diff --git a/include/config.h b/include/config.h index b0b1f7b9..c583f23b 100644 --- a/include/config.h +++ b/include/config.h @@ -25,8 +25,8 @@ /* Version string: */ -// c = release, d = volatile github dev, e = experimental branch -#define VERSION "++3.01a" +// c = release, a = volatile github dev, e = experimental branch +#define VERSION "++3.10c" /****************************************************** * * -- cgit 1.4.1 From 82c05630ba201bfc631e4e2335c6d8c2e76d91c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 10:12:42 +0100 Subject: 3.11a init --- docs/Changelog.md | 3 +++ include/config.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index f3e15b6a..4e3eef16 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,6 +8,9 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . +### Version ++3.11a (dev) + - ... + ### Version ++3.10c (release) - Mac OS ARM64 support diff --git a/include/config.h b/include/config.h index c583f23b..a3aa9a4a 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.10c" +#define VERSION "++3.11a" /****************************************************** * * -- cgit 1.4.1 From c3a8052a16f7d2d1947ea538719905a9d7a24d22 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 19:30:39 +0100 Subject: update changelog --- docs/Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 4e3eef16..f5742d24 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,8 +9,8 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.11a (dev) - - ... - + - afl-cc + - fixed for a crash that can occur with ASAN + CMPLOG together ### Version ++3.10c (release) - Mac OS ARM64 support -- cgit 1.4.1 From 333509bb0a56be9bd2e236f0e2f37d4af2dd7d59 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Mar 2021 16:24:43 +0100 Subject: better unicode support --- docs/Changelog.md | 3 ++- instrumentation/SanitizerCoverageLTO.so.cc | 14 +++++++++----- instrumentation/afl-llvm-dict2file.so.cc | 14 +++++++++----- instrumentation/afl-llvm-lto-instrumentation.so.cc | 14 +++++++++----- instrumentation/compare-transform-pass.so.cc | 11 +++++++++-- 5 files changed, 38 insertions(+), 18 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index f5742d24..01240b2a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,7 +10,8 @@ sending a mail to . ### Version ++3.11a (dev) - afl-cc - - fixed for a crash that can occur with ASAN + CMPLOG together + - fixed for a crash that can occur with ASAN + CMPLOG together plus + better support for unicode (thanks to @stbergmann for reporting!) ### Version ++3.10c (release) - Mac OS ARM64 support diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 942d5357..849b6eef 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -872,17 +872,21 @@ bool ModuleSanitizerCoverage::instrumentModule( // was not already added if (!isMemcmp) { - if (addedNull == false) { + if (addedNull == false && thestring[optLen - 1] != '\0') { thestring.append("\0", 1); // add null byte optLen++; } - // ensure we do not have garbage - size_t offset = thestring.find('\0', 0); - if (offset + 1 < optLen) optLen = offset + 1; - thestring = thestring.substr(0, optLen); + if (!isStdString) { + + // ensure we do not have garbage + size_t offset = thestring.find('\0', 0); + if (offset + 1 < optLen) optLen = offset + 1; + thestring = thestring.substr(0, optLen); + + } } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 1c365da8..885aa035 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -543,17 +543,21 @@ bool AFLdict2filePass::runOnModule(Module &M) { // was not already added if (!isMemcmp) { - if (addedNull == false) { + if (addedNull == false && thestring[optLen - 1] != '\0') { thestring.append("\0", 1); // add null byte optLen++; } - // ensure we do not have garbage - size_t offset = thestring.find('\0', 0); - if (offset + 1 < optLen) optLen = offset + 1; - thestring = thestring.substr(0, optLen); + if (!isStdString) { + + // ensure we do not have garbage + size_t offset = thestring.find('\0', 0); + if (offset + 1 < optLen) optLen = offset + 1; + thestring = thestring.substr(0, optLen); + + } } diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index 1f21b917..ef270a1f 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -658,17 +658,21 @@ bool AFLLTOPass::runOnModule(Module &M) { // was not already added if (!isMemcmp) { - if (addedNull == false) { + if (addedNull == false && thestring[optLen - 1] != '\0') { thestring.append("\0", 1); // add null byte optLen++; } - // ensure we do not have garbage - size_t offset = thestring.find('\0', 0); - if (offset + 1 < optLen) optLen = offset + 1; - thestring = thestring.substr(0, optLen); + if (!isStdString) { + + // ensure we do not have garbage + size_t offset = thestring.find('\0', 0); + if (offset + 1 < optLen) optLen = offset + 1; + thestring = thestring.substr(0, optLen); + + } } diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 84301493..a85522a2 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -421,14 +421,21 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } // add null termination character implicit in c strings - TmpConstStr.append("\0", 1); + if (TmpConstStr[TmpConstStr.length() - 1] != 0) { + + TmpConstStr.append("\0", 1); + + } // in the unusual case the const str has embedded null // characters, the string comparison functions should terminate // at the first null - if (!isMemcmp) + if (!isMemcmp) { + TmpConstStr.assign(TmpConstStr, 0, TmpConstStr.find('\0') + 1); + } + constStrLen = TmpConstStr.length(); // prefer use of StringRef (in comparison to std::string a StringRef has // built-in runtime bounds checking, which makes debugging easier) -- cgit 1.4.1 From 108e588e888df5c2679600ea49846a565bac23f9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Mar 2021 17:46:43 +0100 Subject: add de-unicoded dictionary entries --- docs/Changelog.md | 2 + include/afl-fuzz.h | 1 + src/afl-fuzz-extras.c | 149 ++++++++++++++++++++++++++++++++++++++++++-------- src/afl-fuzz.c | 7 ++- 4 files changed, 134 insertions(+), 25 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 01240b2a..376f5f06 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,8 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.11a (dev) + - afl-fuzz + - add non-unicode variants from unicode-looking dictionary entries - afl-cc - fixed for a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 3531d672..5003b563 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1062,6 +1062,7 @@ u8 has_new_bits_unclassified(afl_state_t *, u8 *); void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32); void load_extras(afl_state_t *, u8 *); void dedup_extras(afl_state_t *); +void deunicode_extras(afl_state_t *); void add_extra(afl_state_t *afl, u8 *mem, u32 len); void maybe_add_auto(afl_state_t *, u8 *, u32); void save_auto(afl_state_t *); diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 7ecad233..52100fa1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -387,6 +387,130 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) { } +/* add an extra/dict/token - no checks performed, no sorting */ + +static void add_extra_nocheck(afl_state_t *afl, u8 *mem, u32 len) { + + afl->extras = afl_realloc((void **)&afl->extras, + (afl->extras_cnt + 1) * sizeof(struct extra_data)); + + if (unlikely(!afl->extras)) { PFATAL("alloc"); } + + afl->extras[afl->extras_cnt].data = ck_alloc(len); + afl->extras[afl->extras_cnt].len = len; + memcpy(afl->extras[afl->extras_cnt].data, mem, len); + afl->extras_cnt++; + + /* We only want to print this once */ + + if (afl->extras_cnt == afl->max_det_extras + 1) { + + WARNF("More than %u tokens - will use them probabilistically.", + afl->max_det_extras); + + } + +} + +/* Sometimes strings in input is transformed to unicode internally, so for + fuzzing we should attempt to de-unicode if it looks like simple unicode */ + +void deunicode_extras(afl_state_t *afl) { + + if (!afl->extras_cnt) return; + + u32 i, j, orig_cnt = afl->extras_cnt; + u8 buf[64]; + + for (i = 0; i < orig_cnt; ++i) { + + if (afl->extras[i].len < 6 || afl->extras[i].len > 64 || + afl->extras[i].len % 2) { + + continue; + + } + + u32 k = 0, z1 = 0, z2 = 0, z3 = 0, z4 = 0, half = afl->extras[i].len >> 1; + u32 quarter = half >> 1; + + for (j = 0; j < afl->extras[i].len; ++j) { + + switch (j % 4) { + + case 2: + if (!afl->extras[i].data[j]) { ++z3; } + // fall through + case 0: + if (!afl->extras[i].data[j]) { ++z1; } + break; + case 3: + if (!afl->extras[i].data[j]) { ++z4; } + // fall through + case 1: + if (!afl->extras[i].data[j]) { ++z2; } + break; + + } + + } + + if ((z1 < half && z2 < half) || z1 + z2 == afl->extras[i].len) { continue; } + + // also maybe 32 bit unicode? + if (afl->extras[i].len % 4 == 0 && afl->extras[i].len >= 12 && + (z3 == quarter || z4 == quarter) && z1 + z2 == quarter * 3) { + + for (j = 0; j < afl->extras[i].len; ++j) { + + if (z4 < quarter) { + + if (j % 4 == 3) { buf[k++] = afl->extras[i].data[j]; } + + } else if (z3 < quarter) { + + if (j % 4 == 2) { buf[k++] = afl->extras[i].data[j]; } + + } else if (z2 < half) { + + if (j % 4 == 1) { buf[k++] = afl->extras[i].data[j]; } + + } else { + + if (j % 4 == 0) { buf[k++] = afl->extras[i].data[j]; } + + } + + } + + add_extra_nocheck(afl, buf, k); + k = 0; + + } + + for (j = 0; j < afl->extras[i].len; ++j) { + + if (z1 < half) { + + if (j % 2 == 0) { buf[k++] = afl->extras[i].data[j]; } + + } else { + + if (j % 2 == 1) { buf[k++] = afl->extras[i].data[j]; } + + } + + } + + add_extra_nocheck(afl, buf, k); + + } + + qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data), + compare_extras_len); + +} + /* Removes duplicates from the loaded extras. This can happen if multiple files are loaded */ @@ -396,9 +520,9 @@ void dedup_extras(afl_state_t *afl) { u32 i, j, orig_cnt = afl->extras_cnt; - for (i = 0; i < afl->extras_cnt - 1; i++) { + for (i = 0; i < afl->extras_cnt - 1; ++i) { - for (j = i + 1; j < afl->extras_cnt; j++) { + for (j = i + 1; j < afl->extras_cnt; ++j) { restart_dedup: @@ -462,30 +586,11 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) { } - afl->extras = afl_realloc((void **)&afl->extras, - (afl->extras_cnt + 1) * sizeof(struct extra_data)); - - if (unlikely(!afl->extras)) { PFATAL("alloc"); } - - afl->extras[afl->extras_cnt].data = ck_alloc(len); - afl->extras[afl->extras_cnt].len = len; - - memcpy(afl->extras[afl->extras_cnt].data, mem, len); - - afl->extras_cnt++; + add_extra_nocheck(afl, mem, len); qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data), compare_extras_len); - /* We only want to print this once */ - - if (afl->extras_cnt == afl->max_det_extras + 1) { - - WARNF("More than %u tokens - will use them probabilistically.", - afl->max_det_extras); - - } - } /* Maybe add automatic extra. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a02eadb2..90f77919 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1449,9 +1449,6 @@ int main(int argc, char **argv_orig, char **envp) { } - dedup_extras(afl); - OKF("Loaded a total of %u extras.", afl->extras_cnt); - } if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! @@ -1681,6 +1678,10 @@ int main(int argc, char **argv_orig, char **envp) { } + deunicode_extras(afl); + dedup_extras(afl); + if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); } + // after we have the correct bitmap size we can read the bitmap -B option // and set the virgin maps if (afl->in_bitmap) { -- cgit 1.4.1 From f0bc2e0e8b9d7b7e6e5371153f1b3bd7500cdae7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Mar 2021 18:45:41 +0100 Subject: docu --- TODO.md | 8 +++++++- docs/Changelog.md | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/TODO.md b/TODO.md index 4615c456..e5a678cf 100644 --- a/TODO.md +++ b/TODO.md @@ -2,12 +2,15 @@ ## Roadmap 3.00+ - - AFL_MAP_SIZE for qemu_mode and unicorn_mode - CPU affinity for many cores? There seems to be an issue > 96 cores - afl-plot to support multiple plot_data - afl_custom_fuzz_splice_optin() - afl_custom_splice() - intel-pt tracer + - better autodetection of shifting runtime timeout values + - cmplog: use colorization input for havoc? + - cmplog: too much tainted bytes, directly add to dict and skip? + ## Further down the road @@ -23,9 +26,12 @@ qemu_mode: - add/implement AFL_QEMU_INST_LIBLIST and AFL_QEMU_NOINST_PROGRAM - add/implement AFL_QEMU_INST_REGIONS as a list of _START/_END addresses + ## Ideas - LTO/sancov: write current edge to prev_loc and use that information when using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow up edge numbers that both following cmp paths have been found and then disable working on this edge id -> cmplog_intelligence branch + - use cmplog colorization taint result for havoc locations? + diff --git a/docs/Changelog.md b/docs/Changelog.md index 376f5f06..1be41267 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,7 +12,7 @@ sending a mail to . - afl-fuzz - add non-unicode variants from unicode-looking dictionary entries - afl-cc - - fixed for a crash that can occur with ASAN + CMPLOG together plus + - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) ### Version ++3.10c (release) -- cgit 1.4.1 From 96c526cb78512737a980726dd32c95593edb8cd1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 4 Mar 2021 14:04:40 +0100 Subject: fix caller/ctx change, support dlopen in afl-compiler-rt --- docs/Changelog.md | 10 ++++ instrumentation/LLVMInsTrim.so.cc | 29 ++++----- instrumentation/afl-compiler-rt.o.c | 114 +++++++++++++++++++++++++++++++----- src/afl-cc.c | 31 ++++++---- 4 files changed, 144 insertions(+), 40 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 1be41267..6fe3517a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,16 @@ sending a mail to . - afl-cc - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) + - handle erroneous setups in which multiple afl-compiler-rt are + compiled into the target. This now also supports dlopen instrumented + libs loaded before the forkserver. + - Renamed CTX to CALLER, added correct/real CTX implemenation to CLASSIC + - qemu_mode + - added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks! + - if no new/updated checkout is wanted, build with: + NO_CHECKOUT=1 ./build_qemu_support.sh + - we no longer perform a "git drop" + ### Version ++3.10c (release) - Mac OS ARM64 support diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc index 948f8f3a..f0de6536 100644 --- a/instrumentation/LLVMInsTrim.so.cc +++ b/instrumentation/LLVMInsTrim.so.cc @@ -135,7 +135,7 @@ struct InsTrim : public ModulePass { unsigned int PrevLocSize = 0; char * ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE"); if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE"); - char *ctx_str = getenv("AFL_LLVM_CTX"); + char *caller_str = getenv("AFL_LLVM_CALLER"); #ifdef AFL_HAVE_VECTOR_INTRINSICS unsigned int ngram_size = 0; @@ -197,9 +197,9 @@ struct InsTrim : public ModulePass { GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); GlobalVariable *AFLPrevLoc; GlobalVariable *AFLContext = NULL; - LoadInst * PrevCtx = NULL; // for CTX sensitive coverage + LoadInst * PrevCaller = NULL; // for CALLER sensitive coverage - if (ctx_str) + if (caller_str) #if defined(__ANDROID__) || defined(__HAIKU__) AFLContext = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx"); @@ -398,11 +398,11 @@ struct InsTrim : public ModulePass { unsigned int cur_loc; // Context sensitive coverage - if (ctx_str && &BB == &F.getEntryBlock()) { + if (caller_str && &BB == &F.getEntryBlock()) { - PrevCtx = IRB.CreateLoad(AFLContext); - PrevCtx->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); + PrevCaller = IRB.CreateLoad(AFLContext); + PrevCaller->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); // does the function have calls? and is any of the calls larger than // one basic block? @@ -441,7 +441,7 @@ struct InsTrim : public ModulePass { } - } // END of ctx_str + } // END of caller_str if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; } @@ -485,9 +485,9 @@ struct InsTrim : public ModulePass { #endif PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); - if (ctx_str) + if (caller_str) PrevLocTrans = - IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCtx), Int32Ty); + IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCaller), Int32Ty); /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); @@ -535,16 +535,17 @@ struct InsTrim : public ModulePass { IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - if (ctx_str && has_calls) { + if (caller_str && has_calls) { - // in CTX mode we have to restore the original context for the + // in CALLER mode we have to restore the original context for the // caller - she might be calling other functions which need the - // correct CTX + // correct CALLER Instruction *Inst = BB.getTerminator(); if (isa(Inst) || isa(Inst)) { IRBuilder<> Post_IRB(Inst); - StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); + StoreInst * RestoreCtx = + Post_IRB.CreateStore(PrevCaller, AFLContext); RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c9577a55..e3aa787f 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -123,6 +123,17 @@ static u8 is_persistent; static u8 _is_sancov; +/* Debug? */ + +static u32 __afl_debug; + +/* Already initialized markers */ + +static u32 __afl_already_initialized_shm; +static u32 __afl_already_initialized_forkserver; +static u32 __afl_already_initialized_first; +static u32 __afl_already_initialized_second; + /* Dummy pipe for area_is_valid() */ static int __afl_dummy_fd[2] = {2, 2}; @@ -176,7 +187,7 @@ static void __afl_map_shm_fuzz() { char *id_str = getenv(SHM_FUZZ_ENV_VAR); - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "DEBUG: fuzzcase shmem %s\n", id_str ? id_str : "none"); @@ -222,7 +233,7 @@ static void __afl_map_shm_fuzz() { __afl_fuzz_len = (u32 *)map; __afl_fuzz_ptr = map + sizeof(u32); - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "DEBUG: successfully got fuzzing shared memory\n"); @@ -242,7 +253,6 @@ static void __afl_map_shm_fuzz() { static void __afl_map_shm(void) { - static u32 __afl_already_initialized_shm = 0; if (__afl_already_initialized_shm) return; __afl_already_initialized_shm = 1; @@ -303,7 +313,7 @@ static void __afl_map_shm(void) { early-stage __afl_area_initial region that is needed to allow some really hacky .init code to work correctly in projects such as OpenSSL. */ - if (getenv("AFL_DEBUG")) + if (__afl_debug) fprintf(stderr, "DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, " "__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, " @@ -359,17 +369,18 @@ static void __afl_map_shm(void) { } + close(shm_fd); + if (shm_base == MAP_FAILED) { - close(shm_fd); shm_fd = -1; - fprintf(stderr, "mmap() failed\n"); + perror("mmap for map"); + if (__afl_map_addr) send_forkserver_error(FS_ERROR_MAP_ADDR); else send_forkserver_error(FS_ERROR_MMAP); - perror("mmap for map"); exit(2); @@ -476,7 +487,7 @@ static void __afl_map_shm(void) { id_str = getenv(CMPLOG_SHM_ENV_VAR); - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "DEBUG: cmplog id_str %s\n", id_str == NULL ? "" : id_str); @@ -541,6 +552,58 @@ static void __afl_map_shm(void) { } +/* unmap SHM. */ + +static void __afl_unmap_shm(void) { + + if (!__afl_already_initialized_shm) return; + + char *id_str = getenv(SHM_ENV_VAR); + + if (id_str) { + +#ifdef USEMMAP + + munmap((void *)__afl_area_ptr, __afl_map_size); + +#else + + shmdt((void *)__afl_area_ptr); + +#endif + + } else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) && + + __afl_map_addr) { + + munmap((void *)__afl_map_addr, __afl_map_size); + + } + + __afl_area_ptr = __afl_area_ptr_dummy; + + id_str = getenv(CMPLOG_SHM_ENV_VAR); + + if (id_str) { + +#ifdef USEMMAP + + munmap((void *)__afl_cmp_map, __afl_map_size); + +#else + + shmdt((void *)__afl_cmp_map); + +#endif + + __afl_cmp_map = NULL; + + } + + __afl_already_initialized_shm = 0; + +} + #ifdef __linux__ static void __afl_start_snapshots(void) { @@ -569,7 +632,7 @@ static void __afl_start_snapshots(void) { if (read(FORKSRV_FD, &was_killed, 4) != 4) { _exit(1); } - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "target forkserver recv: %08x\n", was_killed); @@ -746,7 +809,6 @@ static void __afl_start_snapshots(void) { static void __afl_start_forkserver(void) { - static u32 __afl_already_initialized_forkserver = 0; if (__afl_already_initialized_forkserver) return; __afl_already_initialized_forkserver = 1; @@ -800,7 +862,7 @@ static void __afl_start_forkserver(void) { if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "target forkserver recv: %08x\n", was_killed); @@ -1035,7 +1097,7 @@ void __afl_manual_init(void) { __afl_sharedmem_fuzzing = 0; if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_ptr_dummy; - if (getenv("AFL_DEBUG")) + if (__afl_debug) fprintf(stderr, "DEBUG: disabled instrumentation because of " "AFL_DISABLE_LLVM_INSTRUMENTATION\n"); @@ -1079,10 +1141,11 @@ __attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) { __attribute__((constructor(1))) void __afl_auto_second(void) { - static u32 __afl_already_initialized_second = 0; if (__afl_already_initialized_second) return; __afl_already_initialized_second = 1; + if (getenv("AFL_DEBUG")) { __afl_debug = 1; } + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; u8 *ptr; @@ -1114,7 +1177,6 @@ __attribute__((constructor(1))) void __afl_auto_second(void) { __attribute__((constructor(0))) void __afl_auto_first(void) { - static u32 __afl_already_initialized_first = 0; if (__afl_already_initialized_first) return; __afl_already_initialized_first = 1; @@ -1198,7 +1260,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { _is_sancov = 1; - if (getenv("AFL_DEBUG")) { + if (__afl_debug) { fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges)\n", @@ -1235,6 +1297,28 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } + if (__afl_debug) { + + fprintf(stderr, + "Done __sanitizer_cov_trace_pc_guard_init: __afl_final_loc = %u\n", + __afl_final_loc); + + } + + if (__afl_already_initialized_shm && __afl_final_loc > __afl_map_size) { + + if (__afl_debug) { + + fprintf(stderr, "Reinit shm necessary (+%u)\n", + __afl_final_loc - __afl_map_size); + + } + + __afl_unmap_shm(); + __afl_map_shm(); + + } + } ///// CmpLog instrumentation diff --git a/src/afl-cc.c b/src/afl-cc.c index 0c689286..ab794877 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -89,7 +89,7 @@ char instrument_mode_string[18][18] = { "GCC", "CLANG", "CTX", - "", + "CALLER", "", "", "", @@ -1514,12 +1514,13 @@ int main(int argc, char **argv, char **envp) { " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" + " - CALLER\n" " - CTX\n" " - NGRAM-{2-16}\n" " INSTRIM no yes module yes yes " " yes\n" " - NORMAL\n" - " - CTX\n" + " - CALLER\n" " - NGRAM-{2-16}\n" " [GCC_PLUGIN] gcc plugin: %s%s\n" " CLASSIC DEFAULT no yes no no no " @@ -1566,7 +1567,10 @@ int main(int argc, char **argv, char **envp) { NATIVE_MSG " CLASSIC: decision target instrumentation (README.llvm.md)\n" - " CTX: CLASSIC + callee context (instrumentation/README.ctx.md)\n" + " CALLER: CLASSIC + single callee context " + "(instrumentation/README.ctx.md)\n" + " CTX: CLASSIC + full callee context " + "(instrumentation/README.ctx.md)\n" " NGRAM-x: CLASSIC + previous path " "((instrumentation/README.ngram.md)\n" " INSTRIM: Dominator tree (for LLVM <= 6.0) " @@ -1660,15 +1664,17 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" - " CLASSIC, INSTRIM, PCGUARD, LTO, GCC, CLANG, CTX, NGRAM-2 ... " - "NGRAM-16\n" + " CLASSIC, INSTRIM, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, " + "NGRAM-2 ..-16\n" " You can also use the old environment variables instead:\n" " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed " "(option to INSTRIM)\n" - " AFL_LLVM_CTX: use context sensitive coverage (for CLASSIC and " - "INSTRIM)\n" + " AFL_LLVM_CALLER: use single context sensitive coverage (for " + "CLASSIC)\n" + " AFL_LLVM_CTX: use full context sensitive coverage (for " + "CLASSIC)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " "CLASSIC & INSTRIM)\n"); @@ -1814,11 +1820,14 @@ int main(int argc, char **argv, char **envp) { "(requires LLVM 11 or higher)"); #endif - if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC && - instrument_mode != INSTRUMENT_CFG) + if (instrument_opt_mode && instrument_mode == INSTRUMENT_CFG && + instrument_opt_mode & INSTRUMENT_OPT_CTX) + FATAL("CFG instrumentation mode supports NGRAM and CALLER, but not CTX."); + else if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) + // we will drop CFG/INSTRIM in the future so do not advertise FATAL( - "CTX and NGRAM instrumentation options can only be used with LLVM and " - "CFG or CLASSIC instrumentation modes!"); + "CALLER, CTX and NGRAM instrumentation options can only be used with " + "the LLVM CLASSIC instrumentation mode."); if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) FATAL( -- cgit 1.4.1 From 79d75d8e42e5adf64e149ab6e1fe197cb1d4f303 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 4 Mar 2021 14:19:00 +0100 Subject: even support dlopen instrumented libs after the forkserver --- docs/Changelog.md | 5 +++-- instrumentation/afl-compiler-rt.o.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 6fe3517a..b1c991ff 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,8 +15,9 @@ sending a mail to . - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) - handle erroneous setups in which multiple afl-compiler-rt are - compiled into the target. This now also supports dlopen instrumented - libs loaded before the forkserver. + compiled into the target. This now also supports dlopen + instrumented libs loaded before the forkserver and even after the + forkserver is started (then with collisions though) - Renamed CTX to CALLER, added correct/real CTX implemenation to CLASSIC - qemu_mode - added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks! diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index e3aa787f..87bf6486 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1263,8 +1263,10 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (__afl_debug) { fprintf(stderr, - "Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges)\n", - start, stop, (unsigned long)(stop - start)); + "Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges) " + "after_fs=%u\n", + start, stop, (unsigned long)(stop - start), + __afl_already_initialized_forkserver); } @@ -1280,6 +1282,36 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } + /* instrumented code is loaded *after* our forkserver is up. this is a + problem. We cannot prevent collisions then :( */ + if (__afl_already_initialized_forkserver && + __afl_final_loc + 1 + stop - start > __afl_map_size) { + + if (__afl_debug) + fprintf(stderr, "Warning: new instrumneted code after the forkserver!\n"); + __afl_final_loc = 2; + + if (1 + stop - start > __afl_map_size) { + + *(start++) = ++__afl_final_loc; + + while (start < stop) { + + if (R(100) < inst_ratio) + *start = ++__afl_final_loc % __afl_map_size; + else + *start = 0; + + start++; + + } + + return; + + } + + } + /* Make sure that the first element in the range is always set - we use that to avoid duplicate calls (which can happen as an artifact of the underlying implementation in LLVM). */ -- cgit 1.4.1 From 3342aa751d8e9102449e1739b38a25c40ab18e81 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 5 Mar 2021 10:05:43 +0100 Subject: fix laf string transform crash --- docs/Changelog.md | 1 + instrumentation/SanitizerCoverageLTO.so.cc | 3 +++ instrumentation/afl-llvm-dict2file.so.cc | 4 ++++ instrumentation/afl-llvm-lto-instrumentation.so.cc | 3 +++ instrumentation/compare-transform-pass.so.cc | 11 +++++++++-- 5 files changed, 20 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index b1c991ff..c5b275de 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,7 @@ sending a mail to . - afl-cc - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) + - fixed a crash in LAF transform for empty strings - handle erroneous setups in which multiple afl-compiler-rt are compiled into the target. This now also supports dlopen instrumented libs loaded before the forkserver and even after the diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 849b6eef..13a5e5fd 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -849,15 +849,18 @@ bool ModuleSanitizerCoverage::instrumentModule( thestring = Str2; optLen = thestring.length(); + if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; } if (isMemcmp || isStrncmp || isStrncasecmp) { Value * op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast(op2); + if (ilen) { uint64_t literalLength = optLen; optLen = ilen->getZExtValue(); + if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte thestring.append("\0", 1); addedNull = true; diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 885aa035..c954054b 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -521,14 +521,18 @@ bool AFLdict2filePass::runOnModule(Module &M) { optLen = thestring.length(); + if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; } + if (isMemcmp || isStrncmp || isStrncasecmp) { Value * op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast(op2); + if (ilen) { uint64_t literalLength = optLen; optLen = ilen->getZExtValue(); + if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte thestring.append("\0", 1); addedNull = true; diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index ef270a1f..50306224 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -635,15 +635,18 @@ bool AFLLTOPass::runOnModule(Module &M) { thestring = Str2; optLen = thestring.length(); + if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; } if (isMemcmp || isStrncmp || isStrncasecmp) { Value * op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast(op2); + if (ilen) { uint64_t literalLength = optLen; optLen = ilen->getZExtValue(); + if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte thestring.append("\0", 1); addedNull = true; diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index a85522a2..3ecba4e6 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -316,7 +316,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, uint64_t len = ilen->getZExtValue(); // if len is zero this is a pointless call but allow real // implementation to worry about that - if (!len) continue; + if (len < 2) continue; if (isMemcmp) { @@ -420,8 +420,15 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } + if (TmpConstStr.length() < 2 || + (TmpConstStr.length() == 2 && !TmpConstStr[1])) { + + continue; + + } + // add null termination character implicit in c strings - if (TmpConstStr[TmpConstStr.length() - 1] != 0) { + if (!isMemcmp && TmpConstStr[TmpConstStr.length() - 1]) { TmpConstStr.append("\0", 1); -- cgit 1.4.1 From c9854ec8cbd87dc09d7a6ab1b75f3fce2f7bc9ca Mon Sep 17 00:00:00 2001 From: hexcoder Date: Fri, 5 Mar 2021 18:07:16 +0100 Subject: typo --- docs/Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index c5b275de..4e76fedd 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,10 +16,10 @@ sending a mail to . better support for unicode (thanks to @stbergmann for reporting!) - fixed a crash in LAF transform for empty strings - handle erroneous setups in which multiple afl-compiler-rt are - compiled into the target. This now also supports dlopen + compiled into the target. This now also supports dlopen() instrumented libs loaded before the forkserver and even after the forkserver is started (then with collisions though) - - Renamed CTX to CALLER, added correct/real CTX implemenation to CLASSIC + - Renamed CTX to CALLER, added correct/real CTX implementation to CLASSIC - qemu_mode - added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks! - if no new/updated checkout is wanted, build with: -- cgit 1.4.1 From e8d580f54d0ba4cc096f084ed7c52e772b66039c Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 5 Mar 2021 19:45:48 +0100 Subject: rust mutator changes added to changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 4e76fedd..3ca4a20b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,7 @@ sending a mail to . ### Version ++3.11a (dev) - afl-fuzz - add non-unicode variants from unicode-looking dictionary entries + - Rust custom mutator API improvements - afl-cc - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) -- cgit 1.4.1 From e226d1bbb390fb2f81e192d5a8077ec386504807 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 8 Mar 2021 15:16:43 +0100 Subject: update changelog --- docs/Changelog.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 3ca4a20b..ab0e2da2 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,10 +9,10 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.11a (dev) - - afl-fuzz + - afl-fuzz: - add non-unicode variants from unicode-looking dictionary entries - Rust custom mutator API improvements - - afl-cc + - afl-cc: - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) - fixed a crash in LAF transform for empty strings @@ -21,11 +21,12 @@ sending a mail to . instrumented libs loaded before the forkserver and even after the forkserver is started (then with collisions though) - Renamed CTX to CALLER, added correct/real CTX implementation to CLASSIC - - qemu_mode + - qemu_mode: - added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks! - if no new/updated checkout is wanted, build with: NO_CHECKOUT=1 ./build_qemu_support.sh - we no longer perform a "git drop" + - afl-cmin: support filenames with spaces ### Version ++3.10c (release) -- cgit 1.4.1 From 74a6044b3fba496c1255f9aedbf5b7253ae29f0e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Mar 2021 14:11:52 +0100 Subject: fix sanitizer settings --- docs/Changelog.md | 1 + src/afl-forkserver.c | 17 +++++++++-------- src/afl-fuzz-init.c | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index ab0e2da2..b47b03ba 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ sending a mail to . ### Version ++3.11a (dev) - afl-fuzz: + - fix sanitizer settings (bug since 3.10c) - add non-unicode variants from unicode-looking dictionary entries - Rust custom mutator API improvements - afl-cc: diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 6f08f9f4..82ec3069 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -481,11 +481,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* This should improve performance a bit, since it stops the linker from doing extra work post-fork(). */ - if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); } + if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); } /* Set sane defaults for ASAN if nothing else specified. */ - if (fsrv->debug == true && !getenv("ASAN_OPTIONS")) + if (!getenv("ASAN_OPTIONS")) setenv("ASAN_OPTIONS", "abort_on_error=1:" "detect_leaks=0:" @@ -498,11 +498,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_abort=0:" "handle_sigfpe=0:" "handle_sigill=0", - 0); + 1); /* Set sane defaults for UBSAN if nothing else specified. */ - if (fsrv->debug == true && !getenv("UBSAN_OPTIONS")) + if (!getenv("UBSAN_OPTIONS")) setenv("UBSAN_OPTIONS", "halt_on_error=1:" "abort_on_error=1:" @@ -514,7 +514,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_abort=0:" "handle_sigfpe=0:" "handle_sigill=0", - 0); + 1); /* Envs for QASan */ setenv("QASAN_MAX_CALL_STACK", "0", 0); @@ -523,7 +523,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* MSAN is tricky, because it doesn't support abort_on_error=1 at this point. So, we do this in a very hacky way. */ - if (fsrv->debug == true && !getenv("MSAN_OPTIONS")) + if (!getenv("MSAN_OPTIONS")) setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" "symbolize=0:" @@ -536,7 +536,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "handle_abort=0:" "handle_sigfpe=0:" "handle_sigill=0", - 0); + 1); fsrv->init_child_func(fsrv, argv); @@ -931,7 +931,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "%s" - " - Most likely the target has a huge coverage map, retry with setting the\n" + " - Most likely the target has a huge coverage map, retry with " + "setting the\n" " environment variable AFL_MAP_SIZE=4194304\n\n" " - The current memory limit (%s) is too restrictive, causing an " diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 3dbc4c65..2d5f32a7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2457,7 +2457,7 @@ void check_asan_opts(afl_state_t *afl) { } - if (!strstr(x, "symbolize=0")) { + if (!afl->debug && !strstr(x, "symbolize=0")) { FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); -- cgit 1.4.1 From 47f2650a32470172a32c4ebd446003cb8a4b80e8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Mar 2021 16:53:56 +0100 Subject: add AFL_NOOPT --- README.md | 17 +++++++++++++---- docs/env_variables.md | 11 +++++++++++ include/envs.h | 4 +++- src/afl-cc.c | 21 +++++++++++++++++++-- src/afl-common.c | 1 + 5 files changed, 47 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 6b11fee4..d4e39566 100644 --- a/README.md +++ b/README.md @@ -399,10 +399,19 @@ How to do this is described below. Then build the target. (Usually with `make`) -**NOTE**: sometimes configure and build systems are fickle and do not like -stderr output (and think this means a test failure) - which is something -afl++ like to do to show statistics. It is recommended to disable them via -`export AFL_QUIET=1`. +**NOTES** + +1. sometimes configure and build systems are fickle and do not like + stderr output (and think this means a test failure) - which is something + afl++ like to do to show statistics. It is recommended to disable them via + `export AFL_QUIET=1`. + +2. sometimes configure and build systems error on warnings - these should be + disabled (e.g. `--disable-werror` for some configure scripts` + +3. in case the configure/build system complains about afl++'s compiler and + aborts then set `export AFL_NOOPT=1` which will then just behave like the + real compiler. This option has to be unset again before building the target! ##### configure diff --git a/docs/env_variables.md b/docs/env_variables.md index f6ed12d0..a20f1e42 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -26,6 +26,17 @@ Because (with the exception of the --afl-MODE command line option) the compile-time tools do not accept afl specific command-line options, they make fairly broad use of environmental variables instead: + - Some build/configure scripts break with afl++ compilers. To be able to + pass them, do: +``` + export CC=afl-cc + export CXX=afl-c++ + export AFL_NOOPT=1 + ./configure --disable-shared --disabler-werror + unset AFL_NOOPT + make +``` + - Most afl tools do not print any output if stdout/stderr are redirected. If you want to get the output into a file then set the `AFL_DEBUG` environment variable. diff --git a/include/envs.h b/include/envs.h index e8595ef7..37748a56 100644 --- a/include/envs.h +++ b/include/envs.h @@ -119,10 +119,12 @@ static char *afl_environment_variables[] = { "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", - "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_MAX_DET_EXTRAS", + "AFL_NO_X86", // not really an env but we dont want to warn on it + "AFL_NOOPT", + "AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", diff --git a/src/afl-cc.c b/src/afl-cc.c index bb136fb9..8f9bb397 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1025,7 +1025,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { int main(int argc, char **argv, char **envp) { - int i; + int i, passthrough = 0; char *callname = argv[0], *ptr = NULL; if (getenv("AFL_DEBUG")) { @@ -1045,6 +1045,13 @@ int main(int argc, char **argv, char **envp) { } + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + + passthrough = 1; + if (!debug) { be_quiet = 1; } + + } + if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; argvnull = (u8 *)argv[0]; check_environment_vars(envp); @@ -1665,6 +1672,7 @@ int main(int argc, char **argv, char **envp) { " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" " AFL_NO_BUILTIN: no builtins for string compare functions (for " "libtokencap.so)\n" + " AFL_NOOP: behave lik a normal compiler (to pass configure tests)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" @@ -1977,7 +1985,16 @@ int main(int argc, char **argv, char **envp) { } - execvp(cc_params[0], (char **)cc_params); + if (passthrough) { + + argv[0] = cc_params[0]; + execvp(cc_params[0], (char **)argv); + + } else { + + execvp(cc_params[0], (char **)cc_params); + + } FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); diff --git a/src/afl-common.c b/src/afl-common.c index a306fe5e..68f82a5e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -682,6 +682,7 @@ void check_environment_vars(char **envp) { env[strlen(afl_environment_variables[i])] == '=') { match = 1; + if ((val = getenv(afl_environment_variables[i])) && !*val) { WARNF( -- cgit 1.4.1 From 0868ea8348ebc682c370d763324b49536ee4c1f7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Mar 2021 17:15:19 +0100 Subject: fix compiler rt on -c --- docs/Changelog.md | 8 +++++++- src/afl-cc.c | 12 ++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index b47b03ba..c475911d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,9 @@ sending a mail to . - add non-unicode variants from unicode-looking dictionary entries - Rust custom mutator API improvements - afl-cc: + - added AFL_NOOPT that will just pass everything to the normal + gcc/clang compiler without any changes - to pass weird configure + scripts - fixed a crash that can occur with ASAN + CMPLOG together plus better support for unicode (thanks to @stbergmann for reporting!) - fixed a crash in LAF transform for empty strings @@ -21,7 +24,10 @@ sending a mail to . compiled into the target. This now also supports dlopen() instrumented libs loaded before the forkserver and even after the forkserver is started (then with collisions though) - - Renamed CTX to CALLER, added correct/real CTX implementation to CLASSIC + - the compiler rt was added also in object building (-c) which + should have been fixed years ago but somewhere got lost :( + - Renamed CTX to CALLER, added correct/real CTX implementation to + CLASSIC - qemu_mode: - added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks! - if no new/updated checkout is wanted, build with: diff --git a/src/afl-cc.c b/src/afl-cc.c index 8f9bb397..a517124f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -940,7 +940,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (preprocessor_only) { + // prevent unnecessary build errors + cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + + if (preprocessor_only || have_c) { /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. @@ -1001,18 +1004,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !have_c) + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif #if defined(USEMMAP) && !defined(__HAIKU__) - if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; + cc_params[cc_par_cnt++] = "-lrt"; #endif - // prevent unnecessary build errors - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; - } #endif -- cgit 1.4.1 From 6cc59a38be02d812e1f5bbb46b6a94c5a31b460a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 10 Mar 2021 15:37:28 +0100 Subject: gsoc2021 clarification --- docs/ideas.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/ideas.md b/docs/ideas.md index 08cb16ef..0130cf61 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -35,7 +35,9 @@ and documents something about it. In traditional fuzzing this is the coverage in the target, however we want to add various more observers, e.g. stack depth, heap usage, etc. - this is a topic for an experienced Rust developer. -# Generic ideas and wishlist +# Generic ideas and wishlist - NOT PART OF GSoC 2021 ! + +The below list is not part of GSoC 2021. ## Analysis software -- cgit 1.4.1 From f1d8a01047246cd5981cac6ad51850e98c8382c1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 12 Mar 2021 03:55:18 +0100 Subject: added ui change to changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index c475911d..8f3e588c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ sending a mail to . - fix sanitizer settings (bug since 3.10c) - add non-unicode variants from unicode-looking dictionary entries - Rust custom mutator API improvements + - Imported crash stats painted yellow on resume (only new ones are red) - afl-cc: - added AFL_NOOPT that will just pass everything to the normal gcc/clang compiler without any changes - to pass weird configure -- cgit 1.4.1 From d4fb7f8b4015297e1c74b28d671eba058cfb6366 Mon Sep 17 00:00:00 2001 From: realmadsci <71108352+realmadsci@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:53:42 -0500 Subject: Add AFL_QEMU_CUSTOM_BIN environment flag In QEMU mode (-Q), setting AFL_QEMU_CUSTOM_BIN cause afl-fuzz to skip prepending afl-qemu-trace to your command line. Use this if you wish to use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments. --- docs/env_variables.md | 4 ++++ include/envs.h | 1 + src/afl-common.c | 7 +++++++ src/afl-fuzz-init.c | 1 + 4 files changed, 13 insertions(+) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index a20f1e42..c6ad0aa4 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -393,6 +393,10 @@ checks or alter some of the more exotic semantics of the tool: - In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace. + - In QEMU mode (-Q), setting `AFL_QEMU_CUSTOM_BIN` cause afl-fuzz to skip + prepending `afl-qemu-trace` to your command line. Use this if you wish to use a + custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments. + - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule everytime a cycle is finished. diff --git a/include/envs.h b/include/envs.h index 4d4d6b0e..e92bee2a 100644 --- a/include/envs.h +++ b/include/envs.h @@ -130,6 +130,7 @@ static char *afl_environment_variables[] = { "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", "AFL_PYTHON_MODULE", + "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", diff --git a/src/afl-common.c b/src/afl-common.c index 9f6eb564..58fbf765 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -149,6 +149,13 @@ void argv_cpy_free(char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) { + WARNF( + "AFL_QEMU_CUSTOM_BIN is enabled. " + "You must run your target under afl-qemu-trace on your own!"); + return argv; + } + if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } u8 *tmp, *cp = NULL, *rsl, *own_copy; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ca2f75f1..82c1799e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2592,6 +2592,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode || + (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) || afl->non_instrumented_mode) { return; -- cgit 1.4.1 From ac795ae1e154df87d422eb9a307ee1f40fcb701f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 15 Mar 2021 23:08:28 +0100 Subject: v3.11c release --- README.md | 4 ++-- docs/Changelog.md | 4 +++- include/config.h | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 0deaca22..69e5bb74 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ Logo - Release Version: [3.10c](https://github.com/AFLplusplus/AFLplusplus/releases) + Release Version: [3.11c](https://github.com/AFLplusplus/AFLplusplus/releases) - Github Version: 3.11a + Github Version: 3.12a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 8f3e588c..1c735a70 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,9 +8,11 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++3.11a (dev) +### Version ++3.11c (release) - afl-fuzz: + - better auto detection of map size - fix sanitizer settings (bug since 3.10c) + - fix an off-by-one overwrite in cmplog - add non-unicode variants from unicode-looking dictionary entries - Rust custom mutator API improvements - Imported crash stats painted yellow on resume (only new ones are red) diff --git a/include/config.h b/include/config.h index 6ada0fbe..cc8024ea 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.11a" +#define VERSION "++3.11c" /****************************************************** * * -- cgit 1.4.1 From 1dcc3549b6ecc3925825c00ac63274b83e76ec8a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 15 Mar 2021 23:21:03 +0100 Subject: v3.12a init --- docs/Changelog.md | 5 ++++- include/config.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 1c735a70..8222f942 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,6 +8,10 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . +### Version ++3.12a (dev) + - ... + + ### Version ++3.11c (release) - afl-fuzz: - better auto detection of map size @@ -38,7 +42,6 @@ sending a mail to . - we no longer perform a "git drop" - afl-cmin: support filenames with spaces - ### Version ++3.10c (release) - Mac OS ARM64 support - Android support fixed and updated by Joey Jiaojg - thanks! diff --git a/include/config.h b/include/config.h index cc8024ea..b049fee0 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.11c" +#define VERSION "++3.12a" /****************************************************** * * -- cgit 1.4.1 From f5420e737a1ed1dbeb81783836d0449c06aa0fcc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 16 Mar 2021 16:15:29 +0100 Subject: rtn fix --- docs/Changelog.md | 2 +- instrumentation/afl-compiler-rt.o.c | 23 ++++++++++++----------- qemu_mode/qemuafl | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 8222f942..9aea3638 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.12a (dev) - - ... + - fix cmplog rtn (rare crash and not being able to gather ptr data) ### Version ++3.11c (release) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 50b4e2c5..892118fb 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1734,25 +1734,26 @@ static int area_is_valid(void *ptr, size_t len) { long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len); - if (unlikely(r <= 0 || r > len)) { // fail - maybe hitting asan boundary? + if (r <= 0 || r > len) return 0; - char *p = (char *)ptr; - long page_size = sysconf(_SC_PAGE_SIZE); - char *page = (char *)((uintptr_t)p & ~(page_size - 1)) + page_size; - if (page >= p + len) { return 0; } // no isnt, return fail - len = page - p - len; - r = syscall(SYS_write, __afl_dummy_fd[1], page, len); + // even if the write succeed this can be a false positive if we cross + // a page boundary. who knows why. - } + char *p = (char *)ptr; + long page_size = sysconf(_SC_PAGE_SIZE); + char *page = (char *)((uintptr_t)p & ~(page_size - 1)) + page_size; - // partial writes - we return what was written. - if (likely(r >= 0 && r <= len)) { + if (page > p + len) { + // no, not crossing a page boundary return (int)r; } else { - return 0; + // yes it crosses a boundary, hence we can only return the length of + // rest of the first page, we cannot detect if the next page is valid + // or not, neither by SYS_write nor msync() :-( + return (int)(page - p); } diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 0fb212da..d1ca56b8 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 0fb212daab492411b3e323bc18a3074c1aecfd37 +Subproject commit d1ca56b84e78f821406eef28d836918edfc8d610 -- cgit 1.4.1 From 175a275a3db2c9a9f6c9307c56feb58f4cfe365f Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Tue, 16 Mar 2021 17:04:52 +0100 Subject: changelog --- docs/Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 9aea3638..17d68b0a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,7 +10,9 @@ sending a mail to . ### Version ++3.12a (dev) - fix cmplog rtn (rare crash and not being able to gather ptr data) - + - qemu_mode (thanks @realmadsci): + - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace + - add AFL_QEMU_CUSTOM_BIN ### Version ++3.11c (release) - afl-fuzz: -- cgit 1.4.1 From 7c2436c7114e21f029b06346421a73910deac578 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 16 Mar 2021 19:34:34 +0100 Subject: no runtime for shared linking --- docs/Changelog.md | 4 +++- src/afl-cc.c | 59 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 29 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 17d68b0a..bf04c58e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,9 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.12a (dev) - - fix cmplog rtn (rare crash and not being able to gather ptr data) + - afl-cc: + - fix cmplog rtn (rare crash and not being able to gather ptr data) + - link runtime not to shared libs - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN diff --git a/src/afl-cc.c b/src/afl-cc.c index 44654de0..18401d0d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -959,56 +959,59 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (compiler_mode != GCC && compiler_mode != CLANG) { - switch (bit_mode) { + if (!shared_linking) { - case 0: - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + switch (bit_mode) { - case 32: - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); - if (lto_mode) { + case 0: + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-compiler-rt.o", obj_path); + if (lto_mode) + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); + break; + case 32: cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); + alloc_printf("%s/afl-compiler-rt-32.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m32 is not supported by your compiler"); + if (lto_mode) { - } + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m32 is not supported by your compiler"); - break; + } - case 64: - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); - if (lto_mode) { + break; + case 64: cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); + alloc_printf("%s/afl-compiler-rt-64.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m64 is not supported by your compiler"); + if (lto_mode) { - } + cc_params[cc_par_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m64 is not supported by your compiler"); - break; + } - } + break; + + } #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif + } + #if defined(USEMMAP) && !defined(__HAIKU__) cc_params[cc_par_cnt++] = "-lrt"; #endif -- cgit 1.4.1 From 94312796f936ba1830b61432a0f958e192dd212f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 17 Mar 2021 13:16:02 +0100 Subject: better map variability --- docs/Changelog.md | 1 + src/afl-fuzz.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index bf04c58e..8dc218af 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,6 +12,7 @@ sending a mail to . - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs + - ensure shared libraries are properly built and instrumented - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8318a92e..ff4c5281 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1584,12 +1584,14 @@ int main(int argc, char **argv_orig, char **envp) { afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.init_child_func = cmplog_exec_child; - if (map_size <= DEFAULT_SHMEM_SIZE && !afl->non_instrumented_mode && - !afl->fsrv.qemu_mode && !afl->unicorn_mode) { + if ((map_size <= DEFAULT_SHMEM_SIZE || + afl->cmplog_fsrv.map_size < map_size) && + !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && + !afl->unicorn_mode) { - afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value + afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); char vbuf[16]; - snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE); + snprintf(vbuf, sizeof(vbuf), "%u", afl->cmplog_fsrv.map_size); setenv("AFL_MAP_SIZE", vbuf, 1); } -- cgit 1.4.1 From 2102264acf5c271b7560a82771b3af8136af9354 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Mar 2021 16:06:06 +0100 Subject: fix for new llvm 13 change --- docs/Changelog.md | 4 +++ instrumentation/README.lto.md | 2 +- instrumentation/SanitizerCoverageLTO.so.cc | 7 ++++ instrumentation/SanitizerCoveragePCGUARD.so.cc | 8 +++++ instrumentation/afl-compiler-rt.o.c | 1 + instrumentation/afl-llvm-common.cc | 18 +++------- test-instr.c | 2 +- test/test-dlopen.c | 16 +++++---- test/travis/bionic/Dockerfile | 45 ----------------------- test/travis/focal/Dockerfile | 45 ----------------------- test/travis/trusty/Dockerfile | 49 -------------------------- test/travis/xenial/Dockerfile | 46 ------------------------ 12 files changed, 36 insertions(+), 207 deletions(-) delete mode 100644 test/travis/bionic/Dockerfile delete mode 100644 test/travis/focal/Dockerfile delete mode 100644 test/travis/trusty/Dockerfile delete mode 100644 test/travis/xenial/Dockerfile (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 8dc218af..166393cb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,8 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.12a (dev) + - afl-fuzz: + - better map detection, AFL_MAP_SIZE not needed anymore for most cases - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs @@ -16,6 +18,8 @@ sending a mail to . - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN + - unicorn_mode + - accidently removed the subfolder from github, re-added ### Version ++3.11c (release) - afl-fuzz: diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index 81c82c4b..39f6465a 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -113,7 +113,7 @@ cmake \ -DLLVM_LINK_LLVM_DYLIB="ON" \ -DLLVM_TARGETS_TO_BUILD="host" \ ../llvm/ -cmake --build . --parallel +cmake --build . -j4 export PATH="$(pwd)/bin:$PATH" export LLVM_CONFIG="$(pwd)/bin/llvm-config" export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 13a5e5fd..28d905a3 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1291,10 +1291,17 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); +#if LLVM_VERSION_MAJOR > 12 + if (TargetTriple.supportsCOMDAT() && + (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) + if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) + Array->setComdat(Comdat); +#else if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (auto Comdat = GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) Array->setComdat(Comdat); +#endif Array->setSection(getSectionName(Section)); Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); GlobalsToAppendToUsed.push_back(Array); diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 0b6e274a..99ead3d6 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -769,10 +769,18 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); +#if LLVM_VERSION_MAJOR > 12 + if (TargetTriple.supportsCOMDAT() && + (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) + if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) + Array->setComdat(Comdat); +#else if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (auto Comdat = GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) Array->setComdat(Comdat); +#endif + Array->setSection(getSectionName(Section)); #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index bee03ddc..ab1bfb31 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1681,6 +1681,7 @@ void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2) { __cmplog_ins_hook16(arg1, arg2, 0); } + #endif void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index 17780143..74943fb2 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -96,19 +96,11 @@ bool isIgnoreFunction(const llvm::Function *F) { static const char *ignoreSubstringList[] = { - "__asan", - "__msan", - "__ubsan", - "__lsan", - "__san", - "__sanitize", - "__cxx", - "_GLOBAL__", - "DebugCounter", - "DwarfDebug", - "DebugLoc" - - }; + "__asan", "__msan", "__ubsan", "__lsan", + "__san", "__sanitize", "__cxx", "_GLOBAL__", + "DebugCounter", "DwarfDebug", "DebugLoc" + + }; for (auto const &ignoreListFunc : ignoreSubstringList) { diff --git a/test-instr.c b/test-instr.c index 4129a5b4..13d4eb93 100644 --- a/test-instr.c +++ b/test-instr.c @@ -19,7 +19,7 @@ #include #ifdef TEST_SHARED_OBJECT -#define main main_exported + #define main main_exported #endif int main(int argc, char **argv) { diff --git a/test/test-dlopen.c b/test/test-dlopen.c index 3db6adba..d08d9092 100644 --- a/test/test-dlopen.c +++ b/test/test-dlopen.c @@ -5,17 +5,19 @@ int main(int argc, char **argv) { - if (!getenv("TEST_DLOPEN_TARGET")) - return 1; - void* lib = dlopen(getenv("TEST_DLOPEN_TARGET"), RTLD_LAZY); + if (!getenv("TEST_DLOPEN_TARGET")) return 1; + void *lib = dlopen(getenv("TEST_DLOPEN_TARGET"), RTLD_LAZY); if (!lib) { + perror(dlerror()); return 2; + } - int (*func)(int, char**) = dlsym(lib, "main_exported"); - if (!func) - return 3; - + + int (*func)(int, char **) = dlsym(lib, "main_exported"); + if (!func) return 3; + return func(argc, argv); } + diff --git a/test/travis/bionic/Dockerfile b/test/travis/bionic/Dockerfile deleted file mode 100644 index 00ab96f9..00000000 --- a/test/travis/bionic/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# This is the Dockerfile for testing problems in Travis build -# configuration #1. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:bionic -LABEL "about"="travis image 1" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python3.7 python3.7-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-7 gcc-7-plugin-dev libc++-7-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV LLVM_CONFIG=llvm-config-6.0 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] diff --git a/test/travis/focal/Dockerfile b/test/travis/focal/Dockerfile deleted file mode 100644 index 27d994f2..00000000 --- a/test/travis/focal/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# This is the Dockerfile for testing problems in Travis build -# configuration #1. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:focal -LABEL "about"="travis image 4" -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python3 python3-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-9 gcc-9-plugin-dev libc++-9-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] diff --git a/test/travis/trusty/Dockerfile b/test/travis/trusty/Dockerfile deleted file mode 100644 index 0a6f1804..00000000 --- a/test/travis/trusty/Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# This is the Dockerfile for testing problems in Travis builds -# configuration #3. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:trusty -LABEL "about"="travis image 3" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python2.7 python2.7-dev \ - python3-setuptools \ - libtool \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-4.8 gcc-4.8-plugin-dev \ - libc++-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV TERM linux -ENV DEBIAN_FRONTEND noninteractive -ENV LLVM_CONFIG=llvm-config-3.4 -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] - diff --git a/test/travis/xenial/Dockerfile b/test/travis/xenial/Dockerfile deleted file mode 100644 index 6aa4b1d1..00000000 --- a/test/travis/xenial/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# This is the Dockerfile for testing problems in Travis builds -# configuration #2. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:xenial -LABEL "about"="travis image 2" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang-6.0 \ - flex \ - git \ - python3 python3-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-5 gcc-5-plugin-dev \ - libc++-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV LLVM_CONFIG=llvm-config-6.0 -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] -- cgit 1.4.1 From d7e121e2c99c02d4b6984f21ba837d44bce9c77c Mon Sep 17 00:00:00 2001 From: fuzzah Date: Wed, 17 Mar 2021 01:51:40 +0300 Subject: add AFL_TARGET_ENV to afl-fuzz --- README.md | 1 + docs/Changelog.md | 3 ++ docs/env_variables.md | 6 ++++ include/common.h | 4 +++ include/envs.h | 1 + src/afl-common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz.c | 8 +++++ 7 files changed, 119 insertions(+) (limited to 'docs') diff --git a/README.md b/README.md index 69e5bb74..700fe818 100644 --- a/README.md +++ b/README.md @@ -1178,6 +1178,7 @@ without feedback, bug reports, or patches from: Josephine Calliotte Konrad Welc Thomas Rooijakkers David Carlier Ruben ten Hove Joey Jiao + fuzzah ``` Thank you! diff --git a/docs/Changelog.md b/docs/Changelog.md index bf04c58e..fdb1cf5c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,9 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . ### Version ++3.12a (dev) + - afl-fuzz: + - added AFL_TARGET_ENV variable to pass extra env vars to the target + (for things like LD_LIBRARY_PATH) - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs diff --git a/docs/env_variables.md b/docs/env_variables.md index c6ad0aa4..96fd520f 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -408,6 +408,12 @@ checks or alter some of the more exotic semantics of the tool: without disrupting the afl-fuzz process itself. This is useful, among other things, for bootstrapping libdislocator.so. + - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables + for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... ` + This exists mostly for things like `LD_LIBRARY_PATH` but it would theoretically + allow fuzzing of AFL++ itself (with 'target' AFL++ using some AFL_ vars that + would disrupt work of 'fuzzer' AFL++). + - Setting `AFL_NO_UI` inhibits the UI altogether, and just periodically prints some basic stats. This behavior is also automatically triggered when the output from afl-fuzz is redirected to a file or to a pipe. diff --git a/include/common.h b/include/common.h index b7adbaec..06453b8e 100644 --- a/include/common.h +++ b/include/common.h @@ -49,6 +49,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); +/* Extract env vars from input string and set them using setenv() + For use with AFL_TARGET_ENV, ... */ +u8 extract_and_set_env(u8 *env_str); + extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/include/envs.h b/include/envs.h index cfd73b68..fda4ab55 100644 --- a/include/envs.h +++ b/include/envs.h @@ -130,6 +130,7 @@ static char *afl_environment_variables[] = { "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", + "AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV", diff --git a/src/afl-common.c b/src/afl-common.c index 27b63434..72a95fbc 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -706,6 +706,102 @@ char *get_afl_env(char *env) { } +u8 extract_and_set_env(u8 *env_str) { + + if (!env_str) { return 0; } + + u8 *p = ck_strdup(env_str); + + u8 *end = p + strlen((char *)p); + + u8 ret_val = 0; // return false by default + + u8 *rest = p; + u8 *key = p; + u8 *val = p; + + u8 closing_sym = ' '; + u8 c; + + size_t num_pairs = 0; + + while (rest < end) { + + while (*rest == ' ') { + + rest++; + + } + + if (rest + 1 >= end) break; + + key = rest; + // env variable names may not start with numbers or '=' + if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; } + + while (rest < end && *rest != '=' && *rest != ' ') { + + c = *rest; + // lowercase is bad but we may still allow it + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '_') { + + goto free_and_return; + + } + + rest++; + + } + + if (*rest != '=') { goto free_and_return; } + + *rest = '\0'; // done with variable name + + rest += 1; + if (rest >= end || *rest == ' ') { goto free_and_return; } + + val = rest; + if (*val == '\'' || *val == '"') { + + closing_sym = *val; + val += 1; + rest += 1; + if (rest >= end) { goto free_and_return; } + + } else { + + closing_sym = ' '; + + } + + while (rest < end && *rest != closing_sym) { + + rest++; + + } + + if (closing_sym != ' ' && *rest != closing_sym) { goto free_and_return; } + + *rest = '\0'; // done with variable value + + rest += 1; + if (rest < end && *rest != ' ') { goto free_and_return; } + + num_pairs += 1; + + setenv(key, val, 1); + + } + + if (num_pairs > 0) { ret_val = 1; } + +free_and_return: + ck_free(p); + return ret_val; + +} + /* Read mask bitmap from file. This is for the -B option. */ void read_bitmap(u8 *fname, u8 *map, size_t len) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index cfb507a7..9ea1fb34 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -223,6 +223,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n" "AFL_QUIET: suppress forkserver status messages\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" + "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" @@ -1303,6 +1304,13 @@ int main(int argc, char **argv_orig, char **envp) { } + u8 *extra_env = (u8 *)getenv("AFL_TARGET_ENV"); + if (extra_env && !extract_and_set_env(extra_env)) { + + FATAL("Bad value of AFL_TARGET_ENV"); + + } + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); -- cgit 1.4.1 From 72a70423c2667f7ec9cd6b1ce1645fb9a20e81f1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Mar 2021 09:24:36 +0100 Subject: show afl-cc NATIVE when auto used --- docs/Changelog.md | 4 +++- src/afl-cc.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index ab0312f8..643a959c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,11 +12,13 @@ sending a mail to . - afl-fuzz: - added AFL_TARGET_ENV variable to pass extra env vars to the target (for things like LD_LIBRARY_PATH) - - better map detection, AFL_MAP_SIZE not needed anymore for most cases + - fix map detection, AFL_MAP_SIZE not needed anymore for most cases - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs - ensure shared libraries are properly built and instrumented + - show correct LLVM PCGUARD NATIVE mode when auto switching to it + and keep fsanitize-coverage-*list=... - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN diff --git a/src/afl-cc.c b/src/afl-cc.c index 1fe68df5..80fc0742 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -590,6 +590,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #ifdef __ANDROID__ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + instrument_mode != INSTRUMENT_LLVMNATIVE; #else if (have_instr_list) { @@ -599,6 +600,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { "-fsanitize-coverage-allow/denylist, you can use " "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + instrument_mode = INSTRUMENT_LLVMNATIVE; } else { @@ -618,6 +620,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for " "enhanced version.\n"); cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + instrument_mode = INSTRUMENT_LLVMNATIVE; #else FATAL("pcguard instrumentation requires llvm 4.0.1+"); #endif @@ -718,8 +721,13 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) { + if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) || + !strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) && + (strncmp(cur, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + instrument_mode != INSTRUMENT_LLVMNATIVE)) { if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } continue; -- cgit 1.4.1 From 8868648f7623928c77e75e3e8d56770a52966332 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Mar 2021 10:45:39 +0100 Subject: fix LTO selective instrumentation --- docs/Changelog.md | 2 ++ instrumentation/SanitizerCoverageLTO.so.cc | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 643a959c..a65702d8 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -17,8 +17,10 @@ sending a mail to . - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs - ensure shared libraries are properly built and instrumented + - AFL_LLVM_INSTRUMENT_ALLOW/DENY were not implemented for LTO, added - show correct LLVM PCGUARD NATIVE mode when auto switching to it and keep fsanitize-coverage-*list=... + Short mnemnonic NATIVE is now also accepted. - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 28d905a3..6dd390e6 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -507,6 +507,7 @@ bool ModuleSanitizerCoverage::instrumentModule( Zero = ConstantInt::get(Int8Tyi, 0); One = ConstantInt::get(Int8Tyi, 1); + initInstrumentList(); scanForDangerousFunctions(&M); Mo = &M; @@ -1229,7 +1230,7 @@ void ModuleSanitizerCoverage::instrumentFunction( // afl++ START if (!F.size()) return; - if (isIgnoreFunction(&F)) return; + if (!isInInstrumentList(&F)) return; // afl++ END if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) -- cgit 1.4.1 From 0f9dceff3df8fc537bcbfe3a24dc30f9f0fa67a2 Mon Sep 17 00:00:00 2001 From: Joshua Pereyda Date: Mon, 22 Mar 2021 12:06:52 -0700 Subject: add details to AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES doc --- docs/env_variables.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index 96fd520f..7eb973e5 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -425,7 +425,8 @@ checks or alter some of the more exotic semantics of the tool: no valid terminal was detected (for virtual consoles) - If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`. - Others need not apply. + Others need not apply, unless they also want to disable the + /proc/sys/kernel/core_pattern check. - Benchmarking only: `AFL_BENCH_JUST_ONE` causes the fuzzer to exit after processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to -- cgit 1.4.1 From 28f1e94ab9fdac6886c4383d9f4722f26237a05a Mon Sep 17 00:00:00 2001 From: aflpp Date: Tue, 23 Mar 2021 15:33:27 +0100 Subject: fix our PCGUARD for llvm 10.0.1 --- docs/Changelog.md | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 80 ++++++++++++-------------- 2 files changed, 39 insertions(+), 42 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index a65702d8..51c8c1bc 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,6 +15,7 @@ sending a mail to . - fix map detection, AFL_MAP_SIZE not needed anymore for most cases - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) + - fix our own PCGUARD implementation to compile with llvm 10.0.1 - link runtime not to shared libs - ensure shared libraries are properly built and instrumented - AFL_LLVM_INSTRUMENT_ALLOW/DENY were not implemented for LTO, added diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 99ead3d6..09cda9e2 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -135,12 +135,14 @@ class ModuleSanitizerCoverage { public: ModuleSanitizerCoverage( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), - const SpecialCaseList * Allowlist = nullptr, - const SpecialCaseList * Blocklist = nullptr) - : Options(OverrideFromCL(Options)), - Allowlist(Allowlist), - Blocklist(Blocklist) { + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions() +#if LLVM_MAJOR > 10 + , + const SpecialCaseList *Allowlist = nullptr, + const SpecialCaseList *Blocklist = nullptr +#endif + ) + : Options(OverrideFromCL(Options)) { } @@ -210,9 +212,6 @@ class ModuleSanitizerCoverage { SanitizerCoverageOptions Options; - const SpecialCaseList *Allowlist; - const SpecialCaseList *Blocklist; - uint32_t instr = 0; GlobalVariable *AFLMapPtr = NULL; ConstantInt * One = NULL; @@ -224,27 +223,17 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { public: ModuleSanitizerCoverageLegacyPass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions() +#if LLVM_VERSION_MAJOR > 10 + , const std::vector &AllowlistFiles = std::vector(), const std::vector &BlocklistFiles = - std::vector()) + std::vector() +#endif + ) : ModulePass(ID), Options(Options) { - if (AllowlistFiles.size() > 0) - Allowlist = SpecialCaseList::createOrDie(AllowlistFiles -#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , - *vfs::getRealFileSystem() -#endif - ); - if (BlocklistFiles.size() > 0) - Blocklist = SpecialCaseList::createOrDie(BlocklistFiles -#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , - *vfs::getRealFileSystem() -#endif - ); initializeModuleSanitizerCoverageLegacyPassPass( *PassRegistry::getPassRegistry()); @@ -252,8 +241,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { bool runOnModule(Module &M) override { - ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), - Blocklist.get()); + ModuleSanitizerCoverage ModuleSancov(Options +#if LLVM_MAJOR > 10 + , + Allowlist.get(), Blocklist.get() +#endif + ); auto DTCallback = [this](Function &F) -> const DominatorTree * { return &this->getAnalysis(F).getDomTree(); @@ -298,8 +291,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, ModuleAnalysisManager &MAM) { - ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), - Blocklist.get()); + ModuleSanitizerCoverage ModuleSancov(Options +#if LLVM_MAJOR > 10 + , + Allowlist.get(), Blocklist.get() +#endif + ); auto &FAM = MAM.getResult(M).getManager(); auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { @@ -418,12 +415,6 @@ bool ModuleSanitizerCoverage::instrumentModule( } if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; - if (Allowlist && - !Allowlist->inSection("coverage", "src", M.getSourceFileName())) - return false; - if (Blocklist && - Blocklist->inSection("coverage", "src", M.getSourceFileName())) - return false; C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; @@ -696,9 +687,6 @@ void ModuleSanitizerCoverage::instrumentFunction( if (F.hasPersonalityFn() && isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; - if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName())) - return; - if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) return; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); @@ -1216,12 +1204,20 @@ INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", false) ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options, + const SanitizerCoverageOptions &Options +#if LLVM_MAJOR > 10 + , const std::vector &AllowlistFiles, - const std::vector &BlocklistFiles) { + const std::vector &BlocklistFiles +#endif +) { - return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, - BlocklistFiles); + return new ModuleSanitizerCoverageLegacyPass(Options +#if LLVM_MAJOR > 10 + , + AllowlistFiles, BlocklistFiles +#endif + ); } -- cgit 1.4.1 From 5fcd634f05049564dde59df420ac1c2f291a2fb0 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 23 Mar 2021 18:47:07 +0100 Subject: fixed tiny nitpicks --- docs/env_variables.md | 2 +- include/afl-fuzz.h | 2 +- include/common.h | 2 +- src/afl-common.c | 22 +++++++++------------- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 4 ++-- 6 files changed, 21 insertions(+), 18 deletions(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index 7eb973e5..409425f1 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -426,7 +426,7 @@ checks or alter some of the more exotic semantics of the tool: - If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`. Others need not apply, unless they also want to disable the - /proc/sys/kernel/core_pattern check. + `/proc/sys/kernel/core_pattern` check. - Benchmarking only: `AFL_BENCH_JUST_ONE` causes the fuzzer to exit after processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 5003b563..565e9afd 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -390,7 +390,7 @@ typedef struct afl_env_vars { *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, - *afl_testcache_entries, *afl_kill_signal; + *afl_testcache_entries, *afl_kill_signal, *afl_target_env; } afl_env_vars_t; diff --git a/include/common.h b/include/common.h index 05137fb6..7bba9e91 100644 --- a/include/common.h +++ b/include/common.h @@ -51,7 +51,7 @@ char * get_afl_env(char *env); /* Extract env vars from input string and set them using setenv() For use with AFL_TARGET_ENV, ... */ -u8 extract_and_set_env(u8 *env_str); +bool extract_and_set_env(u8 *env_str); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/src/afl-common.c b/src/afl-common.c index 6e485117..cd24c376 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -618,19 +618,15 @@ char *get_afl_env(char *env) { } -u8 extract_and_set_env(u8 *env_str) { +bool extract_and_set_env(u8 *env_str) { - if (!env_str) { return 0; } + if (!env_str) { return false; } - u8 *p = ck_strdup(env_str); + bool ret = false; // return false by default + u8 *p = ck_strdup(env_str); u8 *end = p + strlen((char *)p); - - u8 ret_val = 0; // return false by default - u8 *rest = p; - u8 *key = p; - u8 *val = p; u8 closing_sym = ' '; u8 c; @@ -647,7 +643,7 @@ u8 extract_and_set_env(u8 *env_str) { if (rest + 1 >= end) break; - key = rest; + u8 *key = rest; // env variable names may not start with numbers or '=' if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; } @@ -673,7 +669,7 @@ u8 extract_and_set_env(u8 *env_str) { rest += 1; if (rest >= end || *rest == ' ') { goto free_and_return; } - val = rest; + u8 *val = rest; if (*val == '\'' || *val == '"') { closing_sym = *val; @@ -700,17 +696,17 @@ u8 extract_and_set_env(u8 *env_str) { rest += 1; if (rest < end && *rest != ' ') { goto free_and_return; } - num_pairs += 1; + num_pairs++; setenv(key, val, 1); } - if (num_pairs > 0) { ret_val = 1; } + if (num_pairs) { ret = true; } free_and_return: ck_free(p); - return ret_val; + return ret; } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 3d36e712..0ddf8cf3 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -433,6 +433,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_kill_signal = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_TARGET_ENV", + + afl_environment_variable_len)) { + + afl->afl_env.afl_target_env = + (u8 *)get_afl_env(afl_environment_variables[i]); + } } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b1d01959..d70ffd31 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1304,8 +1304,8 @@ int main(int argc, char **argv_orig, char **envp) { } - u8 *extra_env = (u8 *)getenv("AFL_TARGET_ENV"); - if (extra_env && !extract_and_set_env(extra_env)) { + if (afl->afl_env.afl_target_env && + !extract_and_set_env(afl->afl_env.afl_target_env)) { FATAL("Bad value of AFL_TARGET_ENV"); -- cgit 1.4.1 From dfe6f7f8c949744eeab7a401affde93729a5b39d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 Mar 2021 20:20:59 +0100 Subject: make setting different file permissions easy via config.h --- docs/Changelog.md | 2 ++ include/config.h | 3 +++ instrumentation/afl-compiler-rt.o.c | 10 +++++----- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-common.c | 4 ++-- src/afl-forkserver.c | 4 ++-- src/afl-fuzz-bitmap.c | 8 ++++---- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 12 ++++++------ src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-queue.c | 6 +++--- src/afl-fuzz-run.c | 14 +++++++------- src/afl-sharedmem.c | 8 ++++---- src/afl-showmap.c | 4 ++-- src/afl-tmin.c | 4 ++-- 16 files changed, 46 insertions(+), 41 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 51c8c1bc..aea95d5d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -27,6 +27,8 @@ sending a mail to . - add AFL_QEMU_CUSTOM_BIN - unicorn_mode - accidently removed the subfolder from github, re-added + - added DEFAULT_PERMISSION to config.h for all files created, default + to 0600 ### Version ++3.11c (release) - afl-fuzz: diff --git a/include/config.h b/include/config.h index 29225f6b..3c09fce4 100644 --- a/include/config.h +++ b/include/config.h @@ -43,6 +43,9 @@ Default: 8MB (defined in bytes) */ #define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024) +/* Default file permission umode when creating files (default: 0600) */ +#define DEFAULT_PERMISSION 0600 + /* CMPLOG/REDQUEEN TUNING * * Here you can modify tuning and solving options for CMPLOG. diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index ab1bfb31..f241447a 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -204,7 +204,7 @@ static void __afl_map_shm_fuzz() { int shm_fd = -1; /* create the shared memory segment as if it was a file */ - shm_fd = shm_open(shm_file_path, O_RDWR, 0600); + shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); if (shm_fd == -1) { fprintf(stderr, "shm_open() failed for fuzz\n"); @@ -353,7 +353,7 @@ static void __afl_map_shm(void) { unsigned char *shm_base = NULL; /* create the shared memory segment as if it was a file */ - shm_fd = shm_open(shm_file_path, O_RDWR, 0600); + shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); if (shm_fd == -1) { fprintf(stderr, "shm_open() failed\n"); @@ -528,7 +528,7 @@ static void __afl_map_shm(void) { struct cmp_map *shm_base = NULL; /* create the shared memory segment as if it was a file */ - shm_fd = shm_open(shm_file_path, O_RDWR, 0600); + shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); if (shm_fd == -1) { perror("shm_open() failed\n"); @@ -729,7 +729,7 @@ static void __afl_start_snapshots(void) { static uint32_t counter = 0; char fn[32]; sprintf(fn, "%09u:forkserver", counter); - s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd_doc >= 0) { if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { @@ -960,7 +960,7 @@ static void __afl_start_forkserver(void) { static uint32_t counter = 0; char fn[32]; sprintf(fn, "%09u:forkserver", counter); - s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd_doc >= 0) { if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 86b0f7e9..e106cd31 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -212,7 +212,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { unlink(path); /* Ignore errors */ - ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); + ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (ret < 0) { PFATAL("Unable to create '%s'", path); } diff --git a/src/afl-as.c b/src/afl-as.c index 7de267a3..aebd0ac8 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -280,7 +280,7 @@ static void add_instrumentation(void) { } - outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); + outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, DEFAULT_PERMISSION); if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); } diff --git a/src/afl-common.c b/src/afl-common.c index cd24c376..37b4788c 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1104,7 +1104,7 @@ FILE *create_ffile(u8 *fn) { s32 fd; FILE *f; - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } @@ -1122,7 +1122,7 @@ s32 create_file(u8 *fn) { s32 fd; - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 68995388..b9cb48cb 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1038,12 +1038,12 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { if (unlikely(fsrv->no_unlink)) { - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); } else { unlink(fsrv->out_file); /* Ignore errors. */ - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 4ed59364..3d0228db 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -42,7 +42,7 @@ void write_bitmap(afl_state_t *afl) { afl->bitmap_changed = 0; snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); - fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to open '%s'", fname); } @@ -407,7 +407,7 @@ static void write_crash_readme(afl_state_t *afl) { sprintf(fn, "%s/crashes/README.txt", afl->out_dir); - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); /* Do not die on errors here - that would be impolite. */ @@ -509,7 +509,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); #endif /* ^!SIMPLE_FILES */ - fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); } ck_write(fd, mem, len, queue_fn); close(fd); @@ -783,7 +783,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* If we're here, we apparently want to save the crash or hang test case, too. */ - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); } ck_write(fd, mem, len, fn); close(fd); diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 52100fa1..6091db15 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -731,7 +731,7 @@ void save_auto(afl_state_t *afl) { alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i); s32 fd; - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index b2569dc0..47521a9e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -152,7 +152,7 @@ void bind_to_free_cpu(afl_state_t *afl) { do { - if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) { + if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION)) < 0) { if (first) { @@ -1219,7 +1219,7 @@ static void link_or_copy(u8 *old_path, u8 *new_path) { sfd = open(old_path, O_RDONLY); if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); } - dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); + dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); } tmp = ck_alloc(64 * 1024); @@ -2015,7 +2015,7 @@ void setup_dirs_fds(afl_state_t *afl) { if (!afl->in_place_resume) { - int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); + int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); @@ -2030,7 +2030,7 @@ void setup_dirs_fds(afl_state_t *afl) { } else { - int fd = open(tmp, O_WRONLY | O_CREAT, 0600); + int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); @@ -2057,7 +2057,7 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) { /* Store the command line to reproduce our findings */ tmp = alloc_printf("%s/cmdline", afl->out_dir); - fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); @@ -2092,7 +2092,7 @@ void setup_stdio_file(afl_state_t *afl) { unlink(afl->fsrv.out_file); /* Ignore errors */ - afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, 0600); + afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (afl->fsrv.out_fd < 0) { diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 80df6d08..a47b4f5f 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -465,7 +465,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, unlink(q->fname); /* ignore errors */ - fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index b2f88205..63592cef 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -249,7 +249,7 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, strrchr(q->fname, '/') + 1); - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); @@ -272,7 +272,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { if (symlink(ldest, fn)) { - s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); @@ -300,7 +300,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 0b84a542..30860eff 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -83,7 +83,7 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { afl->document_counter++, describe_op(afl, 0, NAME_MAX - strlen("000000000:"))); - if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { + if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION)) >= 0) { if (write(doc_fd, mem, len) != len) PFATAL("write to mutation file failed: %s", fn); @@ -247,12 +247,12 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, if (unlikely(afl->no_unlink)) { - fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); } else { unlink(afl->fsrv.out_file); /* Ignore errors. */ - fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); } @@ -564,7 +564,7 @@ void sync_fuzzers(afl_state_t *afl) { /* document the attempt to sync to this instance */ sprintf(qd_synced_path, "%s/.synced/%s.last", afl->out_dir, sd_ent->d_name); - id_fd = open(qd_synced_path, O_RDWR | O_CREAT | O_TRUNC, 0600); + id_fd = open(qd_synced_path, O_RDWR | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (id_fd >= 0) close(id_fd); /* Skip anything that doesn't have a queue/ subdirectory. */ @@ -587,7 +587,7 @@ void sync_fuzzers(afl_state_t *afl) { sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name); - id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); + id_fd = open(qd_synced_path, O_RDWR | O_CREAT, DEFAULT_PERMISSION); if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); } @@ -851,7 +851,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (unlikely(afl->no_unlink)) { - fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } @@ -866,7 +866,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } else { unlink(q->fname); /* ignore errors */ - fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 3241a130..ac662977 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -163,7 +163,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, /* create the shared memory segment as if it was a file */ shm->g_shm_fd = - shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600); + shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, DEFAULT_PERMISSION); if (shm->g_shm_fd == -1) { PFATAL("shm_open() failed"); } /* configure the size of the shared memory segment */ @@ -202,7 +202,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, /* create the shared memory segment as if it was a file */ shm->cmplog_g_shm_fd = - shm_open(shm->cmplog_g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600); + shm_open(shm->cmplog_g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, DEFAULT_PERMISSION); if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); } /* configure the size of the shared memory segment */ @@ -241,13 +241,13 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, #else u8 *shm_str; - shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600); + shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION); if (shm->shm_id < 0) { PFATAL("shmget() failed"); } if (shm->cmplog_mode) { shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map), - IPC_CREAT | IPC_EXCL | 0600); + IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION); if (shm->cmplog_shm_id < 0) { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 7bf5a9c7..cc0f1a7e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -252,7 +252,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { } else { unlink(outfile); /* Ignore errors */ - fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600); + fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", outfile); } } @@ -1119,7 +1119,7 @@ int main(int argc, char **argv_orig, char **envp) { unlink(stdin_file); atexit(at_exit_handler); fsrv->out_file = stdin_file; - fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); + fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } if (arg_offset && use_argv[arg_offset] != stdin_file) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 7ef8b9bf..fc974262 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -244,7 +244,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { unlink(path); /* Ignore errors */ - ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); + ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (ret < 0) { PFATAL("Unable to create '%s'", path); } @@ -666,7 +666,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { unlink(out_file); fsrv->out_file = out_file; - fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600); + fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } -- cgit 1.4.1 From 2fef89950f826be065cc9677df690ebfd21160c1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 Mar 2021 22:49:02 +0100 Subject: v3.12c release --- docs/Changelog.md | 2 +- include/config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index aea95d5d..476c6f4e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,7 +8,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++3.12a (dev) +### Version ++3.12c (release) - afl-fuzz: - added AFL_TARGET_ENV variable to pass extra env vars to the target (for things like LD_LIBRARY_PATH) diff --git a/include/config.h b/include/config.h index 3c09fce4..c93a6d51 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.12a" +#define VERSION "++3.12c" /****************************************************** * * -- cgit 1.4.1 From 2b3642aa39fc79b5fd394120f0fadf4476d4476e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Mar 2021 11:13:16 +0100 Subject: v3.12c ready to go --- docs/Changelog.md | 1 + qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 476c6f4e..5b7d6ab6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ sending a mail to . - added AFL_TARGET_ENV variable to pass extra env vars to the target (for things like LD_LIBRARY_PATH) - fix map detection, AFL_MAP_SIZE not needed anymore for most cases + - fix counting favorites (just a display thing) - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - fix our own PCGUARD implementation to compile with llvm 10.0.1 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index ddc4a974..0fb212da 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit ddc4a9748d59857753fb33c30a356f354595f36d +Subproject commit 0fb212daab492411b3e323bc18a3074c1aecfd37 -- cgit 1.4.1 From ee5078f43c44a022831cf83b6963930975188168 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Mar 2021 11:22:37 +0100 Subject: v3.13a init --- docs/Changelog.md | 3 +++ include/config.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 5b7d6ab6..6b7ebf15 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,6 +8,9 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . +### Version ++3.13a (development) + - ... + ### Version ++3.12c (release) - afl-fuzz: - added AFL_TARGET_ENV variable to pass extra env vars to the target diff --git a/include/config.h b/include/config.h index c93a6d51..8ac74c45 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.12c" +#define VERSION "++3.13a" /****************************************************** * * -- cgit 1.4.1