diff --git a/wasm/binary/decoder.go b/wasm/binary/decoder.go index 0ae26ec4ce..d1af58a1c7 100644 --- a/wasm/binary/decoder.go +++ b/wasm/binary/decoder.go @@ -29,8 +29,8 @@ func DecodeModule(binary []byte) (*wasm.Module, error) { for { // TODO: except custom sections, all others are required to be in order, but we aren't checking yet. // See https://www.w3.org/TR/wasm-core-1/#modules%E2%91%A0%E2%93%AA - sectionID := make([]byte, 1) - if _, err := io.ReadFull(r, sectionID); err == io.EOF { + sectionID, err := r.ReadByte() + if err == io.EOF { break } else if err != nil { return nil, fmt.Errorf("read section id: %w", err) @@ -38,11 +38,11 @@ func DecodeModule(binary []byte) (*wasm.Module, error) { sectionSize, _, err := leb128.DecodeUint32(r) if err != nil { - return nil, fmt.Errorf("get size of section %s: %v", wasm.SectionIDName(sectionID[0]), err) + return nil, fmt.Errorf("get size of section %s: %v", wasm.SectionIDName(sectionID), err) } sectionContentStart := r.Len() - switch sectionID[0] { + switch sectionID { case wasm.SectionIDCustom: // First, validate the section and determine if the section for this name has already been set name, nameSize, decodeErr := decodeUTF8(r, "custom section name") @@ -55,25 +55,19 @@ func DecodeModule(binary []byte) (*wasm.Module, error) { } else if name == "name" && m.NameSection != nil { err = fmt.Errorf("redundant custom section %s", name) break - } else if _, ok := m.CustomSections[name]; ok { - err = fmt.Errorf("redundant custom section %s", name) - break } - // Now, either decode the NameSection or store an unsupported one - // TODO: Do we care to store something we don't use? We could also skip it! - data, dataErr := readCustomSectionData(r, sectionSize-nameSize) - if dataErr != nil { - err = dataErr - } else if name == "name" { - m.NameSection, err = decodeNameSection(data) + // Now, either decode the NameSection or skip an unsupported one + limit := sectionSize - nameSize + if name == "name" { + m.NameSection, err = decodeNameSection(r, uint64(limit)) } else { - if m.CustomSections == nil { - m.CustomSections = map[string][]byte{name: data} - } else { - m.CustomSections[name] = data + // Note: Not Seek because it doesn't err when given an offset past EOF. Rather, it leads to undefined state. + if _, err = io.CopyN(io.Discard, r, int64(limit)); err != nil { + return nil, fmt.Errorf("failed to skip name[%s]: %w", name, err) } } + case wasm.SectionIDType: m.TypeSection, err = decodeTypeSection(r) case wasm.SectionIDImport: @@ -106,11 +100,11 @@ func DecodeModule(binary []byte) (*wasm.Module, error) { } if err != nil { - return nil, fmt.Errorf("section %s: %v", wasm.SectionIDName(sectionID[0]), err) + return nil, fmt.Errorf("section %s: %v", wasm.SectionIDName(sectionID), err) } } - functionCount, codeCount := m.SectionSize(wasm.SectionIDFunction), m.SectionSize(wasm.SectionIDCode) + functionCount, codeCount := m.SectionElementCount(wasm.SectionIDFunction), m.SectionElementCount(wasm.SectionIDCode) if functionCount != codeCount { return nil, fmt.Errorf("function and code section have inconsistent lengths: %d != %d", functionCount, codeCount) } diff --git a/wasm/binary/decoder_test.go b/wasm/binary/decoder_test.go index 813d801ca9..9ab47ce875 100644 --- a/wasm/binary/decoder_test.go +++ b/wasm/binary/decoder_test.go @@ -26,21 +26,6 @@ func TestDecodeModule(t *testing.T) { name: "only name section", input: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "simple"}}, }, - { - name: "only custom section", - input: &wasm.Module{CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }}, - }, - { - name: "name section and a custom section", - input: &wasm.Module{ - NameSection: &wasm.NameSection{ModuleName: "simple"}, - CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }, - }, - }, { name: "type section", input: &wasm.Module{ @@ -107,6 +92,29 @@ func TestDecodeModule(t *testing.T) { require.Equal(t, tc.input, m) }) } + t.Run("skips custom section", func(t *testing.T) { + input := append(append(magic, version...), + wasm.SectionIDCustom, 0xf, // 15 bytes in this section + 0x04, 'm', 'e', 'm', 'e', + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0) + m, e := DecodeModule(input) + require.NoError(t, e) + require.Equal(t, &wasm.Module{}, m) + }) + t.Run("skips custom section, but not name", func(t *testing.T) { + input := append(append(magic, version...), + wasm.SectionIDCustom, 0xf, // 15 bytes in this section + 0x04, 'm', 'e', 'm', 'e', + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + wasm.SectionIDCustom, 0x0e, // 14 bytes in this section + 0x04, 'n', 'a', 'm', 'e', + subsectionIDModuleName, 0x07, // 7 bytes in this subsection + 0x06, // the Module name simple is 6 bytes long + 's', 'i', 'm', 'p', 'l', 'e') + m, e := DecodeModule(input) + require.NoError(t, e) + require.Equal(t, &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "simple"}}, m) + }) } func TestDecodeModule_Errors(t *testing.T) { @@ -125,26 +133,15 @@ func TestDecodeModule_Errors(t *testing.T) { input: []byte("\x00asm\x01\x00\x00\x01"), expectedErr: "invalid version header", }, - { - name: "redundant custom section", - input: append(append(magic, version...), - wasm.SectionIDCustom, 0x09, // 9 bytes in this section - 0x04, 'm', 'e', 'm', 'e', - subsectionIDModuleName, 0x03, 0x01, 'x', - wasm.SectionIDCustom, 0x09, // 9 bytes in this section - 0x04, 'm', 'e', 'm', 'e', - subsectionIDModuleName, 0x03, 0x01, 'y'), - expectedErr: "section custom: redundant custom section meme", - }, { name: "redundant name section", input: append(append(magic, version...), wasm.SectionIDCustom, 0x09, // 9 bytes in this section 0x04, 'n', 'a', 'm', 'e', - subsectionIDModuleName, 0x03, 0x01, 'x', + subsectionIDModuleName, 0x02, 0x01, 'x', wasm.SectionIDCustom, 0x09, // 9 bytes in this section 0x04, 'n', 'a', 'm', 'e', - subsectionIDModuleName, 0x03, 0x01, 'x'), + subsectionIDModuleName, 0x02, 0x01, 'x'), expectedErr: "section custom: redundant custom section name", }, } diff --git a/wasm/binary/encoder.go b/wasm/binary/encoder.go index 54417a3509..3db533cb67 100644 --- a/wasm/binary/encoder.go +++ b/wasm/binary/encoder.go @@ -11,44 +11,40 @@ var sizePrefixedName = []byte{4, 'n', 'a', 'm', 'e'} // See https://www.w3.org/TR/wasm-core-1/#binary-format%E2%91%A0 func EncodeModule(m *wasm.Module) (bytes []byte) { bytes = append(magic, version...) - if m.SectionSize(wasm.SectionIDType) > 0 { + if m.SectionElementCount(wasm.SectionIDType) > 0 { bytes = append(bytes, encodeTypeSection(m.TypeSection)...) } - if m.SectionSize(wasm.SectionIDImport) > 0 { + if m.SectionElementCount(wasm.SectionIDImport) > 0 { bytes = append(bytes, encodeImportSection(m.ImportSection)...) } - if m.SectionSize(wasm.SectionIDFunction) > 0 { + if m.SectionElementCount(wasm.SectionIDFunction) > 0 { bytes = append(bytes, encodeFunctionSection(m.FunctionSection)...) } - if m.SectionSize(wasm.SectionIDTable) > 0 { + if m.SectionElementCount(wasm.SectionIDTable) > 0 { panic("TODO: TableSection") } - if m.SectionSize(wasm.SectionIDMemory) > 0 { + if m.SectionElementCount(wasm.SectionIDMemory) > 0 { bytes = append(bytes, encodeMemorySection(m.MemorySection)...) } - if m.SectionSize(wasm.SectionIDGlobal) > 0 { + if m.SectionElementCount(wasm.SectionIDGlobal) > 0 { panic("TODO: GlobalSection") } - if m.SectionSize(wasm.SectionIDExport) > 0 { + if m.SectionElementCount(wasm.SectionIDExport) > 0 { bytes = append(bytes, encodeExportSection(m.ExportSection)...) } - if m.SectionSize(wasm.SectionIDStart) > 0 { + if m.SectionElementCount(wasm.SectionIDStart) > 0 { bytes = append(bytes, encodeStartSection(*m.StartSection)...) } - if m.SectionSize(wasm.SectionIDElement) > 0 { + if m.SectionElementCount(wasm.SectionIDElement) > 0 { panic("TODO: ElementSection") } - if m.SectionSize(wasm.SectionIDCode) > 0 { + if m.SectionElementCount(wasm.SectionIDCode) > 0 { bytes = append(bytes, encodeCodeSection(m.CodeSection)...) } - if m.SectionSize(wasm.SectionIDData) > 0 { + if m.SectionElementCount(wasm.SectionIDData) > 0 { panic("TODO: DataSection") } - if m.SectionSize(wasm.SectionIDCustom) > 0 { - for name, data := range m.CustomSections { - bytes = append(bytes, encodeCustomSection(name, data)...) - } - + if m.SectionElementCount(wasm.SectionIDCustom) > 0 { // >> The name section should appear only once in a module, and only after the data section. // See https://www.w3.org/TR/wasm-core-1/#binary-namesec if m.NameSection != nil { diff --git a/wasm/binary/encoder_test.go b/wasm/binary/encoder_test.go index 903466b93b..6dc938b539 100644 --- a/wasm/binary/encoder_test.go +++ b/wasm/binary/encoder_test.go @@ -32,34 +32,6 @@ func TestModule_Encode(t *testing.T) { 0x06, // the Module name simple is 6 bytes long 's', 'i', 'm', 'p', 'l', 'e'), }, - { - name: "only custom section", - input: &wasm.Module{CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }}, - expected: append(append(magic, version...), - wasm.SectionIDCustom, 0xf, // 15 bytes in this section - 0x04, 'm', 'e', 'm', 'e', - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0), - }, - { - name: "name section and a custom section", // name should encode last - input: &wasm.Module{ - NameSection: &wasm.NameSection{ModuleName: "simple"}, - CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }, - }, - expected: append(append(magic, version...), - wasm.SectionIDCustom, 0xf, // 15 bytes in this section - 0x04, 'm', 'e', 'm', 'e', - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, - wasm.SectionIDCustom, 0x0e, // 14 bytes in this section - 0x04, 'n', 'a', 'm', 'e', - subsectionIDModuleName, 0x07, // 7 bytes in this subsection - 0x06, // the Module name simple is 6 bytes long - 's', 'i', 'm', 'p', 'l', 'e'), - }, { name: "type section", input: &wasm.Module{ diff --git a/wasm/binary/names.go b/wasm/binary/names.go index b9590522e6..dc64cdfd3e 100644 --- a/wasm/binary/names.go +++ b/wasm/binary/names.go @@ -27,17 +27,17 @@ const ( // * LocalNames decode from subsection 2 // // See https://www.w3.org/TR/wasm-core-1/#binary-namesec -func decodeNameSection(data []byte) (result *wasm.NameSection, err error) { +func decodeNameSection(r *bytes.Reader, limit uint64) (result *wasm.NameSection, err error) { // TODO: add leb128 functions that work on []byte and offset. While using a reader allows us to reuse reader-based // leb128 functions, it is less efficient, causes untestable code and in some cases more complex vs plain []byte. - r := bytes.NewReader(data) result = &wasm.NameSection{} // subsectionID is decoded if known, and skipped if not var subsectionID uint8 // subsectionSize is the length to skip when the subsectionID is unknown var subsectionSize uint32 - for { + var bytesRead uint64 + for limit > 0 { if subsectionID, err = r.ReadByte(); err != nil { if err == io.EOF { return result, nil @@ -45,11 +45,12 @@ func decodeNameSection(data []byte) (result *wasm.NameSection, err error) { // TODO: untestable as this can't fail for a reason beside EOF reading a byte from a buffer return nil, fmt.Errorf("failed to read a subsection ID: %w", err) } + limit-- - // TODO: unused except when skipping. This means we can pass on a corrupt length of a known subsection - if subsectionSize, _, err = leb128.DecodeUint32(r); err != nil { + if subsectionSize, bytesRead, err = leb128.DecodeUint32(r); err != nil { return nil, fmt.Errorf("failed to read the size of subsection[%d]: %w", subsectionID, err) } + limit -= bytesRead switch subsectionID { case subsectionIDModuleName: @@ -66,11 +67,13 @@ func decodeNameSection(data []byte) (result *wasm.NameSection, err error) { } default: // Skip other subsections. // Note: Not Seek because it doesn't err when given an offset past EOF. Rather, it leads to undefined state. - if _, err := io.CopyN(io.Discard, r, int64(subsectionSize)); err != nil { + if _, err = io.CopyN(io.Discard, r, int64(subsectionSize)); err != nil { return nil, fmt.Errorf("failed to skip subsection[%d]: %w", subsectionID, err) } } + limit -= uint64(subsectionSize) } + return } func decodeFunctionNames(r *bytes.Reader) (wasm.NameMap, error) { diff --git a/wasm/binary/names_test.go b/wasm/binary/names_test.go index d148b7cb47..0cf3450524 100644 --- a/wasm/binary/names_test.go +++ b/wasm/binary/names_test.go @@ -1,6 +1,7 @@ package binary import ( + "bytes" "testing" "github.com/stretchr/testify/require" @@ -201,7 +202,8 @@ func TestDecodeNameSection(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - ns, err := decodeNameSection(encodeNameSectionData(tc.input)) + data := encodeNameSectionData(tc.input) + ns, err := decodeNameSection(bytes.NewReader(data), uint64(len(data))) require.NoError(t, err) require.Equal(t, tc.input, ns) }) @@ -302,7 +304,7 @@ func TestDecodeNameSection_Errors(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - _, err := decodeNameSection(tc.input) + _, err := decodeNameSection(bytes.NewReader(tc.input), uint64(len(tc.input))) require.EqualError(t, err, tc.expectedErr) }) } diff --git a/wasm/binary/section.go b/wasm/binary/section.go index e117a6b61d..7c587f977b 100644 --- a/wasm/binary/section.go +++ b/wasm/binary/section.go @@ -9,14 +9,6 @@ import ( "github.com/tetratelabs/wazero/wasm/internal/leb128" ) -func readCustomSectionData(r *bytes.Reader, dataSize uint32) ([]byte, error) { - data := make([]byte, dataSize) - if _, err := io.ReadFull(r, data); err != nil { - return nil, fmt.Errorf("cannot read custom section data: %w", err) - } - return data, nil -} - func decodeTypeSection(r io.Reader) ([]*wasm.FunctionType, error) { vs, _, err := leb128.DecodeUint32(r) if err != nil { @@ -218,14 +210,6 @@ func decodeDataSection(r *bytes.Reader) ([]*wasm.DataSegment, error) { return result, nil } -// encodeCustomSection encodes the opaque bytes for the given name as a SectionIDCustom -// See https://www.w3.org/TR/wasm-core-1/#binary-customsec -func encodeCustomSection(name string, data []byte) []byte { - // The contents of a custom section is the non-empty name followed by potentially empty opaque data - contents := append(encodeSizePrefixed([]byte(name)), data...) - return encodeSection(wasm.SectionIDCustom, contents) -} - // encodeSection encodes the sectionID, the size of its contents in bytes, followed by the contents. // See https://www.w3.org/TR/wasm-core-1/#sections%E2%91%A0 func encodeSection(sectionID wasm.SectionID, contents []byte) []byte { diff --git a/wasm/module.go b/wasm/module.go index 33e5953c78..2965fe93c0 100644 --- a/wasm/module.go +++ b/wasm/module.go @@ -92,6 +92,7 @@ type Module struct { // (Store.Instantiate). // // Note: there are no unique constraints relating to the two-level namespace of Import.Module and Import.Name. + // // Note: In the Binary Format, this is SectionIDImport. // // See https://www.w3.org/TR/wasm-core-1/#import-section%E2%91%A0 @@ -105,6 +106,7 @@ type Module struct { // // Note: FunctionSection is index correlated with the CodeSection. If given the same position, ex. 2, a function // type is at TypeSection[FunctionSection[2]], while its locals and body are at CodeSection[2]. + // // Note: In the Binary Format, this is SectionIDFunction. // // See https://www.w3.org/TR/wasm-core-1/#function-section%E2%91%A0 @@ -151,6 +153,8 @@ type Module struct { // ExportSection contains each export defined in this module. // + // Note: In the Binary Format, this is SectionIDExport. + // // See https://www.w3.org/TR/wasm-core-1/#exports%E2%91%A0 ExportSection map[string]*Export @@ -179,20 +183,12 @@ type Module struct { // NameSection is set when the SectionIDCustom "name" was successfully decoded from the binary format. // - // Note: This is the only SectionIDCustom defined in the WebAssembly 1.0 (MVP) Binary Format. Others are in - // CustomSections + // Note: This is the only SectionIDCustom defined in the WebAssembly 1.0 (MVP) Binary Format. + // Others are skipped as they are not used in wazero. // // See https://www.w3.org/TR/wasm-core-1/#name-section%E2%91%A0 - NameSection *NameSection - - // CustomSections is set when at least one non-standard, or otherwise unsupported custom section was found in the - // binary format. - // - // Note: This never contains a "name" because that is standard and parsed into the NameSection. - // Note: In the Binary Format, this is SectionIDCode. - // // See https://www.w3.org/TR/wasm-core-1/#custom-section%E2%91%A0 - CustomSections map[string][]byte + NameSection *NameSection } // Index is the offset in an index namespace, not necessarily an absolute position in a Module section. This is because @@ -467,20 +463,19 @@ func (m *Module) allDeclarations() (functions []Index, globals []*GlobalType, me return } -// SectionSize returns the count of items for a given section ID +// SectionElementCount returns the count of elements in a given section ID // -// For example, given... -// * SectionIDType this returns the count of FunctionType -// * SectionIDCustom this returns the count of unique section names -// * SectionIDExport this returns the count of unique export names -func (m *Module) SectionSize(sectionID SectionID) uint32 { +// For example... +// * SectionIDType returns the count of FunctionType +// * SectionIDCustom returns one if the NameSection is present +// * SectionIDExport returns the count of unique export names +func (m *Module) SectionElementCount(sectionID SectionID) uint32 { // element as in vector elements! switch sectionID { case SectionIDCustom: - count := uint32(len(m.CustomSections)) if m.NameSection != nil { - return count + 1 + return 1 } - return count + return 0 case SectionIDType: return uint32(len(m.TypeSection)) case SectionIDImport: diff --git a/wasm/module_test.go b/wasm/module_test.go index ad558122a6..13a463adc2 100644 --- a/wasm/module_test.go +++ b/wasm/module_test.go @@ -224,23 +224,6 @@ func TestModule_SectionSize(t *testing.T) { input: &Module{NameSection: &NameSection{ModuleName: "simple"}}, expected: map[string]uint32{"custom": 1}, }, - { - name: "only custom section", - input: &Module{CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }}, - expected: map[string]uint32{"custom": 1}, - }, - { - name: "name section and a custom section", - input: &Module{ - NameSection: &NameSection{ModuleName: "simple"}, - CustomSections: map[string][]byte{ - "meme": {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - }, - }, - expected: map[string]uint32{"custom": 2}, - }, { name: "type section", input: &Module{ @@ -312,7 +295,7 @@ func TestModule_SectionSize(t *testing.T) { t.Run(tc.name, func(t *testing.T) { actual := map[string]uint32{} for i := SectionID(0); i <= SectionIDData; i++ { - if size := tc.input.SectionSize(i); size > 0 { + if size := tc.input.SectionElementCount(i); size > 0 { actual[SectionIDName(i)] = size } } diff --git a/wasm/store.go b/wasm/store.go index 0732111fd4..3771303c0a 100644 --- a/wasm/store.go +++ b/wasm/store.go @@ -288,7 +288,7 @@ func (s *Store) Instantiate(module *Module, name string) error { for i, f := range instance.Functions { if err := s.engine.Compile(f); err != nil { - idx := module.SectionSize(SectionIDFunction) - 1 + idx := module.SectionElementCount(SectionIDFunction) - 1 return fmt.Errorf("compilation failed at index %d/%d: %v", i, idx, err) } } @@ -598,9 +598,9 @@ func (s *Store) buildFunctionInstances(module *Module, target *ModuleInstance) ( n, nLen := 0, len(functionNames) for codeIndex, typeIndex := range module.FunctionSection { - if typeIndex >= module.SectionSize(SectionIDType) { + if typeIndex >= module.SectionElementCount(SectionIDType) { return rollbackFuncs, fmt.Errorf("function type index out of range") - } else if uint32(codeIndex) >= module.SectionSize(SectionIDCode) { + } else if uint32(codeIndex) >= module.SectionElementCount(SectionIDCode) { return rollbackFuncs, fmt.Errorf("code index out of range") } @@ -631,7 +631,7 @@ func (s *Store) buildFunctionInstances(module *Module, target *ModuleInstance) ( } if err := validateFunctionInstance(f, funcs, globals, mems, tables, module.TypeSection, maximumValuesOnStack); err != nil { - idx := module.SectionSize(SectionIDFunction) - 1 + idx := module.SectionElementCount(SectionIDFunction) - 1 return rollbackFuncs, fmt.Errorf("invalid function '%s' (%d/%d): %v", f.Name, codeIndex, idx, err) } @@ -684,7 +684,7 @@ func (s *Store) buildMemoryInstances(module *Module, target *ModuleInstance) (ro size := uint64(offset) + uint64(len(d.Init)) maxPage := MemoryMaxPages - if d.MemoryIndex < module.SectionSize(SectionIDMemory) && module.MemorySection[d.MemoryIndex].Max != nil { + if d.MemoryIndex < module.SectionElementCount(SectionIDMemory) && module.MemorySection[d.MemoryIndex].Max != nil { maxPage = *module.MemorySection[d.MemoryIndex].Max } if size > memoryPagesToBytesNum(maxPage) { @@ -737,7 +737,7 @@ func (s *Store) buildTableInstances(module *Module, target *ModuleInstance) (rol size := offset + len(elem.Init) max := uint32(math.MaxUint32) - if elem.TableIndex < module.SectionSize(SectionIDTable) && module.TableSection[elem.TableIndex].Limit.Max != nil { + if elem.TableIndex < module.SectionElementCount(SectionIDTable) && module.TableSection[elem.TableIndex].Limit.Max != nil { max = *module.TableSection[elem.TableIndex].Limit.Max } @@ -775,7 +775,7 @@ func (s *Store) buildTableInstances(module *Module, target *ModuleInstance) (rol } func (s *Store) buildExportInstances(module *Module, target *ModuleInstance) (rollbackFuncs []func(), err error) { - target.Exports = make(map[string]*ExportInstance, module.SectionSize(SectionIDExport)) + target.Exports = make(map[string]*ExportInstance, module.SectionElementCount(SectionIDExport)) for name, exp := range module.ExportSection { index := exp.Index var ei *ExportInstance diff --git a/wasm/text/decoder.go b/wasm/text/decoder.go index 7ee66b5e65..1d5f89d7a8 100644 --- a/wasm/text/decoder.go +++ b/wasm/text/decoder.go @@ -175,7 +175,7 @@ func (p *moduleParser) beginModuleField(tok tokenType, tokenBytes []byte, _, _ u return p.parseImportModule, nil case "func": p.pos = positionFunc - p.funcParser.currentIdx = p.module.SectionSize(wasm.SectionIDFunction) + p.funcParser.currentIdx = p.module.SectionElementCount(wasm.SectionIDFunction) return p.funcParser.begin, nil case "table": return nil, errors.New("TODO: table") @@ -191,7 +191,7 @@ func (p *moduleParser) beginModuleField(tok tokenType, tokenBytes []byte, _, _ u p.pos = positionExport return p.parseExportName, nil case "start": - if p.module.SectionSize(wasm.SectionIDStart) > 0 { + if p.module.SectionElementCount(wasm.SectionIDStart) > 0 { return nil, moreThanOneInvalid("start") } p.pos = positionStart @@ -310,7 +310,7 @@ func (p *moduleParser) beginImportDesc(tok tokenType, tokenBytes []byte, _, _ ui switch string(tokenBytes) { case "func": - if p.module.SectionSize(wasm.SectionIDFunction) > 0 { + if p.module.SectionElementCount(wasm.SectionIDFunction) > 0 { return nil, importAfterModuleDefined(wasm.SectionIDFunction) } p.pos = positionImportFunc @@ -361,7 +361,7 @@ func (p *moduleParser) addFunctionName(name string) { // Ex. If there is no signature `(import "" "main" (func))` // calls onImportFunc here ---^ func (p *moduleParser) parseImportFunc(tok tokenType, tokenBytes []byte, line, col uint32) (tokenParser, error) { - idx := p.module.SectionSize(wasm.SectionIDImport) + idx := p.module.SectionElementCount(wasm.SectionIDImport) if tok == tokenID { // Ex. (func $main $main) return nil, fmt.Errorf("redundant ID %s", tokenBytes) } @@ -520,7 +520,7 @@ func (p *moduleParser) parseExportDesc(tok tokenType, tokenBytes []byte, line, c default: panic(fmt.Errorf("BUG: unhandled parsing state on parseExportDesc: %v", p.pos)) } - eIdx := p.module.SectionSize(wasm.SectionIDExport) + eIdx := p.module.SectionElementCount(wasm.SectionIDExport) typeIdx, resolved, err := namespace.parseIndex(wasm.SectionIDExport, eIdx, 0, tok, tokenBytes, line, col) if err != nil { return nil, err @@ -730,22 +730,22 @@ func (p *moduleParser) errorContext() string { case positionModule: return "module" case positionType: - idx := p.module.SectionSize(wasm.SectionIDType) + idx := p.module.SectionElementCount(wasm.SectionIDType) return fmt.Sprintf("module.type[%d]%s", idx, p.typeParser.errorContext()) case positionImport, positionImportFunc: // TODO: table, memory or global - idx := p.module.SectionSize(wasm.SectionIDImport) + idx := p.module.SectionElementCount(wasm.SectionIDImport) if p.pos == positionImport { return fmt.Sprintf("module.import[%d]", idx) } return fmt.Sprintf("module.import[%d].func%s", idx, p.typeUseParser.errorContext()) case positionFunc: - idx := p.module.SectionSize(wasm.SectionIDFunction) + idx := p.module.SectionElementCount(wasm.SectionIDFunction) return fmt.Sprintf("module.func[%d]%s", idx, p.typeUseParser.errorContext()) case positionMemory: - idx := p.module.SectionSize(wasm.SectionIDMemory) + idx := p.module.SectionElementCount(wasm.SectionIDMemory) return fmt.Sprintf("module.memory[%d]", idx) case positionExport, positionExportFunc: // TODO: table, memory or global - idx := p.module.SectionSize(wasm.SectionIDExport) + idx := p.module.SectionElementCount(wasm.SectionIDExport) if p.pos == positionExport { return fmt.Sprintf("module.export[%d]", idx) }