diff options
-rw-r--r-- | src/passes/Asyncify.cpp | 3 | ||||
-rw-r--r-- | src/support/string.h | 42 | ||||
-rw-r--r-- | test/unit/input/asyncify-pure.wast | 3 | ||||
-rw-r--r-- | test/unit/test_asyncify.py | 2 |
4 files changed, 50 insertions, 0 deletions
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index 361976fc3..379452d42 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -1043,6 +1043,9 @@ struct Asyncify : public Pass { String::Split whitelist( runner->options.getArgumentOrDefault("asyncify-whitelist", ""), ","); + blacklist = handleBracketingOperators(blacklist); + whitelist = handleBracketingOperators(whitelist); + // The lists contain human-readable strings. Turn them into the internal // escaped names for later comparisons auto processList = [module](String::Split& list, const std::string& which) { diff --git a/src/support/string.h b/src/support/string.h index c8a8cb445..72bbdb509 100644 --- a/src/support/string.h +++ b/src/support/string.h @@ -31,6 +31,8 @@ namespace String { // Creates a vector of the split parts of a string, by a delimiter. class Split : public std::vector<std::string> { public: + Split() = default; + Split(const std::string& input, const std::string& delim) { size_t lastEnd = 0; while (lastEnd < input.size()) { @@ -44,6 +46,46 @@ public: } }; +// Handles bracketing in a list initially split by ",", but the list may +// contain nested ","s. For example, +// void foo(int, double) +// must be kept together because of the "(". Likewise, "{", "<", "[" are +// handled. +inline String::Split handleBracketingOperators(String::Split split) { + String::Split ret; + std::string last; + int nesting = 0; + auto handlePart = [&](std::string part) { + if (part.empty()) { + return; + } + for (const char c : part) { + if (c == '(' || c == '<' || c == '[' || c == '{') { + nesting++; + } else if (c == ')' || c == '>' || c == ']' || c == '}') { + nesting--; + } + } + if (last.empty()) { + last = part; + } else { + last += ',' + part; + } + if (nesting == 0) { + ret.push_back(last); + last.clear(); + } + }; + for (auto& part : split) { + handlePart(part); + } + handlePart(""); + if (nesting != 0) { + Fatal() << "Asyncify: failed to parse lists"; + } + return ret; +} + // Does a simple wildcard match between a pattern and a value. Currently // supports a '*' at the end of the pattern. inline bool wildcardMatch(const std::string& pattern, diff --git a/test/unit/input/asyncify-pure.wast b/test/unit/input/asyncify-pure.wast index 27c9da111..961ab9442 100644 --- a/test/unit/input/asyncify-pure.wast +++ b/test/unit/input/asyncify-pure.wast @@ -55,5 +55,8 @@ (call $main) (call $print (i32.const 500)) ) + ;; interesting escaped name + (func $DOS_ReadFile\28unsigned\20short\2c\20unsigned\20char*\2c\20unsigned\20short*\2c\20bool\29 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + ) ) diff --git a/test/unit/test_asyncify.py b/test/unit/test_asyncify.py index 3856c262d..f2d7839b6 100644 --- a/test/unit/test_asyncify.py +++ b/test/unit/test_asyncify.py @@ -35,6 +35,8 @@ class AsyncifyTest(BinaryenTestCase): ('--pass-arg=asyncify-whitelist@nonexistent', 'nonexistent'), ('--pass-arg=asyncify-blacklist@main', None), ('--pass-arg=asyncify-whitelist@main', None), + ('--pass-arg=asyncify-whitelist@main', None), + ('--pass-arg=asyncify-whitelist@DOS_ReadFile(unsigned short, unsigned char*, unsigned short*, bool)', None), ]: print(arg, warning) err = run_process(WASM_OPT + [self.input_path('asyncify-pure.wast'), '--asyncify', arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stderr.strip() |