From 0e92cd6e6da711f584a945e3cea325f9c0a788a9 Mon Sep 17 00:00:00 2001 From: ArkadySkv Date: Thu, 10 Sep 2026 13:35:19 +0400 Subject: [PATCH 1/3] Fix invalid tag index when parsing declarative element segments with GC reftypes The binary reader in readElementSegments() read only a single LEB for the type of declarative element segments (flag 0x07). For that flag the type is a full reftype, which may be a prefix byte plus a heap- type LEB (e.g. 0x63 0x02 for (ref null 2)). This misaligned the stream and eventually caused a spurious 'invalid tag index' error. The fix uses the same logic already applied to passive and hasTableIdx segments: read a full reftype when usesExpressions is true, and an elemkind (single byte) otherwise. Fixes #8540. --- src/wasm/wasm-binary.cpp | 13 ++++++++++--- test/spec/gc-elem-declare.wast | 5 +++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 test/spec/gc-elem-declare.wast diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 746ddbc339f..fa857fd8307 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -5333,8 +5333,15 @@ void WasmBinaryReader::readElementSegments() { if (isDeclarative) { // Declared segments are needed in wasm text and binary, but not in - // Binaryen IR; skip over the segment - [[maybe_unused]] auto type = getU32LEB(); + // Binaryen IR; skip over the segment. + if (usesExpressions) { + [[maybe_unused]] auto type = getType(); + } else { + auto elemKind = getU32LEB(); + if (elemKind != 0x0) { + throwError("unexpected passive segment elemkind, expected 0, got " + std::to_string(elemKind)); + } + } auto num = getU32LEB(); for (Index i = 0; i < num; i++) { if (usesExpressions) { @@ -5369,7 +5376,7 @@ void WasmBinaryReader::readElementSegments() { } else { auto elemKind = getU32LEB(); if (elemKind != 0x0) { - throwError("Invalid kind (!= funcref(0)) since !usesExpressions."); + throwError("unexpected passive segment elemkind, expected 0, got " + std::to_string(elemKind)); } } } diff --git a/test/spec/gc-elem-declare.wast b/test/spec/gc-elem-declare.wast new file mode 100644 index 00000000000..ada0eff9d09 --- /dev/null +++ b/test/spec/gc-elem-declare.wast @@ -0,0 +1,5 @@ +;; Binary spec test for declarative element segments with GC reftypes. +;; Before the fix, parsing this module failed with "invalid tag index". +;; See https://github.com/WebAssembly/binaryen/issues/8540 + +(module binary "\00asm\01\00\00\00\01\1b\01N\06^w\00P\00_\00^r\01P\00`\01~\00^}\01P\00^{\01\03\03\02\03\03\09\0f\03\07c\02\00\07c\03\01\d0\03\0b\07q\00\0a\07\02\02\00\0b\02\00\0b") From 093de6daf2ef663f3a048528ec5756f3fbdedf46 Mon Sep 17 00:00:00 2001 From: ArkadySkv Date: Sun, 13 Sep 2026 21:27:06 +0400 Subject: [PATCH 2/3] Reformatted to match the style in --- test/spec/gc-elem-declare.wast | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/spec/gc-elem-declare.wast b/test/spec/gc-elem-declare.wast index ada0eff9d09..8cb8174d34a 100644 --- a/test/spec/gc-elem-declare.wast +++ b/test/spec/gc-elem-declare.wast @@ -2,4 +2,27 @@ ;; Before the fix, parsing this module failed with "invalid tag index". ;; See https://github.com/WebAssembly/binaryen/issues/8540 -(module binary "\00asm\01\00\00\00\01\1b\01N\06^w\00P\00_\00^r\01P\00`\01~\00^}\01P\00^{\01\03\03\02\03\03\09\0f\03\07c\02\00\07c\03\01\d0\03\0b\07q\00\0a\07\02\02\00\0b\02\00\0b") +(module binary + "\00asm" "\01\00\00\00" ;; magic + version + + "\01\1b" ;; Type section, 27 bytes + "\01" ;; 1 rec group + "\4e\06" ;; rec group of size 6 + "\5e\77\00" ;; type 0: (array i16) + "\50\00\5f\00" ;; type 1: (sub (struct)) + "\5e\72\01" ;; type 2: (array (mut nullexternref)) + "\50\00\60\01\7e\00" ;; type 3: (sub (func (param i64))) + "\5e\7d\01" ;; type 4: (array (mut f32)) + "\50\00\5e\7b\01" ;; type 5: (sub (array (mut v128))) + + "\03\03\02\03\03" ;; Function section: 2 funcs, both type 3 + + "\09\0f\03" ;; Element section, 15 bytes + "\07\63\02\00" ;; segment 0: declare (ref null 2), 0 exprs + "\07\63\03\01\d0\03\0b" ;; segment 1: declare (ref null 3) (ref.null 3) + "\07\71\00" ;; segment 2: declare nullref, 0 exprs + + "\0a\07\02" ;; Code section, 7 bytes + "\02\00\0b" ;; function 0: empty body + "\02\00\0b" ;; function 1: empty body +) \ No newline at end of file From 44379ab90436fea4088358a7062c11e4368f9a04 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Sun, 13 Sep 2026 21:43:04 -0700 Subject: [PATCH 3/3] newline at end of test file --- test/spec/gc-elem-declare.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/gc-elem-declare.wast b/test/spec/gc-elem-declare.wast index 8cb8174d34a..347841aa0e9 100644 --- a/test/spec/gc-elem-declare.wast +++ b/test/spec/gc-elem-declare.wast @@ -25,4 +25,4 @@ "\0a\07\02" ;; Code section, 7 bytes "\02\00\0b" ;; function 0: empty body "\02\00\0b" ;; function 1: empty body -) \ No newline at end of file +)