Removes validatedActiveElementSegment (#1292)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
Takeshi Yoneda
2023-03-27 16:19:40 -07:00
committed by GitHub
parent a9829b627b
commit 9a87d2628b
5 changed files with 112 additions and 206 deletions

View File

@@ -152,16 +152,6 @@ type Module struct {
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0
CustomSections []*CustomSection
// validatedActiveElementSegments are built on Validate when
// SectionIDElement is non-empty and all inputs are valid.
//
// Note: elementSegments retain Module.ElementSection order. Since an
// ElementSegment can overlap with another, order preservation ensures a
// consistent initialization result.
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-instances%E2%91%A0
validatedActiveElementSegments []validatedActiveElementSegment
// DataCountSection is the optional section and holds the number of data segments in the data section.
//
// Note: This may exist in WebAssembly 2.0 or WebAssembly 1.0 with CoreFeatureBulkMemoryOperations.
@@ -272,7 +262,7 @@ func (m *Module) Validate(enabledFeatures api.CoreFeatures) error {
}
} // No need to validate host functions as NewHostModule validates
if _, err = m.validateTable(enabledFeatures, tables, MaximumTableIndex); err != nil {
if err = m.validateTable(enabledFeatures, tables, MaximumTableIndex); err != nil {
return err
}

View File

@@ -174,20 +174,29 @@ func (m *ModuleInstance) buildElementInstances(elements []ElementSegment) {
}
}
func (m *ModuleInstance) applyElements(elems []validatedActiveElementSegment) {
func (m *ModuleInstance) applyElements(elems []ElementSegment) {
for elemI := range elems {
elem := &elems[elemI]
if !elem.IsActive() ||
// Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op.
len(elem.Init) == 0 {
continue
}
var offset uint32
if elem.opcode == OpcodeGlobalGet {
global := m.Globals[elem.arg]
if elem.OffsetExpr.Opcode == OpcodeGlobalGet {
// Ignore error as it's already validated.
globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data)
global := m.Globals[globalIdx]
offset = uint32(global.Val)
} else {
offset = elem.arg // constant
// Ignore error as it's already validated.
o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data)
offset = uint32(o)
}
table := m.Tables[elem.tableIndex]
table := m.Tables[elem.TableIndex]
references := table.References
if int(offset)+len(elem.init) > len(references) {
if int(offset)+len(elem.Init) > len(references) {
// ErrElementOffsetOutOfBounds is the error raised when the active element offset exceeds the table length.
// Before CoreFeatureReferenceTypes, this was checked statically before instantiation, after the proposal,
// this must be raised as runtime error (as in assert_trap in spectest), not even an instantiation error.
@@ -199,11 +208,11 @@ func (m *ModuleInstance) applyElements(elems []validatedActiveElementSegment) {
}
if table.Type == RefTypeExternref {
for i := 0; i < len(elem.init); i++ {
for i := 0; i < len(elem.Init); i++ {
references[offset+uint32(i)] = Reference(0)
}
} else {
for i, fnIndex := range elem.init {
for i, fnIndex := range elem.Init {
if fnIndex != ElementInitNullReference {
references[offset+uint32(i)] = m.Engine.FunctionInstanceReference(fnIndex)
}
@@ -386,7 +395,7 @@ func (s *Store) instantiate(
return nil, err
}
m.applyElements(module.validatedActiveElementSegments)
m.applyElements(module.ElementSection)
// Execute the start function.
if module.StartSection != nil {

View File

@@ -879,7 +879,9 @@ func globalsContain(globals []*GlobalInstance, want *GlobalInstance) bool {
return false
}
func TestModuleInstance_applyTableInits(t *testing.T) {
func TestModuleInstance_applyElementsapplyElements(t *testing.T) {
leb128_100 := leb128.EncodeInt32(100)
t.Run("extenref", func(t *testing.T) {
m := &ModuleInstance{}
m.Tables = []*TableInstance{{Type: RefTypeExternref, References: make([]Reference, 10)}}
@@ -888,16 +890,16 @@ func TestModuleInstance_applyTableInits(t *testing.T) {
}
// This shouldn't panic.
m.applyElements([]validatedActiveElementSegment{{arg: 100}})
m.applyElements([]validatedActiveElementSegment{
{arg: 0, init: make([]Index, 3)},
{arg: 100}, // Iteration stops at this point, so the offset:5 below shouldn't be applied.
{arg: 5, init: make([]Index, 5)},
m.applyElements([]ElementSegment{{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128_100}}})
m.applyElements([]ElementSegment{
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: make([]Index, 3)},
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128_100}, Init: make([]Index, 5)}, // Iteration stops at this point, so the offset:5 below shouldn't be applied.
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{5}}, Init: make([]Index, 5)},
})
require.Equal(t, []Reference{0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
m.Tables[0].References)
m.applyElements([]validatedActiveElementSegment{
{arg: 5, init: make([]Index, 5)},
m.applyElements([]ElementSegment{
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{5}}, Init: make([]Index, 5)},
})
require.Equal(t, []Reference{0, 0, 0, 0xffff, 0xffff, 0, 0, 0, 0, 0}, m.Tables[0].References)
})
@@ -914,16 +916,16 @@ func TestModuleInstance_applyTableInits(t *testing.T) {
}
// This shouldn't panic.
m.applyElements([]validatedActiveElementSegment{{arg: 100}})
m.applyElements([]validatedActiveElementSegment{
{arg: 0, init: []Index{0, 1, 2}},
{arg: 100}, // Iteration stops at this point, so the offset:5 below shouldn't be applied.
{arg: 5, init: make([]Index, 5)},
m.applyElements([]ElementSegment{{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128_100}, Init: []Index{1, 2, 3}}})
m.applyElements([]ElementSegment{
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0, 1, 2}},
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128_100}, Init: make([]Index, 5)}, // Iteration stops at this point, so the offset:5 below shouldn't be applied.
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{5}}, Init: make([]Index, 5)},
})
require.Equal(t, []Reference{0xa, 0xaa, 0xaaa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
m.Tables[0].References)
m.applyElements([]validatedActiveElementSegment{
{arg: 5, init: []Index{0, ElementInitNullReference, 2}},
m.applyElements([]ElementSegment{
{Mode: ElementModeActive, OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{5}}, Init: []Index{0, ElementInitNullReference, 2}},
})
require.Equal(t, []Reference{0xa, 0xaa, 0xaaa, 0xffff, 0xffff, 0xa, 0xffff, 0xaaa, 0xffff, 0xffff},
m.Tables[0].References)

View File

@@ -124,42 +124,15 @@ type ElementInstance struct {
// Reference is the runtime representation of RefType which is either RefTypeFuncref or RefTypeExternref.
type Reference = uintptr
// validatedActiveElementSegment is like ElementSegment of active mode except the inputs are expanded and validated based on defining module.
//
// Note: The global imported at globalIdx may have an offset value that is out-of-bounds for the corresponding table.
type validatedActiveElementSegment struct {
// opcode is OpcodeGlobalGet or OpcodeI32Const
opcode Opcode
// arg is the only argument to opcode, which when applied results in the offset to add to init indices.
// * OpcodeGlobalGet: position in the global index of an imported Global ValueTypeI32 holding the offset.
// * OpcodeI32Const: a constant ValueTypeI32 offset.
arg uint32
// init are a range of table elements whose values are positions in the function index. This range
// replaces any values in TableInstance.Table at an offset arg which is a constant if opcode == OpcodeI32Const or
// derived from a globalIdx if opcode == OpcodeGlobalGet
init []Index
// tableIndex is the table's index to which this active element will be applied.
tableIndex Index
}
// validateTable ensures any ElementSegment is valid. This caches results via Module.validatedActiveElementSegments.
// Note: limitsType are validated by decoders, so not re-validated here.
func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) ([]validatedActiveElementSegment, error) {
func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) error {
if len(tables) > int(maximumTableIndex) {
return nil, fmt.Errorf("too many tables in a module: %d given with limit %d", len(tables), maximumTableIndex)
}
if m.validatedActiveElementSegments != nil {
return m.validatedActiveElementSegments, nil
return fmt.Errorf("too many tables in a module: %d given with limit %d", len(tables), maximumTableIndex)
}
importedTableCount := m.ImportTableCount
ret := make([]validatedActiveElementSegment, 0, m.SectionElementCount(SectionIDElement))
// Create bounds checks as these can err prior to instantiation
funcCount := m.ImportFunctionCount + m.SectionElementCount(SectionIDFunction)
@@ -174,25 +147,25 @@ func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table,
// Any offset applied is to the element, not the function index: validate here if the funcidx is sound.
for ei, funcIdx := range elem.Init {
if funcIdx != ElementInitNullReference && funcIdx >= funcCount {
return nil, fmt.Errorf("%s[%d].init[%d] funcidx %d out of range", SectionIDName(SectionIDElement), idx, ei, funcIdx)
return fmt.Errorf("%s[%d].init[%d] funcidx %d out of range", SectionIDName(SectionIDElement), idx, ei, funcIdx)
}
}
} else {
for j, elem := range elem.Init {
if elem != ElementInitNullReference {
return nil, fmt.Errorf("%s[%d].init[%d] must be ref.null but was %v", SectionIDName(SectionIDElement), idx, j, elem)
return fmt.Errorf("%s[%d].init[%d] must be ref.null but was %v", SectionIDName(SectionIDElement), idx, j, elem)
}
}
}
if elem.IsActive() {
if len(tables) <= int(elem.TableIndex) {
return nil, fmt.Errorf("unknown table %d as active element target", elem.TableIndex)
return fmt.Errorf("unknown table %d as active element target", elem.TableIndex)
}
t := tables[elem.TableIndex]
if t.Type != elem.Type {
return nil, fmt.Errorf("element type mismatch: table has %s but element has %s",
return fmt.Errorf("element type mismatch: table has %s but element has %s",
RefTypeName(t.Type), RefTypeName(elem.Type),
)
}
@@ -202,46 +175,31 @@ func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table,
if oc == OpcodeGlobalGet {
globalIdx, _, err := leb128.LoadUint32(elem.OffsetExpr.Data)
if err != nil {
return nil, fmt.Errorf("%s[%d] couldn't read global.get parameter: %w", SectionIDName(SectionIDElement), idx, err)
return fmt.Errorf("%s[%d] couldn't read global.get parameter: %w", SectionIDName(SectionIDElement), idx, err)
} else if err = m.verifyImportGlobalI32(SectionIDElement, idx, globalIdx); err != nil {
return nil, err
return err
}
if initCount == 0 {
continue // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op, but validate anyway!
}
ret = append(ret, validatedActiveElementSegment{opcode: oc, arg: globalIdx, init: elem.Init, tableIndex: elem.TableIndex})
} else if oc == OpcodeI32Const {
// Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
o, _, err := leb128.LoadInt32(elem.OffsetExpr.Data)
if err != nil {
return nil, fmt.Errorf("%s[%d] couldn't read i32.const parameter: %w", SectionIDName(SectionIDElement), idx, err)
}
offset := Index(o)
// Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 we must pass if imported
// table has set its min=0. Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142, we
// have to do fail if module-defined min=0.
if !enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) && elem.TableIndex >= importedTableCount {
// Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
o, _, err := leb128.LoadInt32(elem.OffsetExpr.Data)
if err != nil {
return fmt.Errorf("%s[%d] couldn't read i32.const parameter: %w", SectionIDName(SectionIDElement), idx, err)
}
offset := Index(o)
if err = checkSegmentBounds(t.Min, uint64(initCount)+uint64(offset), idx); err != nil {
return nil, err
return err
}
}
if initCount == 0 {
continue // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op, but validate anyway!
}
ret = append(ret, validatedActiveElementSegment{opcode: oc, arg: offset, init: elem.Init, tableIndex: elem.TableIndex})
} else {
return nil, fmt.Errorf("%s[%d] has an invalid const expression: %s", SectionIDName(SectionIDElement), idx, InstructionName(oc))
return fmt.Errorf("%s[%d] has an invalid const expression: %s", SectionIDName(SectionIDElement), idx, InstructionName(oc))
}
}
}
m.validatedActiveElementSegments = ret
return ret, nil
return nil
}
// buildTable returns TableInstances if the module defines or imports a table.
@@ -263,25 +221,24 @@ func (m *ModuleInstance) buildTables(module *Module, skipBoundCheck bool) (err e
idx++
}
elementSegments := module.validatedActiveElementSegments
if len(elementSegments) == 0 {
return
}
if !skipBoundCheck {
for elemI := range elementSegments { // Do not loop over the value since elementSegments is a slice of value.
elem := &elementSegments[elemI]
table := m.Tables[elem.tableIndex]
for elemI := range module.ElementSection { // Do not loop over the value since elementSegments is a slice of value.
elem := &module.ElementSection[elemI]
table := m.Tables[elem.TableIndex]
var offset uint32
if elem.opcode == OpcodeGlobalGet {
global := m.Globals[elem.arg]
if elem.OffsetExpr.Opcode == OpcodeGlobalGet {
// Ignore error as it's already validated.
globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data)
global := m.Globals[globalIdx]
offset = uint32(global.Val)
} else {
offset = elem.arg // constant
} else { // i32.const
// Ignore error as it's already validated.
o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data)
offset = uint32(o)
}
// Check to see if we are out-of-bounds
initCount := uint64(len(elem.init))
initCount := uint64(len(elem.Init))
if err = checkSegmentBounds(table.Min, uint64(offset)+initCount, Index(elemI)); err != nil {
return
}

View File

@@ -83,29 +83,24 @@ func TestModule_validateTable(t *testing.T) {
const maxTableIndex = 5
three := uint32(3)
tests := []struct {
name string
input *Module
expected []validatedActiveElementSegment
name string
input *Module
}{
{
name: "empty",
input: &Module{},
expected: []validatedActiveElementSegment{},
name: "empty",
input: &Module{},
},
{
name: "min zero",
input: &Module{TableSection: []Table{{}}},
expected: []validatedActiveElementSegment{},
name: "min zero",
input: &Module{TableSection: []Table{{}}},
},
{
name: "maximum number of tables",
input: &Module{TableSection: []Table{{}, {}, {}, {}, {}}},
expected: []validatedActiveElementSegment{},
name: "maximum number of tables",
input: &Module{TableSection: []Table{{}, {}, {}, {}, {}}},
},
{
name: "min/max",
input: &Module{TableSection: []Table{{Min: 1, Max: &three}}},
expected: []validatedActiveElementSegment{},
name: "min/max",
input: &Module{TableSection: []Table{{Min: 1, Max: &three}}},
},
{ // See: https://github.com/WebAssembly/spec/issues/1427
name: "constant derived element offset=0 and no index",
@@ -121,7 +116,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{},
},
{
name: "constant derived element offset=0 and one index",
@@ -138,9 +132,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
},
},
{
name: "constant derived element offset - ignores min on imported table",
@@ -158,9 +149,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
},
},
{
name: "constant derived element offset=0 and one index - imported table",
@@ -177,9 +165,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
},
},
{
name: "constant derived element offset and two indices",
@@ -196,9 +181,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 1, init: []Index{0, 2}},
},
},
{ // See: https://github.com/WebAssembly/spec/issues/1427
name: "imported global derived element offset and no index",
@@ -217,7 +199,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{},
},
{
name: "imported global derived element offset and one index",
@@ -237,9 +218,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
},
},
{
name: "imported global derived element offset and one index - imported table",
@@ -259,9 +237,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
},
},
{
name: "imported global derived element offset - ignores min on imported table",
@@ -281,9 +256,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
},
},
{
name: "imported global derived element offset - two indices",
@@ -304,9 +276,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 1, init: []Index{0, 2}},
},
},
{
name: "mixed elementSegments - const before imported global",
@@ -332,10 +301,6 @@ func TestModule_validateTable(t *testing.T) {
},
},
},
expected: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 1, init: []Index{0, 2}},
{opcode: OpcodeGlobalGet, arg: 1, init: []Index{1, 2}},
},
},
}
@@ -346,15 +311,11 @@ func TestModule_validateTable(t *testing.T) {
_, _, _, tables, err := tc.input.AllDeclarations()
require.NoError(t, err)
vt, err := tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
err = tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
require.NoError(t, err)
require.Equal(t, tc.expected, vt)
// Ensure it was cached. We have to use Equal not Same because this is a slice, not a pointer.
require.Equal(t, vt, tc.input.validatedActiveElementSegments)
vt2, err := tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
err = tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
require.NoError(t, err)
require.Equal(t, vt, vt2)
})
}
}
@@ -681,7 +642,7 @@ func TestModule_validateTable_Errors(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
_, _, _, tables, err := tc.input.AllDeclarations()
require.NoError(t, err)
_, err = tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
err = tc.input.validateTable(api.CoreFeaturesV1, tables, maxTableIndex)
require.EqualError(t, err, tc.expectedErr)
})
}
@@ -704,33 +665,33 @@ func TestModule_buildTables(t *testing.T) {
{
name: "empty",
module: &Module{
validatedActiveElementSegments: []validatedActiveElementSegment{},
ElementSection: []ElementSegment{},
},
},
{
name: "min zero",
module: &Module{
TableSection: []Table{{Type: RefTypeFuncref}},
validatedActiveElementSegments: []validatedActiveElementSegment{},
TableSection: []Table{{Type: RefTypeFuncref}},
ElementSection: []ElementSegment{},
},
expectedTables: []*TableInstance{{References: make([]Reference, 0), Min: 0, Type: RefTypeFuncref}},
},
{
name: "min/max",
module: &Module{
TableSection: []Table{{Min: 1, Max: &three}},
validatedActiveElementSegments: []validatedActiveElementSegment{},
TableSection: []Table{{Min: 1, Max: &three}},
ElementSection: []ElementSegment{},
},
expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1, Max: &three}},
},
{ // See: https://github.com/WebAssembly/spec/issues/1427
name: "constant derived element offset=0 and no index",
module: &Module{
TypeSection: []FunctionType{{}},
TableSection: []Table{{Min: 1}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{},
TypeSection: []FunctionType{{}},
TableSection: []Table{{Min: 1}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
ElementSection: []ElementSegment{},
},
expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1}},
},
@@ -738,8 +699,8 @@ func TestModule_buildTables(t *testing.T) {
name: "null extern refs",
module: &Module{
TableSection: []Table{{Min: 10, Type: RefTypeExternref}},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 5, init: []Index{ElementInitNullReference, ElementInitNullReference, ElementInitNullReference}}, // three null refs.
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{5}}, Init: []Index{ElementInitNullReference, ElementInitNullReference, ElementInitNullReference}}, // three null refs.
},
},
expectedTables: []*TableInstance{{References: make([]Reference, 10), Min: 10, Type: RefTypeExternref}},
@@ -751,8 +712,8 @@ func TestModule_buildTables(t *testing.T) {
TableSection: []Table{{Min: 1}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1}},
@@ -763,8 +724,8 @@ func TestModule_buildTables(t *testing.T) {
TypeSection: []FunctionType{{}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
importedTables: []*TableInstance{{Min: 2}},
@@ -777,8 +738,8 @@ func TestModule_buildTables(t *testing.T) {
ImportSection: []Import{{Type: ExternTypeTable, DescTable: Table{Min: 1}}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
importedTables: []*TableInstance{{Min: 1}},
@@ -791,8 +752,8 @@ func TestModule_buildTables(t *testing.T) {
TableSection: []Table{{Min: 3}},
FunctionSection: []Index{0, 0, 0, 0},
CodeSection: []Code{codeEnd, codeEnd, codeEnd, codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 1, init: []Index{0, 2}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{1}}, Init: []Index{0, 2}},
},
},
expectedTables: []*TableInstance{{References: make([]Reference, 3), Min: 3}},
@@ -804,10 +765,10 @@ func TestModule_buildTables(t *testing.T) {
ImportSection: []Import{
{Type: ExternTypeGlobal, DescGlobal: GlobalType{ValType: ValueTypeI32}},
},
TableSection: []Table{{Min: 1}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{},
TableSection: []Table{{Min: 1}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
ElementSection: []ElementSegment{},
},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 1}},
expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1}},
@@ -822,8 +783,8 @@ func TestModule_buildTables(t *testing.T) {
TableSection: []Table{{Min: 2}},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 1}},
@@ -839,8 +800,8 @@ func TestModule_buildTables(t *testing.T) {
},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 1}},
@@ -857,8 +818,8 @@ func TestModule_buildTables(t *testing.T) {
},
FunctionSection: []Index{0},
CodeSection: []Code{codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0}}, Init: []Index{0}},
},
},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 1}},
@@ -888,10 +849,6 @@ func TestModule_buildTables(t *testing.T) {
TableIndex: 0,
},
},
validatedActiveElementSegments: []validatedActiveElementSegment{
{tableIndex: 1, opcode: OpcodeGlobalGet, arg: 0, init: []Index{ElementInitNullReference, 2}},
{tableIndex: 0, opcode: OpcodeGlobalGet, arg: 1, init: []Index{0, 2}},
},
},
importedGlobals: []*GlobalInstance{
{Type: GlobalType{ValType: ValueTypeI64}, Val: 3},
@@ -913,9 +870,9 @@ func TestModule_buildTables(t *testing.T) {
TableSection: []Table{{Min: 3}},
FunctionSection: []Index{0, 0, 0, 0},
CodeSection: []Code{codeEnd, codeEnd, codeEnd, codeEnd},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 1, init: []Index{0, 2}},
{opcode: OpcodeGlobalGet, arg: 1, init: []Index{1, 2}},
ElementSection: []ElementSegment{
{OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{1}}, Init: []Index{0, 2}},
{OffsetExpr: ConstantExpression{Opcode: OpcodeGlobalGet, Data: []byte{1}}, Init: []Index{1, 2}},
},
},
importedGlobals: []*GlobalInstance{
@@ -960,13 +917,10 @@ func TestModule_buildTable_Errors(t *testing.T) {
CodeSection: []Code{codeEnd},
ElementSection: []ElementSegment{
{
OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: const0},
OffsetExpr: ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{2}},
Init: []Index{0},
},
},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeI32Const, arg: 2, init: []Index{0}},
},
},
importedTables: []*TableInstance{{References: make([]Reference, 2), Min: 2}},
expectedErr: "element[0].init exceeds min table size",
@@ -987,9 +941,6 @@ func TestModule_buildTable_Errors(t *testing.T) {
Init: []Index{0},
},
},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
},
},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 2}},
expectedErr: "element[0].init exceeds min table size",
@@ -1011,9 +962,6 @@ func TestModule_buildTable_Errors(t *testing.T) {
Init: []Index{0},
},
},
validatedActiveElementSegments: []validatedActiveElementSegment{
{opcode: OpcodeGlobalGet, arg: 0, init: []Index{0}},
},
},
importedTables: []*TableInstance{{References: make([]Reference, 2), Min: 2}},
importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 2}},