diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-02-26 17:05:07 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-02-26 17:05:07 -0500 |
commit | 2f5e6f993e1b1a446331520b4dc2d5b19d597371 (patch) | |
tree | 970e5a6e77c2540f7e9459bd7fc0df1681eff46b | |
parent | 0e51f92d800dac9e697a8488c36b62e23bdb0d76 (diff) |
SAFE_DYNCALLS option
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/modules.js | 9 | ||||
-rw-r--r-- | src/settings.js | 2 | ||||
-rwxr-xr-x | tests/runner.py | 31 |
4 files changed, 43 insertions, 1 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 5f327076..ff43c8c6 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1401,6 +1401,8 @@ function JSify(data, functionsOnly, givenFunctions) { if (ASM_JS) { assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out) callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py + } else if (SAFE_DYNCALLS) { + callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 ? abort("dyncall error") : tempInt)'; } callIdent = Functions.getTable(sig) + '[' + callIdent + ']'; } diff --git a/src/modules.js b/src/modules.js index f3c14cd1..7f8a959b 100644 --- a/src/modules.js +++ b/src/modules.js @@ -330,9 +330,16 @@ var Functions = { } } } + if (SAFE_DYNCALLS) { + assert(!ASM_JS, 'cannot emit safe dyncalls in asm'); + for (var j = 0; j < table.length; j++) { + if (table[j] == 0) { + table[j] = "function() { abort('dyncall error') }"; + } + } + } if (table.length > 20) { // add some newlines in the table, for readability - table = table.slice(0); var j = 10; while (j+10 < table.length) { table[j] += '\n'; diff --git a/src/settings.js b/src/settings.js index 21b6abcf..308afddc 100644 --- a/src/settings.js +++ b/src/settings.js @@ -128,6 +128,8 @@ var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give // that 3 is the option you usually want here. var SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations +var SAFE_DYNCALLS = 0; // Show stack traces on missing function pointer/virtual method calls + var ASM_HEAP_LOG = 0; // Simple heap logging, like SAFE_HEAP_LOG but cheaper, and in asm.js var CORRUPTION_CHECK = 0; // When enabled, will emit a buffer area at the beginning and diff --git a/tests/runner.py b/tests/runner.py index aae4c460..4c41c72e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2806,6 +2806,37 @@ Exiting setjmp function, level: 0, prev_jmp: -1 ''' % addr self.do_run(src, 'segmentation fault' if addr.isdigit() else 'marfoosh') + def test_safe_dyncalls(self): + if Settings.ASM_JS: return self.skip('asm does not support missing function stack traces') + if Settings.SAFE_HEAP: return self.skip('safe heap warning will appear instead') + if self.emcc_args is None: return self.skip('need libc') + + Settings.SAFE_DYNCALLS = 1 + + for cond, body, work in [(True, True, False), (True, False, False), (False, True, True), (False, False, False)]: + print cond, body, work + src = r''' + #include <stdio.h> + + struct Classey { + virtual void doIt() = 0; + }; + + struct D1 : Classey { + virtual void doIt() BODY; + }; + + int main(int argc, char **argv) + { + Classey *p = argc COND 100 ? new D1() : NULL; + printf("%p\n", p); + p->doIt(); + + return 0; + } + '''.replace('COND', '==' if cond else '!=').replace('BODY', r'{ printf("all good\n"); }' if body else '') + self.do_run(src, 'dyncall error' if not work else 'all good') + def test_dynamic_cast(self): if self.emcc_args is None: return self.skip('need libcxxabi') |