diff options
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 25 | ||||
-rw-r--r-- | test/ctor-eval/stack-direction.wast | 30 | ||||
-rw-r--r-- | test/ctor-eval/stack-direction.wast.ctors | 1 | ||||
-rw-r--r-- | test/ctor-eval/stack-direction.wast.out | 2 |
4 files changed, 48 insertions, 10 deletions
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 53f33944e..b0e2e2ce7 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -113,12 +113,17 @@ public: } }; -enum { - // put the stack in some ridiculously high location - STACK_START = 0x40000000, - // use a ridiculously large stack size - STACK_SIZE = 32 * 1024 * 1024 -}; +// Use a ridiculously large stack size. +static Index STACK_SIZE = 32 * 1024 * 1024; + +// Start the stack at a ridiculously large location, and do so in +// a way that works regardless if the stack goes up or down. +static Index STACK_START = 1024 * 1024 * 1024 + STACK_SIZE; + +// Bound the stack location in both directions, so we have bounds +// that do not depend on the direction it grows. +static Index STACK_LOWER_LIMIT = STACK_START - STACK_SIZE; +static Index STACK_UPPER_LIMIT = STACK_START + STACK_SIZE; class EvallingModuleInstance : public ModuleInstanceBase<EvallingGlobalManager, EvallingModuleInstance> { public: @@ -151,7 +156,7 @@ public: // but it should not be read afterwards, doing so would be undefined behavior void setupEnvironment() { // prepare scratch memory - stack.resize(STACK_SIZE); + stack.resize(2 * STACK_SIZE); // tell the module to accept writes up to the stack end auto total = STACK_START + STACK_SIZE; memorySize = total / Memory::kPageSize; @@ -266,11 +271,11 @@ private: template<typename T> T* getMemory(Address address) { // if memory is on the stack, use the stack - if (address >= STACK_START) { - Address relative = address - STACK_START; - if (relative + sizeof(T) > STACK_SIZE) { + if (address >= STACK_LOWER_LIMIT) { + if (address >= STACK_UPPER_LIMIT) { throw FailToEvalException("stack usage too high"); } + Address relative = address - STACK_LOWER_LIMIT; // in range, all is good, use the stack return (T*)(&instance->stack[relative]); } diff --git a/test/ctor-eval/stack-direction.wast b/test/ctor-eval/stack-direction.wast new file mode 100644 index 000000000..ebd6ef3fc --- /dev/null +++ b/test/ctor-eval/stack-direction.wast @@ -0,0 +1,30 @@ +(module + (type $0 (func)) + (import "env" "memory" (memory $1 256 256)) + (import "env" "STACKTOP" (global $gimport$0 i32)) + (global $global$0 (mut i32) (get_global $gimport$0)) + (export "__post_instantiate" (func $0)) + ;; if the stack goes **down**, this may seem to write to memory we care about + (func $0 (; 0 ;) (type $0) + (local $0 i32) + (i32.store offset=12 + (tee_local $0 + (i32.sub + (get_global $global$0) + (i32.const 16) + ) + ) + (i32.const 10) + ) + (i32.store offset=12 + (get_local $0) + (i32.add + (i32.load offset=12 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) +) + diff --git a/test/ctor-eval/stack-direction.wast.ctors b/test/ctor-eval/stack-direction.wast.ctors new file mode 100644 index 000000000..a9d301395 --- /dev/null +++ b/test/ctor-eval/stack-direction.wast.ctors @@ -0,0 +1 @@ +__post_instantiate diff --git a/test/ctor-eval/stack-direction.wast.out b/test/ctor-eval/stack-direction.wast.out new file mode 100644 index 000000000..4427f36e0 --- /dev/null +++ b/test/ctor-eval/stack-direction.wast.out @@ -0,0 +1,2 @@ +(module +) |