From d6034d9790030efa3f1cb4fce62abba36f014646 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 10:36:08 -0700 Subject: refactor string to binary parsing in s-expression code so that we can use it in more places --- src/wasm-s-parser.h | 79 +++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 2c81b8a27..298f155ee 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1051,6 +1051,48 @@ private: return ret; } + // converts an s-expression string representing binary data into an output sequence of raw bytes + void stringToBinary(const char* input, size_t size, std::vector& data) { + data.resize(size); + char *write = data.data(); + while (1) { + if (input[0] == 0) break; + if (input[0] == '\\') { + if (input[1] == '"') { + *write++ = '"'; + input += 2; + continue; + } else if (input[1] == '\'') { + *write++ = '\''; + input += 2; + continue; + } else if (input[1] == '\\') { + *write++ = '\\'; + input += 2; + continue; + } else if (input[1] == 'n') { + *write++ = '\n'; + input += 2; + continue; + } else if (input[1] == 't') { + *write++ = '\t'; + input += 2; + continue; + } else { + *write++ = (char)(unhex(input[1])*16 + unhex(input[2])); + input += 3; + continue; + } + } + *write++ = input[0]; + input++; + } + assert(write >= data.data()); + size_t written = write - data.data(); + assert(written <= data.size()); + data.resize(written); + } + bool hasMemory = false; void parseMemory(Element& s) { @@ -1069,41 +1111,8 @@ private: const char *input = curr[2]->c_str(); if (auto size = strlen(input)) { std::vector data; - data.resize(size); - char *write = data.data(); - while (1) { - if (input[0] == 0) break; - if (input[0] == '\\') { - if (input[1] == '"') { - *write++ = '"'; - input += 2; - continue; - } else if (input[1] == '\'') { - *write++ = '\''; - input += 2; - continue; - } else if (input[1] == '\\') { - *write++ = '\\'; - input += 2; - continue; - } else if (input[1] == 'n') { - *write++ = '\n'; - input += 2; - continue; - } else if (input[1] == 't') { - *write++ = '\t'; - input += 2; - continue; - } else { - *write++ = (char)(unhex(input[1])*16 + unhex(input[2])); - input += 3; - continue; - } - } - *write++ = input[0]; - input++; - } - wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), data.data(), write - data.data()); + stringToBinary(input, size, data); + wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), data.data(), data.size()); } else { wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), "", 0); } -- cgit v1.2.3 From aca5642e0d8d17c31c86f6da3dff4256ae53babd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 10:48:34 -0700 Subject: parse binary modules encoded in wats --- src/wasm-s-parser.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 298f155ee..3187ce63c 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -27,6 +27,7 @@ #include #include "wasm.h" +#include "wasm-binary.h" #include "asmjs/shared-constants.h" #include "mixed_arena.h" #include "parsing.h" @@ -248,6 +249,19 @@ public: // Assumes control of and modifies the input. SExpressionWasmBuilder(Module& wasm, Element& module, std::function onError) : wasm(wasm), allocator(wasm.allocator), onError(onError), importCounter(0) { assert(module[0]->str() == MODULE); + if (module.size() > 1 && module[1]->isStr()) { + // these s-expressions contain a binary module, actually + auto str = module[1]->c_str(); + if (auto size = strlen(str)) { + std::vector data; + stringToBinary(str, size, data); + WasmBinaryBuilder binaryBuilder(wasm, data, false); + binaryBuilder.read(); + } else { + onError(); + } + return; + } functionCounter = 0; for (unsigned i = 1; i < module.size(); i++) { preParseFunctionType(*module[i]); -- cgit v1.2.3 From d36b1975100f3c73557fd303d095ee8e57306089 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 10:52:40 -0700 Subject: allow appending in stringToBinary --- src/wasm-s-parser.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 3187ce63c..3b6b07fb0 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1066,9 +1066,11 @@ private: } // converts an s-expression string representing binary data into an output sequence of raw bytes + // this appends to data, which may already contain content. void stringToBinary(const char* input, size_t size, std::vector& data) { - data.resize(size); - char *write = data.data(); + auto originalSize = data.size(); + data.resize(originalSize + size); + char *write = data.data() + originalSize; while (1) { if (input[0] == 0) break; if (input[0] == '\\') { @@ -1102,9 +1104,9 @@ private: input++; } assert(write >= data.data()); - size_t written = write - data.data(); - assert(written <= data.size()); - data.resize(written); + size_t actual = write - data.data(); + assert(actual <= data.size()); + data.resize(actual); } bool hasMemory = false; -- cgit v1.2.3 From 7cb38a21e3e1085a39048b20dbbbb5c06f9dc4c5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 10:54:32 -0700 Subject: parse binary modules encoded in wasts that arrive in pieces --- src/wasm-s-parser.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 3b6b07fb0..73421e773 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -251,15 +251,16 @@ public: assert(module[0]->str() == MODULE); if (module.size() > 1 && module[1]->isStr()) { // these s-expressions contain a binary module, actually - auto str = module[1]->c_str(); - if (auto size = strlen(str)) { - std::vector data; - stringToBinary(str, size, data); - WasmBinaryBuilder binaryBuilder(wasm, data, false); - binaryBuilder.read(); - } else { - onError(); + std::vector data; + size_t i = 1; + while (i < module.size()) { + auto str = module[i++]->c_str(); + if (auto size = strlen(str)) { + stringToBinary(str, size, data); + } } + WasmBinaryBuilder binaryBuilder(wasm, data, false); + binaryBuilder.read(); return; } functionCounter = 0; -- cgit v1.2.3 From bc307c19ddca4bef900db3ff9d512bd21a57be60 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 11:02:43 -0700 Subject: allow error handling in binary parsing --- src/binaryen-c.cpp | 4 +++- src/wasm-binary.h | 3 ++- src/wasm-dis.cpp | 4 +++- src/wasm-s-parser.h | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 583f64094..ecb70bc1b 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -416,7 +416,9 @@ BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) { std::vector buffer(false); buffer.resize(inputSize); std::copy_n(input, inputSize, buffer.begin()); - WasmBinaryBuilder parser(*wasm, buffer, false); + WasmBinaryBuilder parser(*wasm, buffer, []() { + Fatal() << "error in parsing wasm binary"; + }, false); parser.read(); return wasm; } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index c889f1418..4670c9de3 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1164,13 +1164,14 @@ class WasmBinaryBuilder { Module& wasm; MixedArena& allocator; std::vector& input; + std::function onError; bool debug; size_t pos = 0; int32_t startIndex = -1; public: - WasmBinaryBuilder(Module& wasm, std::vector& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug) {} + WasmBinaryBuilder(Module& wasm, std::vector& input, std::function onError, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), onError(onError), debug(debug) {} void read() { diff --git a/src/wasm-dis.cpp b/src/wasm-dis.cpp index e2e103b46..94965518c 100644 --- a/src/wasm-dis.cpp +++ b/src/wasm-dis.cpp @@ -45,7 +45,9 @@ int main(int argc, const char *argv[]) { if (options.debug) std::cerr << "parsing binary..." << std::endl; Module wasm; - WasmBinaryBuilder parser(wasm, input, options.debug); + WasmBinaryBuilder parser(wasm, input, []() { + Fatal() << "error in parsing wasm binary"; + }, options.debug); parser.read(); if (options.debug) std::cerr << "Printing..." << std::endl; diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 73421e773..4b27918d3 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -259,7 +259,7 @@ public: stringToBinary(str, size, data); } } - WasmBinaryBuilder binaryBuilder(wasm, data, false); + WasmBinaryBuilder binaryBuilder(wasm, data, onError, false); binaryBuilder.read(); return; } -- cgit v1.2.3 From b519fd87f7f1e1adead0ed648f29301303518ff0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 May 2016 11:07:28 -0700 Subject: add error handling for binary errors in new spec test --- src/wasm-binary.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 4670c9de3..a5cf0fe5c 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1226,7 +1226,7 @@ public: } uint8_t getInt8() { - assert(more()); + if (!more()) onError(); if (debug) std::cerr << "getInt8: " << (int)(uint8_t)input[pos] << " (at " << pos << ")" << std::endl; return input[pos++]; } @@ -1330,27 +1330,27 @@ public: void verifyInt8(int8_t x) { int8_t y = getInt8(); - assert(x == y); + if (x != y) onError(); } void verifyInt16(int16_t x) { int16_t y = getInt16(); - assert(x == y); + if (x != y) onError(); } void verifyInt32(int32_t x) { int32_t y = getInt32(); - assert(x == y); + if (x != y) onError(); } void verifyInt64(int64_t x) { int64_t y = getInt64(); - assert(x == y); + if (x != y) onError(); } void verifyFloat32(float x) { float y = getFloat32(); - assert(x == y); + if (x != y) onError(); } void verifyFloat64(double x) { double y = getFloat64(); - assert(x == y); + if (x != y) onError(); } void ungetInt8() { -- cgit v1.2.3