summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-08-21 15:05:22 -0700
committerGitHub <noreply@github.com>2024-08-21 15:05:22 -0700
commit692e55c14bd3055b1aae49681bb8e62c757c678d (patch)
tree1b25a10166b1cd2dea159f3f59e02dde361a7636 /src
parent99db0d9c7c33bcea7b7730bb5684f41176146f83 (diff)
downloadbinaryen-692e55c14bd3055b1aae49681bb8e62c757c678d.tar.gz
binaryen-692e55c14bd3055b1aae49681bb8e62c757c678d.tar.bz2
binaryen-692e55c14bd3055b1aae49681bb8e62c757c678d.zip
Add a string lowering mode disallowing non-UTF-8 strings (#6861)
The best way to lower strings is via the "magic imports" API that uses the names of imported string globals as their values. This approach only works for valid UTF-8 strings, though. The existing string-lowering-magic-imports pass falls back to putting non-UTF-8 strings in a JSON custom section, but this requires the runtime to support that custom section for correctness. To help catch errors early when runtimes do not support the strings custom section, add a new pass that uses magic imports and raises an error if there are any invalid strings.
Diffstat (limited to 'src')
-rw-r--r--src/passes/StringLowering.cpp21
-rw-r--r--src/passes/pass.cpp4
-rw-r--r--src/passes/passes.h1
3 files changed, 24 insertions, 2 deletions
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp
index fa5c1c9a8..92e3268dc 100644
--- a/src/passes/StringLowering.cpp
+++ b/src/passes/StringLowering.cpp
@@ -194,8 +194,16 @@ struct StringLowering : public StringGathering {
// instead of emitting them into the JSON custom section.
bool useMagicImports;
- StringLowering(bool useMagicImports = false)
- : useMagicImports(useMagicImports) {}
+ // Whether to throw a fatal error on non-UTF8 strings that would not be able
+ // to use the "magic import" mechanism. Only usable in conjunction with magic
+ // imports.
+ bool assertUTF8;
+
+ StringLowering(bool useMagicImports = false, bool assertUTF8 = false)
+ : useMagicImports(useMagicImports), assertUTF8(assertUTF8) {
+ // If we are asserting valid UTF-8, we must be using magic imports.
+ assert(!assertUTF8 || useMagicImports);
+ }
void run(Module* module) override {
if (!module->features.has(FeatureSet::Strings)) {
@@ -238,6 +246,12 @@ struct StringLowering : public StringGathering {
global->module = "'";
global->base = Name(utf8.str());
} else {
+ if (assertUTF8) {
+ std::stringstream escaped;
+ String::printEscaped(escaped, utf8.str());
+ Fatal() << "Cannot lower non-UTF-16 string " << escaped.str()
+ << '\n';
+ }
global->module = "string.const";
global->base = std::to_string(jsonImportIndex);
if (first) {
@@ -534,5 +548,8 @@ struct StringLowering : public StringGathering {
Pass* createStringGatheringPass() { return new StringGathering(); }
Pass* createStringLoweringPass() { return new StringLowering(); }
Pass* createStringLoweringMagicImportPass() { return new StringLowering(true); }
+Pass* createStringLoweringMagicImportAssertPass() {
+ return new StringLowering(true, true);
+}
} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index ccfc7b728..35d2f6779 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -503,6 +503,10 @@ void PassRegistry::registerPasses() {
"string-lowering-magic-imports",
"same as string-lowering, but encodes well-formed strings as magic imports",
createStringLoweringMagicImportPass);
+ registerPass("string-lowering-magic-imports-assert",
+ "same as string-lowering-magic-imports, but raise a fatal error "
+ "if there are invalid strings",
+ createStringLoweringMagicImportAssertPass);
registerPass(
"strip", "deprecated; same as strip-debug", createStripDebugPass);
registerPass("stack-check",
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 9fcb5f95f..a95365676 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -158,6 +158,7 @@ Pass* createStackCheckPass();
Pass* createStringGatheringPass();
Pass* createStringLoweringPass();
Pass* createStringLoweringMagicImportPass();
+Pass* createStringLoweringMagicImportAssertPass();
Pass* createStripDebugPass();
Pass* createStripDWARFPass();
Pass* createStripProducersPass();