From 996cbd861c0cae4c942cc57b1915af5ea7b4d5f5 Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Wed, 4 May 2022 17:50:29 -0700 Subject: Parse the prototype nominal binary format (#4644) In f124a11ca3 we removed support for the prototype nominal binary format entirely, but that means that we can no longer parse older binary modules that used that format. Fix this regression by restoring the ability to parse the prototype binary format. --- src/wasm/wasm-binary.cpp | 49 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) (limited to 'src/wasm/wasm-binary.cpp') diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 9dcdbb73d..60a4bad77 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1985,6 +1985,7 @@ void WasmBinaryBuilder::readTypes() { builder.createRecGroup(i, groupSize); form = getS32LEB(); } + std::optional superIndex; if (form == BinaryConsts::EncodedType::Sub) { uint32_t supers = getU32LEB(); if (supers > 0) { @@ -1992,24 +1993,54 @@ void WasmBinaryBuilder::readTypes() { throwError("Invalid type definition with " + std::to_string(supers) + " supertypes"); } - uint32_t superIndex = getU32LEB(); - if (superIndex > builder.size()) { - throwError("Out of bounds supertype index " + - std::to_string(superIndex)); - } - builder[i].subTypeOf(builder[superIndex]); + superIndex = getU32LEB(); } form = getS32LEB(); } - if (form == BinaryConsts::EncodedType::Func) { + if (form == BinaryConsts::EncodedType::Func || + form == BinaryConsts::EncodedType::FuncSubtype) { builder[i] = readSignatureDef(); - } else if (form == BinaryConsts::EncodedType::Struct) { + } else if (form == BinaryConsts::EncodedType::Struct || + form == BinaryConsts::EncodedType::StructSubtype) { builder[i] = readStructDef(); - } else if (form == BinaryConsts::EncodedType::Array) { + } else if (form == BinaryConsts::EncodedType::Array || + form == BinaryConsts::EncodedType::ArraySubtype) { builder[i] = Array(readFieldDef()); } else { throwError("Bad type form " + std::to_string(form)); } + if (form == BinaryConsts::EncodedType::FuncSubtype || + form == BinaryConsts::EncodedType::StructSubtype || + form == BinaryConsts::EncodedType::ArraySubtype) { + int64_t super = getS64LEB(); // TODO: Actually s33 + if (super >= 0) { + superIndex = (uint32_t)super; + } else { + // Validate but otherwise ignore trivial supertypes. + HeapType basicSuper; + if (!getBasicHeapType(super, basicSuper)) { + throwError("Unrecognized supertype " + std::to_string(super)); + } + if (form == BinaryConsts::EncodedType::FuncSubtype) { + if (basicSuper != HeapType::func) { + throwError( + "The only allowed trivial supertype for functions is func"); + } + } else { + if (basicSuper != HeapType::data) { + throwError("The only allowed trivial supertype for structs and " + "arrays is data"); + } + } + } + } + if (superIndex) { + if (*superIndex > builder.size()) { + throwError("Out of bounds supertype index " + + std::to_string(*superIndex)); + } + builder[i].subTypeOf(builder[*superIndex]); + } } auto result = builder.build(); -- cgit v1.2.3