summaryrefslogtreecommitdiff
path: root/src/binaryen-shell.cpp
diff options
context:
space:
mode:
authorJF Bastien <jfb@chromium.org>2016-01-13 18:55:57 -0800
committerJF Bastien <jfb@chromium.org>2016-01-13 19:43:29 -0800
commit01455820d430120c694dbc9978ed4dc8192185e0 (patch)
tree40c46c355edbda1c7b188685aa88cc6e6aa59a85 /src/binaryen-shell.cpp
parent1466e072717f6516eae1885296ace1d7acb38f2f (diff)
downloadbinaryen-01455820d430120c694dbc9978ed4dc8192185e0.tar.gz
binaryen-01455820d430120c694dbc9978ed4dc8192185e0.tar.bz2
binaryen-01455820d430120c694dbc9978ed4dc8192185e0.zip
Avoid potential setjmp clobber
-Wextra adds checks for potential clobbers which triggered in binaryen-shell.cpp: might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered] The fix moves the setjmp/longjmp using code into another function, and passes in potentially-clobbered values from the parent frame so they can't be clobbered. We could also mark them as volatile but that's a big hammer.
Diffstat (limited to 'src/binaryen-shell.cpp')
-rw-r--r--src/binaryen-shell.cpp142
1 files changed, 77 insertions, 65 deletions
diff --git a/src/binaryen-shell.cpp b/src/binaryen-shell.cpp
index 55beb6aa8..6000430a5 100644
--- a/src/binaryen-shell.cpp
+++ b/src/binaryen-shell.cpp
@@ -169,6 +169,79 @@ struct Invocation {
}
};
+static void run_asserts(size_t* i, bool* checked, AllocatingModule* wasm,
+ Element* root,
+ std::unique_ptr<SExpressionWasmBuilder>* builder,
+ bool print_before, bool print_after) {
+ auto interface = new ShellExternalInterface();
+ auto instance = new ModuleInstance(*wasm, interface);
+ while (*i < root->size()) {
+ Element& curr = *(*root)[*i];
+ IString id = curr[0]->str();
+ if (id == MODULE) break;
+ *checked = true;
+ Colors::red(std::cerr);
+ std::cerr << *i << '/' << (root->size()-1);
+ Colors::green(std::cerr);
+ std::cerr << " CHECKING: ";
+ Colors::normal(std::cerr);
+ std::cerr << curr << '\n';
+ if (id == ASSERT_INVALID) {
+ // a module invalidity test
+ AllocatingModule wasm;
+ bool invalid = false;
+ jmp_buf trapState;
+ if (setjmp(trapState) == 0) {
+ *builder = std::unique_ptr<SExpressionWasmBuilder>(new SExpressionWasmBuilder(wasm, *curr[1], [&]() {
+ invalid = true;
+ longjmp(trapState, 1);
+ }));
+ }
+ if (print_before || print_after) {
+ Colors::bold(std::cout);
+ std::cerr << "printing in module invalidity test:\n";
+ Colors::normal(std::cout);
+ std::cout << wasm;
+ }
+ if (!invalid) {
+ // maybe parsed ok, but otherwise incorrect
+ invalid = !WasmValidator().validate(wasm);
+ }
+ assert(invalid);
+ } else if (id == INVOKE) {
+ Invocation invocation(curr, instance, *builder->get());
+ invocation.invoke();
+ } else {
+ // an invoke test
+ Invocation invocation(*curr[1], instance, *builder->get());
+ bool trapped = false;
+ Literal result;
+ if (setjmp(interface->trapState) == 0) {
+ result = invocation.invoke();
+ } else {
+ trapped = true;
+ }
+ if (id == ASSERT_RETURN) {
+ assert(!trapped);
+ if (curr.size() >= 3) {
+ Literal expected = builder->get()
+ ->parseExpression(*curr[2])
+ ->dyn_cast<Const>()
+ ->value;
+ std::cerr << "seen " << result << ", expected " << expected << '\n';
+ assert(expected == result);
+ } else {
+ Literal expected;
+ std::cerr << "seen " << result << ", expected " << expected << '\n';
+ assert(expected == result);
+ }
+ }
+ if (id == ASSERT_TRAP) assert(trapped);
+ }
+ *i += 1;
+ }
+}
+
//
// main
//
@@ -265,12 +338,10 @@ int main(int argc, char **argv) {
while (i < root.size()) {
if (debug) std::cerr << "parsing s-expressions to wasm...\n";
AllocatingModule wasm;
- SExpressionWasmBuilder builder(wasm, *root[i], [&]() { abort(); }, debug);
+ std::unique_ptr<SExpressionWasmBuilder> builder(
+ new SExpressionWasmBuilder(wasm, *root[i], [&]() { abort(); }, debug));
i++;
- auto interface = new ShellExternalInterface();
- auto instance = new ModuleInstance(wasm, interface);
-
if (print_before) {
Colors::bold(std::cout);
std::cerr << "printing before:\n";
@@ -296,67 +367,8 @@ int main(int argc, char **argv) {
std::cout << wasm;
}
- // run asserts
- while (i < root.size()) {
- Element& curr = *root[i];
- IString id = curr[0]->str();
- if (id == MODULE) break;
- checked = true;
- Colors::red(std::cerr);
- std::cerr << i << '/' << (root.size()-1);
- Colors::green(std::cerr);
- std::cerr << " CHECKING: ";
- Colors::normal(std::cerr);
- std::cerr << curr << '\n';
- if (id == ASSERT_INVALID) {
- // a module invalidity test
- AllocatingModule wasm;
- bool invalid = false;
- jmp_buf trapState;
- std::unique_ptr<SExpressionWasmBuilder> builder;
- if (setjmp(trapState) == 0) {
- builder = std::unique_ptr<SExpressionWasmBuilder>(new SExpressionWasmBuilder(wasm, *curr[1], [&]() {
- invalid = true;
- longjmp(trapState, 1);
- }));
- }
- if (print_before || print_after) {
- Colors::bold(std::cout);
- std::cerr << "printing in module invalidity test:\n";
- Colors::normal(std::cout);
- std::cout << wasm;
- }
- if (!invalid) {
- // maybe parsed ok, but otherwise incorrect
- invalid = !WasmValidator().validate(wasm);
- }
- assert(invalid);
- } else if (id == INVOKE) {
- Invocation invocation(curr, instance, builder);
- invocation.invoke();
- } else {
- // an invoke test
- Invocation invocation(*curr[1], instance, builder);
- bool trapped = false;
- Literal result;
- if (setjmp(interface->trapState) == 0) {
- result = invocation.invoke();
- } else {
- trapped = true;
- }
- if (id == ASSERT_RETURN) {
- assert(!trapped);
- Literal expected;
- if (curr.size() >= 3) {
- expected = builder.parseExpression(*curr[2])->dyn_cast<Const>()->value;
- }
- std::cerr << "seen " << result << ", expected " << expected << '\n';
- assert(expected == result);
- }
- if (id == ASSERT_TRAP) assert(trapped);
- }
- i++;
- }
+ run_asserts(&i, &checked, &wasm, &root, &builder, print_before,
+ print_after);
}
if (checked) {