Bug 1819215 - wasm: Change the validation of supertypes during parsing. r=rhunt,jseward

Split the parsing and validation of the types section in two iterations.
First, parse and validate the types. Then, check the subtyping relationships
in a second iteration, this avoid dealing with not yet loaded supertypes.

Differential Revision: https://phabricator.services.mozilla.com/D175698
This commit is contained in:
Julien Pages 2023-04-24 17:02:58 +00:00
parent 1229a40148
commit a493bef73e
2 changed files with 31 additions and 5 deletions

View File

@ -0,0 +1,15 @@
// |jit-test| skip-if: !wasmGcEnabled()
// Checking that we are correctly validating all subtyping rules.
// In this example, $b should be a subtype of $a, even if their field types
// will be loaded later.
wasmValidateText(`
(module
(rec
(type $a (struct (field (ref $notParsedYet))))
(type $b (sub $a (struct (field (ref $notParsedYet2)))))
(type $notParsedYet (struct))
(type $notParsedYet2 (sub $notParsedYet (struct (field i32))))
)
)`);

View File

@ -1711,6 +1711,8 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) {
return false;
}
// First, iterate over the types, validate them and set super types.
// Subtyping relationship will be checked in a second iteration.
for (uint32_t recGroupTypeIndex = 0; recGroupTypeIndex < recGroupLength;
recGroupTypeIndex++) {
uint32_t typeIndex =
@ -1795,11 +1797,6 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) {
}
if (superTypeDef) {
// Check that the super type is compatible with this type
if (!TypeDef::canBeSubTypeOf(typeDef, superTypeDef)) {
return d.fail("incompatible super type");
}
// Check that we aren't creating too deep of a subtyping chain
if (superTypeDef->subTypingDepth() >= MaxSubTypingDepth) {
return d.fail("type is too deep");
@ -1809,6 +1806,20 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) {
}
}
// Check the super types to make sure they are compatible with their
// subtypes. This is done in a second iteration to avoid dealing with not
// yet loaded types.
for (uint32_t recGroupTypeIndex = 0; recGroupTypeIndex < recGroupLength;
recGroupTypeIndex++) {
TypeDef* typeDef = &recGroup->type(recGroupTypeIndex);
if (typeDef->superTypeDef()) {
// Check that the super type is compatible with this type
if (!TypeDef::canBeSubTypeOf(typeDef, typeDef->superTypeDef())) {
return d.fail("incompatible super type");
}
}
}
// Finish the recursion group, which will canonicalize the types.
if (!env->types->endRecGroup()) {
return false;