aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc3
-rwxr-xr-xemscripten.py4
-rw-r--r--src/analyzer.js3
-rw-r--r--src/compiler.js1
-rw-r--r--src/intertyper.js2
-rw-r--r--src/jsifier.js20
-rw-r--r--src/library.js12
-rw-r--r--src/library_gl.js2
-rw-r--r--src/modules.js11
-rw-r--r--src/parseTools.js11
-rw-r--r--src/preamble.js22
-rw-r--r--system/lib/dlmalloc.c9123
-rw-r--r--tests/cases/atomicrmw.ll1
-rw-r--r--tests/cases/breakinthemiddle2.ll35
-rw-r--r--tests/cases/callalias.ll21
-rw-r--r--tests/cases/callalias2.ll22
-rw-r--r--tests/cases/cmpxchg_volatile.ll548
-rw-r--r--tests/cases/inttoptrfloat.ll19
-rw-r--r--tests/dlmalloc_test.c4
-rw-r--r--tests/fuzz/2.c2006
-rw-r--r--tests/fuzz/2.c.txt1
-rw-r--r--tests/fuzz/3.c1043
-rw-r--r--tests/fuzz/3.c.txt1
-rw-r--r--tests/fuzz/4.c216
-rw-r--r--tests/fuzz/4.c.txt1
-rw-r--r--tests/fuzz/5.c13
-rw-r--r--tests/fuzz/5.c.txt101
-rw-r--r--tests/fuzz/7.c852
-rw-r--r--tests/fuzz/7.c.txt1
-rwxr-xr-xtests/fuzz/csmith_driver.py35
-rwxr-xr-xtests/runner.py35
-rw-r--r--tools/autodebugger_c.py10
-rw-r--r--tools/shared.py3
33 files changed, 9869 insertions, 4313 deletions
diff --git a/emcc b/emcc
index 30074540..b3581ea8 100755
--- a/emcc
+++ b/emcc
@@ -1268,9 +1268,6 @@ try:
execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)])
if DEBUG: save_intermediate('transformed')
- if shared.Settings.ASM_JS: # XXX temporary wrapping for testing purposes
- print >> sys.stderr, 'emcc: ASM_JS mode is highly experimental, and will not work on most codebases yet. It is NOT recommended that you try this yet.'
-
# It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing
js_optimizer_queue = []
def flush_js_optimizer_queue():
diff --git a/emscripten.py b/emscripten.py
index 1db09a80..1fc5f190 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -242,6 +242,8 @@ def emscript(infile, settings, outfile, libraries=[]):
if jcache: outputs += cached_outputs # TODO: preserve order
outputs = [output.split('//FORWARDED_DATA:') for output in outputs]
+ for output in outputs:
+ assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0]
if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
if DEBUG: t = time.time()
@@ -310,7 +312,7 @@ def emscript(infile, settings, outfile, libraries=[]):
post_file = temp_files.get('.post.ll').name
open(post_file, 'w').write('\n') # no input, just processing of forwarded data
out = shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src'))
- post, last_forwarded_data = out.split('//FORWARDED_DATA:')
+ post, last_forwarded_data = out.split('//FORWARDED_DATA:') # if this fails, perhaps the process failed prior to printing forwarded data?
last_forwarded_json = json.loads(last_forwarded_data)
if settings.get('ASM_JS'):
diff --git a/src/analyzer.js b/src/analyzer.js
index c930231f..f9b0c5af 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -18,6 +18,7 @@ function recomputeLines(func) {
// Handy sets
var BRANCH_INVOKE = set('branch', 'invoke');
+var LABEL_ENDERS = set('branch', 'return');
var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic');
var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam');
@@ -88,7 +89,7 @@ function analyzer(data, sidePass) {
// Internal line
if (!currLabelFinished) {
item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); // If this line fails, perhaps missing a label?
- if (subItem.intertype === 'branch') {
+ if (subItem.intertype in LABEL_ENDERS) {
currLabelFinished = true;
}
} else {
diff --git a/src/compiler.js b/src/compiler.js
index 14816f1e..b40891a5 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -172,6 +172,7 @@ assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS ==
if (ASM_JS) {
assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap');
assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2');
+ assert(DISABLE_EXCEPTION_CATCHING == 1, 'asm.js does not support C++ exceptions yet');
}
assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals
diff --git a/src/intertyper.js b/src/intertyper.js
index c1a98354..6c88e765 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -741,10 +741,12 @@ function intertyper(data, sidePass, baseLineNums) {
processItem: function(item) {
item.intertype = 'atomic';
if (item.tokens[0].text == 'atomicrmw') {
+ if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
item.op = item.tokens[1].text;
item.tokens.splice(1, 1);
} else {
assert(item.tokens[0].text == 'cmpxchg')
+ if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
item.op = 'cmpxchg';
}
var last = getTokenIndexByText(item.tokens, ';');
diff --git a/src/jsifier.js b/src/jsifier.js
index bd0e5e75..ca404258 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -375,6 +375,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var ret = [item];
item.JS = 'var ' + item.ident + ';';
// Set the actual value in a postset, since it may be a global variable. We also order by dependencies there
+ Variables.globals[item.ident].targetIdent = item.value.ident;
var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value);
var fix = '';
if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
@@ -913,7 +914,11 @@ function JSify(data, functionsOnly, givenFunctions) {
case VAR_NATIVIZED:
if (isNumber(item.ident)) {
// Direct write to a memory address; this may be an intentional segfault, if not, it is a bug in the source
- return 'throw "fault on write to ' + item.ident + '";';
+ if (ASM_JS) {
+ return 'abort(' + item.ident + ')';
+ } else {
+ return 'throw "fault on write to ' + item.ident + '";';
+ }
}
return item.ident + '=' + value + ';'; // We have the actual value here
break;
@@ -1199,6 +1204,9 @@ function JSify(data, functionsOnly, givenFunctions) {
switch (item.op) {
case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type, null, null, null, null, ',') + ',tempValue)';
case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'or': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue|' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'and': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue&' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'xor': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue^' + param2, type, null, null, null, null, ',') + ',tempValue)';
case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type, null, null, null, null, ',') + ',tempValue)';
case 'cmpxchg': {
var param3 = finalizeLLVMParameter(item.params[2]);
@@ -1221,6 +1229,15 @@ function JSify(data, functionsOnly, givenFunctions) {
var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED;
switch (impl) {
case VAR_NATIVIZED: {
+ if (isNumber(item.ident)) {
+ item.assignTo = null;
+ // Direct read from a memory address; this may be an intentional segfault, if not, it is a bug in the source
+ if (ASM_JS) {
+ return 'abort(' + item.ident + ')';
+ } else {
+ return 'throw "fault on read from ' + item.ident + '";';
+ }
+ }
return value; // We have the actual value here
}
case VAR_EMULATED: return makeGetValue(value, 0, item.type, 0, item.unsigned, 0, item.align);
@@ -1284,6 +1301,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
+ ident = Variables.resolveAliasToIdent(ident);
var shortident = ident.slice(1);
var callIdent = LibraryManager.getRootIdent(shortident);
if (callIdent) {
diff --git a/src/library.js b/src/library.js
index 4d7b397e..1676a82c 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3363,14 +3363,15 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.ECHILD);
return -1;
},
- perror__deps: ['puts', 'putc', 'strerror', '__errno_location'],
+ perror__deps: ['puts', 'fputs', 'fputc', 'strerror', '__errno_location'],
perror: function(s) {
// void perror(const char *s);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/perror.html
+ var stdout = {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}};
if (s) {
- _puts(s);
- _putc(':'.charCodeAt(0));
- _putc(' '.charCodeAt(0));
+ _fputs(s, stdout);
+ _fputc(':'.charCodeAt(0), stdout);
+ _fputc(' '.charCodeAt(0), stdout);
}
var errnum = {{{ makeGetValue('___errno_location()', '0', 'i32') }}};
_puts(_strerror(errnum));
@@ -4313,8 +4314,9 @@ LibraryManager.library = {
ptr = ptr|0; value = value|0; num = num|0;
var stop = 0, value4 = 0, stop4 = 0, unaligned = 0;
stop = (ptr + num)|0;
- if (num|0 >= {{{ SEEK_OPTIMAL_ALIGN_MIN }}}) {
+ if ((num|0) >= {{{ SEEK_OPTIMAL_ALIGN_MIN }}}) {
// This is unaligned, but quite large, so work hard to get to aligned settings
+ value = value & 0xff;
unaligned = ptr & 3;
value4 = value | (value << 8) | (value << 16) | (value << 24);
stop4 = stop & ~3;
diff --git a/src/library_gl.js b/src/library_gl.js
index b0bf9650..4977d2e9 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1634,7 +1634,7 @@ var LibraryGL = {
// GL Immediate mode
$GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });',
- $GLImmediate__deps: ['$Browser', '$GL'],
+ $GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'],
$GLImmediate: {
MAX_TEXTURES: 7,
diff --git a/src/modules.js b/src/modules.js
index 712d8a78..afdbc21e 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -179,7 +179,16 @@ var Variables = {
globals: {},
indexedGlobals: {}, // for indexed globals, ident ==> index
// Used in calculation of indexed globals
- nextIndexedOffset: 0
+ nextIndexedOffset: 0,
+
+ resolveAliasToIdent: function(ident) {
+ while (1) {
+ var varData = Variables.globals[ident];
+ if (!(varData && varData.targetIdent)) break;
+ ident = varData.targetIdent; // might need to eval to turn (6) into 6
+ }
+ return ident;
+ },
};
var Types = {
diff --git a/src/parseTools.js b/src/parseTools.js
index 78c9e31c..5d3c0179 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -692,7 +692,7 @@ function makeCopyI64(value) {
function parseArbitraryInt(str, bits) {
// We parse the string into a vector of digits, base 10. This is convenient to work on.
- assert(bits % 32 == 0 || ('i' + (bits % 32)) in Runtime.INT_TYPES, 'Arbitrary-sized ints must tails that are of legal size');
+ assert(bits > 0); // NB: we don't check that the value in str can fit in this amount of bits
function str2vec(s) { // index 0 is the highest value
var ret = [];
@@ -1371,6 +1371,8 @@ var TWO_TWENTY = Math.pow(2, 20);
function getFastValue(a, op, b, type) {
a = a.toString();
b = b.toString();
+ a = a == 'true' ? '1' : (a == 'false' ? '0' : a);
+ b = b == 'true' ? '1' : (b == 'false' ? '0' : b);
if (isNumber(a) && isNumber(b)) {
if (op == 'pow') {
return Math.pow(a, b).toString();
@@ -1838,9 +1840,10 @@ function makeSignOp(value, type, op, force, ignore) {
if (!CHECK_SIGNS || ignore) {
if (bits === 32) {
if (op === 're') {
- return '((' + value + ')|0)';
+ return '(' + getFastValue(value, '|', '0') + ')';
} else {
- return '((' + value + ')>>>0)';
+
+ return '(' + getFastValue(value, '>>>', '0') + ')';
// Alternatively, we can consider the lengthier
// return makeInlineCalculation('VALUE >= 0 ? VALUE : ' + Math.pow(2, bits) + ' + VALUE', value, 'tempBigInt');
// which does not always turn us into a 32-bit *un*signed value
@@ -1849,7 +1852,7 @@ function makeSignOp(value, type, op, force, ignore) {
if (op === 're') {
return makeInlineCalculation('(VALUE << ' + (32-bits) + ') >> ' + (32-bits), value, 'tempInt');
} else {
- return '((' + value + ')&' + (Math.pow(2, bits)-1) + ')';
+ return '(' + getFastValue(value, '&', Math.pow(2, bits)-1) + ')';
}
} else { // bits > 32
if (op === 're') {
diff --git a/src/preamble.js b/src/preamble.js
index 0bfeda1b..9bc68d8f 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -412,14 +412,6 @@ Module['ALLOC_STACK'] = ALLOC_STACK;
Module['ALLOC_STATIC'] = ALLOC_STATIC;
Module['ALLOC_NONE'] = ALLOC_NONE;
-// Simple unoptimized memset - necessary during startup
-var _memset = function(ptr, value, num) {
- var stop = ptr + num;
- while (ptr < stop) {
- {{{ makeSetValue('ptr++', 0, 'value', 'i8', null, true) }}};
- }
-}
-
// allocate(): This is for internal use. You can use it yourself as well, but the interface
// is a little tricky (see docs right below). The reason is that it is optimized
// for multiple syntaxes to save space in generated code. So you should
@@ -453,7 +445,18 @@ function allocate(slab, types, allocator, ptr) {
}
if (zeroinit) {
- _memset(ret, 0, size);
+ var ptr = ret, stop;
+#if USE_TYPED_ARRAYS == 2
+ assert((ret & 3) == 0);
+ stop = ret + (size & ~3);
+ for (; ptr < stop; ptr += 4) {
+ {{{ makeSetValue('ptr', '0', '0', 'i32', null, true) }}};
+ }
+#endif
+ stop = ret + size;
+ while (ptr < stop) {
+ {{{ makeSetValue('ptr++', '0', '0', 'i8', null, true) }}};
+ }
return ret;
}
@@ -566,6 +569,7 @@ function enlargeMemory() {
while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY);
}
+ assert(TOTAL_MEMORY <= Math.pow(2, 30)); // 2^30==1GB is a practical maximum - 2^31 is already close to possible negative numbers etc.
#if USE_TYPED_ARRAYS == 1
var oldIHEAP = IHEAP;
Module['HEAP'] = Module['IHEAP'] = HEAP = IHEAP = new Int32Array(TOTAL_MEMORY);
diff --git a/system/lib/dlmalloc.c b/system/lib/dlmalloc.c
index 9ee3709e..7e04a726 100644
--- a/system/lib/dlmalloc.c
+++ b/system/lib/dlmalloc.c
@@ -5,492 +5,537 @@
/*
- This is a version (aka dlmalloc) of malloc/free/realloc written by
- Doug Lea and released to the public domain, as explained at
- http://creativecommons.org/licenses/publicdomain. Send questions,
- comments, complaints, performance data, etc to dl@cs.oswego.edu
-
-* Version 2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
-* Quickstart
-
- This library is all in one file to simplify the most common usage:
- ftp it, compile it (-O3), and link it into another program. All of
- the compile-time options default to reasonable values for use on
- most platforms. You might later want to step through various
- compile-time and dynamic tuning options.
-
- For convenience, an include file for code using this malloc is at:
- ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h
- You don't really need this .h file unless you call functions not
- defined in your system include files. The .h file contains only the
- excerpts from this file needed for using this malloc on ANSI C/C++
- systems, so long as you haven't changed compile-time options about
- naming and tuning parameters. If you do, then you can create your
- own malloc.h that does include all settings by cutting at the point
- indicated below. Note that you may already by default be using a C
- library containing a malloc that is based on some version of this
- malloc (for example in linux). You might still want to use the one
- in this file to customize settings or to avoid overheads associated
- with library versions.
-
-* Vital statistics:
-
- Supported pointer/size_t representation: 4 or 8 bytes
- size_t MUST be an unsigned type of the same width as
- pointers. (If you are using an ancient system that declares
- size_t as a signed type, or need it to be a different width
- than pointers, you can use a previous release of this malloc
- (e.g. 2.7.2) supporting these.)
-
- Alignment: 8 bytes (default)
- This suffices for nearly all current machines and C compilers.
- However, you can define MALLOC_ALIGNMENT to be wider than this
- if necessary (up to 128bytes), at the expense of using more space.
-
- Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
- 8 or 16 bytes (if 8byte sizes)
- Each malloced chunk has a hidden word of overhead holding size
- and status information, and additional cross-check word
- if FOOTERS is defined.
-
- Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
- 8-byte ptrs: 32 bytes (including overhead)
-
- Even a request for zero bytes (i.e., malloc(0)) returns a
- pointer to something of the minimum allocatable size.
- The maximum overhead wastage (i.e., number of extra bytes
- allocated than were requested in malloc) is less than or equal
- to the minimum size, except for requests >= mmap_threshold that
- are serviced via mmap(), where the worst case wastage is about
- 32 bytes plus the remainder from a system page (the minimal
- mmap unit); typically 4096 or 8192 bytes.
-
- Security: static-safe; optionally more or less
- The "security" of malloc refers to the ability of malicious
- code to accentuate the effects of errors (for example, freeing
- space that is not currently malloc'ed or overwriting past the
- ends of chunks) in code that calls malloc. This malloc
- guarantees not to modify any memory locations below the base of
- heap, i.e., static variables, even in the presence of usage
- errors. The routines additionally detect most improper frees
- and reallocs. All this holds as long as the static bookkeeping
- for malloc itself is not corrupted by some other means. This
- is only one aspect of security -- these checks do not, and
- cannot, detect all possible programming errors.
-
- If FOOTERS is defined nonzero, then each allocated chunk
- carries an additional check word to verify that it was malloced
- from its space. These check words are the same within each
- execution of a program using malloc, but differ across
- executions, so externally crafted fake chunks cannot be
- freed. This improves security by rejecting frees/reallocs that
- could corrupt heap memory, in addition to the checks preventing
- writes to statics that are always on. This may further improve
- security at the expense of time and space overhead. (Note that
- FOOTERS may also be worth using with MSPACES.)
-
- By default detected errors cause the program to abort (calling
- "abort()"). You can override this to instead proceed past
- errors by defining PROCEED_ON_ERROR. In this case, a bad free
- has no effect, and a malloc that encounters a bad address
- caused by user overwrites will ignore the bad address by
- dropping pointers and indices to all known memory. This may
- be appropriate for programs that should continue if at all
- possible in the face of programming errors, although they may
- run out of memory because dropped memory is never reclaimed.
-
- If you don't like either of these options, you can define
- CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
- else. And if if you are sure that your program using malloc has
- no errors or vulnerabilities, you can define INSECURE to 1,
- which might (or might not) provide a small performance improvement.
-
- Thread-safety: NOT thread-safe unless USE_LOCKS defined
- When USE_LOCKS is defined, each public call to malloc, free,
- etc is surrounded with either a pthread mutex or a win32
- spinlock (depending on WIN32). This is not especially fast, and
- can be a major bottleneck. It is designed only to provide
- minimal protection in concurrent environments, and to provide a
- basis for extensions. If you are using malloc in a concurrent
- program, consider instead using nedmalloc
- (http://www.nedprod.com/programs/portable/nedmalloc/) or
- ptmalloc (See http://www.malloc.de), which are derived
- from versions of this malloc.
-
- System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
- This malloc can use unix sbrk or any emulation (invoked using
- the CALL_MORECORE macro) and/or mmap/munmap or any emulation
- (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
- memory. On most unix systems, it tends to work best if both
- MORECORE and MMAP are enabled. On Win32, it uses emulations
- based on VirtualAlloc. It also uses common C library functions
- like memset.
-
- Compliance: I believe it is compliant with the Single Unix Specification
- (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
- others as well.
-
-* Overview of algorithms
-
- This is not the fastest, most space-conserving, most portable, or
- most tunable malloc ever written. However it is among the fastest
- while also being among the most space-conserving, portable and
- tunable. Consistent balance across these factors results in a good
- general-purpose allocator for malloc-intensive programs.
-
- In most ways, this malloc is a best-fit allocator. Generally, it
- chooses the best-fitting existing chunk for a request, with ties
- broken in approximately least-recently-used order. (This strategy
- normally maintains low fragmentation.) However, for requests less
- than 256bytes, it deviates from best-fit when there is not an
- exactly fitting available chunk by preferring to use space adjacent
- to that used for the previous small request, as well as by breaking
- ties in approximately most-recently-used order. (These enhance
- locality of series of small allocations.) And for very large requests
- (>= 256Kb by default), it relies on system memory mapping
- facilities, if supported. (This helps avoid carrying around and
- possibly fragmenting memory used only for large chunks.)
-
- All operations (except malloc_stats and mallinfo) have execution
- times that are bounded by a constant factor of the number of bits in
- a size_t, not counting any clearing in calloc or copying in realloc,
- or actions surrounding MORECORE and MMAP that have times
- proportional to the number of non-contiguous regions returned by
- system allocation routines, which is often just 1. In real-time
- applications, you can optionally suppress segment traversals using
- NO_SEGMENT_TRAVERSAL, which assures bounded execution even when
- system allocators return non-contiguous spaces, at the typical
- expense of carrying around more memory and increased fragmentation.
-
- The implementation is not very modular and seriously overuses
- macros. Perhaps someday all C compilers will do as good a job
- inlining modular code as can now be done by brute-force expansion,
- but now, enough of them seem not to.
-
- Some compilers issue a lot of warnings about code that is
- dead/unreachable only on some platforms, and also about intentional
- uses of negation on unsigned types. All known cases of each can be
- ignored.
-
- For a longer but out of date high-level description, see
- http://gee.cs.oswego.edu/dl/html/malloc.html
-
-* MSPACES
- If MSPACES is defined, then in addition to malloc, free, etc.,
- this file also defines mspace_malloc, mspace_free, etc. These
- are versions of malloc routines that take an "mspace" argument
- obtained using create_mspace, to control all internal bookkeeping.
- If ONLY_MSPACES is defined, only these versions are compiled.
- So if you would like to use this allocator for only some allocations,
- and your system malloc for others, you can compile with
- ONLY_MSPACES and then do something like...
- static mspace mymspace = create_mspace(0,0); // for example
- #define mymalloc(bytes) mspace_malloc(mymspace, bytes)
-
- (Note: If you only need one instance of an mspace, you can instead
- use "USE_DL_PREFIX" to relabel the global malloc.)
-
- You can similarly create thread-local allocators by storing
- 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.
- You cannot allocate from one and free to another (although
- conformance is only weakly checked, so usage errors are not always
- caught). If FOOTERS is defined, then each chunk carries around a tag
- indicating its originating mspace, and frees are directed to their
- originating spaces.
-
+ This is a version (aka dlmalloc) of malloc/free/realloc written by
+ Doug Lea and released to the public domain, as explained at
+ http://creativecommons.org/publicdomain/zero/1.0/ Send questions,
+ comments, complaints, performance data, etc to dl@cs.oswego.edu
+
+ * Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea
+ Note: There may be an updated version of this malloc obtainable at
+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ * Quickstart
+
+ This library is all in one file to simplify the most common usage:
+ ftp it, compile it (-O3), and link it into another program. All of
+ the compile-time options default to reasonable values for use on
+ most platforms. You might later want to step through various
+ compile-time and dynamic tuning options.
+
+ For convenience, an include file for code using this malloc is at:
+ ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h
+ You don't really need this .h file unless you call functions not
+ defined in your system include files. The .h file contains only the
+ excerpts from this file needed for using this malloc on ANSI C/C++
+ systems, so long as you haven't changed compile-time options about
+ naming and tuning parameters. If you do, then you can create your
+ own malloc.h that does include all settings by cutting at the point
+ indicated below. Note that you may already by default be using a C
+ library containing a malloc that is based on some version of this
+ malloc (for example in linux). You might still want to use the one
+ in this file to customize settings or to avoid overheads associated
+ with library versions.
+
+ * Vital statistics:
+
+ Supported pointer/size_t representation: 4 or 8 bytes
+ size_t MUST be an unsigned type of the same width as
+ pointers. (If you are using an ancient system that declares
+ size_t as a signed type, or need it to be a different width
+ than pointers, you can use a previous release of this malloc
+ (e.g. 2.7.2) supporting these.)
+
+ Alignment: 8 bytes (minimum)
+ This suffices for nearly all current machines and C compilers.
+ However, you can define MALLOC_ALIGNMENT to be wider than this
+ if necessary (up to 128bytes), at the expense of using more space.
+
+ Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
+ 8 or 16 bytes (if 8byte sizes)
+ Each malloced chunk has a hidden word of overhead holding size
+ and status information, and additional cross-check word
+ if FOOTERS is defined.
+
+ Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
+ 8-byte ptrs: 32 bytes (including overhead)
+
+ Even a request for zero bytes (i.e., malloc(0)) returns a
+ pointer to something of the minimum allocatable size.
+ The maximum overhead wastage (i.e., number of extra bytes
+ allocated than were requested in malloc) is less than or equal
+ to the minimum size, except for requests >= mmap_threshold that
+ are serviced via mmap(), where the worst case wastage is about
+ 32 bytes plus the remainder from a system page (the minimal
+ mmap unit); typically 4096 or 8192 bytes.
+
+ Security: static-safe; optionally more or less
+ The "security" of malloc refers to the ability of malicious
+ code to accentuate the effects of errors (for example, freeing
+ space that is not currently malloc'ed or overwriting past the
+ ends of chunks) in code that calls malloc. This malloc
+ guarantees not to modify any memory locations below the base of
+ heap, i.e., static variables, even in the presence of usage
+ errors. The routines additionally detect most improper frees
+ and reallocs. All this holds as long as the static bookkeeping
+ for malloc itself is not corrupted by some other means. This
+ is only one aspect of security -- these checks do not, and
+ cannot, detect all possible programming errors.
+
+ If FOOTERS is defined nonzero, then each allocated chunk
+ carries an additional check word to verify that it was malloced
+ from its space. These check words are the same within each
+ execution of a program using malloc, but differ across
+ executions, so externally crafted fake chunks cannot be
+ freed. This improves security by rejecting frees/reallocs that
+ could corrupt heap memory, in addition to the checks preventing
+ writes to statics that are always on. This may further improve
+ security at the expense of time and space overhead.