From 1ae46f1ec7228f33e2f61b5b8b7cdc79486358b8 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 11 Feb 2026 10:14:01 -0800 Subject: [PATCH 1/2] Validate features when building shared types Previously we would validate that some usages (e.g. globals) of shared types required the shared-everything feature, but that was not enough to prevent fuzzer issues because it was still possible to write a file that used shared types and passed validation without shared-everything, so would fail when fuzzed on V8. Fix the problem by validating features when building shared types in the first place. --- src/wasm-type.h | 2 ++ src/wasm/wasm-type.cpp | 5 ++++ test/lit/basic/print-explicit-typeuse.wast | 2 +- test/lit/passes/gto-jsinterop.wast | 29 ------------------ test/lit/passes/gto-shared-jsinterop.wast | 34 ++++++++++++++++++++++ test/lit/validation/shared-struct.wast | 2 +- 6 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 test/lit/passes/gto-shared-jsinterop.wast diff --git a/src/wasm-type.h b/src/wasm-type.h index d5d1a5348bf..2364641a17c 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -904,6 +904,8 @@ struct TypeBuilder { ForwardChildReference, // A continuation reference that does not refer to a function type. InvalidFuncType, + // A shared type with shared-everything disabled. + InvalidSharedType, // A non-shared field of a shared heap type. InvalidUnsharedField, // A describes clause on a non-struct type. diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 70887233cf2..d621df72154 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -1445,6 +1445,8 @@ std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) { return os << "Heap type has an undeclared child"; case TypeBuilder::ErrorReason::InvalidFuncType: return os << "Continuation has invalid function type"; + case TypeBuilder::ErrorReason::InvalidSharedType: + return os << "Shared types require shared-everything"; case TypeBuilder::ErrorReason::InvalidUnsharedField: return os << "Heap type has an invalid unshared field"; case TypeBuilder::ErrorReason::NonStructDescribes: @@ -2470,6 +2472,9 @@ validateType(HeapTypeInfo& info, } } if (info.share == Shared) { + if (!features.hasSharedEverything()) { + return TypeBuilder::ErrorReason::InvalidSharedType; + } if (info.described && info.described->share != Shared) { return TypeBuilder::ErrorReason::InvalidUnsharedDescribes; } diff --git a/test/lit/basic/print-explicit-typeuse.wast b/test/lit/basic/print-explicit-typeuse.wast index 367159f373d..310d4b14a68 100644 --- a/test/lit/basic/print-explicit-typeuse.wast +++ b/test/lit/basic/print-explicit-typeuse.wast @@ -1,5 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: wasm-opt %s --no-validation -S -o - | filecheck %s +;; RUN: wasm-opt %s --enable-shared-everything --no-validation -S -o - | filecheck %s ;; Check that we print explicit type uses for function signatures when the ;; function type uses non-MVP features, whether or not those features are diff --git a/test/lit/passes/gto-jsinterop.wast b/test/lit/passes/gto-jsinterop.wast index 23bc2a5fd02..8a7c5af626a 100644 --- a/test/lit/passes/gto-jsinterop.wast +++ b/test/lit/passes/gto-jsinterop.wast @@ -143,35 +143,6 @@ ) ) -(module - (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $struct (descriptor $desc) (struct)) - (type $struct (descriptor $desc) (struct)) - ;; Maybe we will support shared prototypes someday. - ;; CHECK: (type $desc (describes $struct) (struct (field (ref null (shared extern))))) - (type $desc (describes $struct) (struct (field (ref null (shared extern))))) - ) - - ;; CHECK: (type $2 (func)) - - ;; CHECK: (func $externalize (type $2) - ;; CHECK-NEXT: (local $struct (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (extern.convert_any - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $externalize - (local $struct (ref null $struct)) - (drop - (extern.convert_any - (local.get $struct) - ) - ) - ) -) (module (rec diff --git a/test/lit/passes/gto-shared-jsinterop.wast b/test/lit/passes/gto-shared-jsinterop.wast new file mode 100644 index 00000000000..cf0261fd970 --- /dev/null +++ b/test/lit/passes/gto-shared-jsinterop.wast @@ -0,0 +1,34 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: foreach %s %t wasm-opt -all --closed-world --gto --preserve-type-order -S -o - | filecheck %s + +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $struct (descriptor $desc) (struct)) + (type $struct (descriptor $desc) (struct)) + ;; Maybe we will support shared prototypes someday. The shared externref + ;; should not be optimized out. + ;; CHECK: (type $desc (describes $struct) (struct (field (ref null (shared extern))))) + (type $desc (describes $struct) (struct (field (ref null (shared extern))))) + ) + + ;; CHECK: (type $2 (func)) + + ;; CHECK: (func $externalize (type $2) + ;; CHECK-NEXT: (local $struct (ref null $struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (extern.convert_any + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $externalize + (local $struct (ref null $struct)) + (drop + (extern.convert_any + (local.get $struct) + ) + ) + ) +) \ No newline at end of file diff --git a/test/lit/validation/shared-struct.wast b/test/lit/validation/shared-struct.wast index 1e96dc9f5a5..d2cf8ee00b8 100644 --- a/test/lit/validation/shared-struct.wast +++ b/test/lit/validation/shared-struct.wast @@ -3,7 +3,7 @@ ;; RUN: not wasm-opt %s 2>&1 | filecheck %s --check-prefix NO-SHARED ;; RUN: wasm-opt %s --enable-reference-types --enable-gc --enable-shared-everything -o - -S | filecheck %s --check-prefix SHARED -;; NO-SHARED: global type requires additional features [--enable-reference-types --enable-gc --enable-shared-everything] +;; NO-SHARED: invalid type: Shared types require shared-everything ;; SHARED: (type $t (shared (struct))) (module From 663e802bf0d51f023fa6baab3e2c851d2a58277e Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 11 Feb 2026 10:57:28 -0800 Subject: [PATCH 2/2] Update test/lit/passes/gto-shared-jsinterop.wast --- test/lit/passes/gto-shared-jsinterop.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit/passes/gto-shared-jsinterop.wast b/test/lit/passes/gto-shared-jsinterop.wast index cf0261fd970..28f632739d8 100644 --- a/test/lit/passes/gto-shared-jsinterop.wast +++ b/test/lit/passes/gto-shared-jsinterop.wast @@ -31,4 +31,4 @@ ) ) ) -) \ No newline at end of file +)