Skip to content

Commit 1dd0e24

Browse files
Fix crash in ctor-eval when a tag is imported (#8284)
Fix for [fuzzer-detected crash when ctor-eval runs on a module that imports a tag](#8254 (comment)). Prior to #8254, ctor-eval would [crash](https://github.com/WebAssembly/binaryen/blob/23d218d0bd469a399ff17b26fdd71164beeb63fa/src/tools/wasm-ctor-eval.cpp#L396) when an imported tag was evaluated, but not when imported. Change the code to allow imported tags even during evaluation. Note that we can't reason about the identity of imported tags. In the following code, $t1 and $t2 may be the same or different tags: ```wasm (import "foo" "bar" (tag $t1)) (import "foo" "bar2" (tag $t2)) ``` In this PR, we assume that $t1 and $t2 are different tags, and that they're the same tag if the import name is the same (this is also not true in general, the hosting environment may provide two different values for the same exact import name). This may cause some correctness issues. As a followup, we can make equality comparison of two imported tags throw FailToEvalException to make evaluation correct. Part of #8180.
1 parent e103d6d commit 1dd0e24

5 files changed

Lines changed: 52 additions & 2 deletions

File tree

src/ir/import-name.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,32 @@
1919

2020
#include <ostream>
2121

22+
#include "support/hash.h"
2223
#include "support/name.h"
2324

2425
namespace wasm {
2526

2627
struct ImportNames {
2728
Name module;
2829
Name name;
30+
31+
bool operator==(const ImportNames& other) const {
32+
return module == other.module && name == other.name;
33+
}
2934
};
3035

3136
} // namespace wasm
3237

38+
namespace std {
39+
40+
template<> struct hash<wasm::ImportNames> {
41+
std::size_t operator()(const wasm::ImportNames& importNames) const noexcept {
42+
size_t val = hash<wasm::Name>{}(importNames.module);
43+
wasm::rehash(val, importNames.name);
44+
return val;
45+
}
46+
};
47+
48+
} // namespace std
49+
3350
#endif // wasm_ir_import_name_h

src/tools/wasm-ctor-eval.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,22 @@ class EvallingImportResolver : public ImportResolver {
8484
throw FailToEvalException{"Imported table access."};
8585
}
8686

87+
// We assume that each tag import is distinct. This is wrong if the same tag
88+
// instantiation is imported twice with different import names.
8789
Tag* getTagOrNull(ImportNames name,
8890
const Signature& signature) const override {
89-
Fatal() << "getTagOrNull not implemented in ctor-eval.";
90-
return nullptr;
91+
auto [it, inserted] = importedTags.try_emplace(name, Tag{});
92+
if (inserted) {
93+
auto& tag = it->second;
94+
tag.type = HeapType(signature);
95+
}
96+
97+
return &it->second;
9198
}
9299

93100
private:
94101
mutable Literals stubLiteral;
102+
mutable std::unordered_map<ImportNames, Tag> importedTags;
95103
};
96104

97105
class EvallingRuntimeTable : public RuntimeTable {

test/ctor-eval/tag-import.wast

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(module
2+
;; an imported tag that isn't accessed doesn't stop us from optimizing
3+
(import "import" "tag" (tag $imported))
4+
(global $g (mut i32) (i32.const 0))
5+
(func $setg (export "setg")
6+
(drop (i32.const 1))
7+
(global.set $g
8+
(i32.add (i32.const 1) (i32.const 2))
9+
)
10+
)
11+
12+
(func $keepalive (export "keepalive") (result i32)
13+
;; Keep the global alive so we can see its value.
14+
(global.get $g)
15+
)
16+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
setg

test/ctor-eval/tag-import.wast.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(module
2+
(type $0 (func (result i32)))
3+
(global $g (mut i32) (i32.const 3))
4+
(export "keepalive" (func $keepalive))
5+
(func $keepalive (type $0) (result i32)
6+
(global.get $g)
7+
)
8+
)

0 commit comments

Comments
 (0)