parser.go raw
1 //go:generate stringer -trimprefix sec -type sectionID
2
3 package wasm
4
5 import (
6 "fmt"
7 "io"
8 "io/ioutil"
9 )
10
11 // magicnumber is a magic number which must appear as the very first bytes of a
12 // wasm file.
13 const magicnumber = 0x6d736100 // \0asm
14
15 type sectionID uint8
16
17 const (
18 secCustom sectionID = iota // 0x00
19 secType // 0x01
20 secImport // 0x02
21 secFunction // 0x03
22 secTable // 0x04
23 secMemory // 0x05
24 secGlobal // 0x06
25 secExport // 0x07
26 secStart // 0x08
27 secElement // 0x09
28 secCode // 0x0A
29 secData // 0x0B
30 secDataCount // 0x0C
31 )
32
33 type parser struct {
34 r *reader
35 }
36
37 var errDone = fmt.Errorf("done")
38
39 // Parse parses the input to a WASM module.
40 func Parse(r io.Reader) (*Module, error) {
41 p := &parser{
42 r: newReader(r),
43 }
44
45 if err := p.parsePreamble(); err != nil {
46 return nil, err
47 }
48
49 // Parse file sections
50 var m Module
51 for {
52 err := p.parseSection(&m.Sections)
53 if err != nil {
54 if err == errDone {
55 break
56 }
57 return nil, fmt.Errorf("[0x%06x] parse section: %v", p.r.Index(), err)
58 }
59 }
60 return &m, nil
61 }
62
63 func (p *parser) parsePreamble() error {
64 var h, v uint32
65 if err := read(p.r, &h); err != nil {
66 return fmt.Errorf("could not read file header")
67 }
68 if h != magicnumber {
69 return fmt.Errorf("not a wasm file")
70 }
71 if err := read(p.r, &v); err != nil {
72 return fmt.Errorf("could not version")
73 }
74 if v != 1 {
75 return fmt.Errorf("unsupported version %d", v)
76 }
77 return nil
78 }
79
80 func (p *parser) parseSection(ss *[]Section) error {
81 var i uint8
82 if err := readVarUint7(p.r, &i); err != nil {
83 if err == io.EOF {
84 return errDone
85 }
86 return fmt.Errorf("read section id: %v", err)
87 }
88 sid := sectionID(i)
89
90 var s Section
91 var err error
92
93 base := §ion{
94 id: sid,
95 name: sid.String(),
96 }
97
98 if err := readVarUint32(p.r, &base.size); err != nil {
99 return fmt.Errorf("read type section payload length: %v", err)
100 }
101
102 switch sid {
103 case secCustom:
104 s, err = p.parseCustomSection(base)
105 case secType:
106 s, err = p.parseTypeSection(base)
107 case secImport:
108 s, err = p.parseImportSection(base)
109 case secFunction:
110 s, err = p.parseFunctionSection(base)
111 case secTable:
112 s, err = p.parseTableSection(base)
113 case secMemory:
114 s, err = p.parseMemorySection(base)
115 case secGlobal:
116 s, err = p.parseGlobalSection(base)
117 case secExport:
118 s, err = p.parseExportSection(base)
119 case secStart:
120 s, err = p.parseStartSection(base)
121 case secElement:
122 s, err = p.parseElementSection(base)
123 case secCode:
124 s, err = p.parseCodeSection(base)
125 case secData:
126 s, err = p.parseDataSection(base)
127 case secDataCount:
128 s, err = p.parseDataCountSection(base)
129 default:
130 if _, err := io.CopyN(ioutil.Discard, p.r, int64(base.size)); err != nil {
131 return fmt.Errorf("discard section payload, %d bytes: %v", base.size, err)
132 }
133 if sid > secData {
134 // This happens if the previous section was not read to the end,
135 // indicating a bug in that section parser.
136 return fmt.Errorf("data corrupted; section id 0x%02x not valid", uint8(sid))
137 }
138 // Skip unknown section
139 return nil
140 }
141 if err != nil {
142 return err
143 }
144
145 if s != nil {
146 *ss = append(*ss, s)
147 }
148
149 return nil
150 }
151
152 func (p *parser) parseCustomSection(base *section) (Section, error) {
153 var nl uint32
154 if err := readVarUint32(p.r, &nl); err != nil {
155 return nil, fmt.Errorf("read section name length: %v", err)
156 }
157
158 b := make([]byte, nl)
159 if err := read(p.r, &b); err != nil {
160 return nil, fmt.Errorf("read section name: %v", err)
161 }
162 name := string(b)
163
164 base.size -= uint32(nl) // sizeof name
165 base.size -= uint32(varUint32Size(nl)) // sizeof name_len
166
167 if name == "name" {
168 // A name section is a special custom section meant for debugging
169 // purposes. It's defined in the spec so we'll parse it.
170 return p.parseNameSection(base, name, base.size)
171 }
172 if name == "linking" {
173 // A linking section is added to object files and used by the linker.
174 // It is defined here:
175 // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
176 return p.parseLinkingSection(base, name)
177 }
178
179 s := SectionCustom{
180 section: base,
181 SectionName: name,
182 }
183
184 // set raw bytes
185 s.Payload = make([]byte, base.size)
186 if err := read(p.r, s.Payload); err != nil {
187 return nil, fmt.Errorf("read custom section %#v payload: %v", name, err)
188 }
189
190 return &s, nil
191 }
192
193 func (p *parser) parseTypeSection(base *section) (*SectionType, error) {
194 s := SectionType{section: base}
195
196 err := p.loopCount(func() error {
197 var e FuncType
198
199 if err := readVarInt7(p.r, &e.Form); err != nil {
200 return fmt.Errorf("read form: %v", err)
201 }
202
203 p.loopCount(func() error {
204 var param int8
205 if err := readVarInt7(p.r, ¶m); err != nil {
206 return fmt.Errorf("read function param type: %v", err)
207 }
208 e.Params = append(e.Params, param)
209 return nil
210 })
211
212 var rc uint8
213 if err := readVarUint1(p.r, &rc); err != nil {
214 return fmt.Errorf("read number of returns from function: %v", err)
215 }
216 e.ReturnTypes = make([]int8, rc)
217 for i := range e.ReturnTypes {
218 if err := readVarInt7(p.r, &e.ReturnTypes[i]); err != nil {
219 return fmt.Errorf("read function return type: %v", err)
220 }
221 }
222
223 s.Entries = append(s.Entries, e)
224 return nil
225 })
226 if err != nil {
227 return nil, err
228 }
229
230 return &s, nil
231 }
232
233 func (p *parser) parseImportSection(base *section) (*SectionImport, error) {
234 s := SectionImport{section: base}
235
236 err := p.loopCount(func() error {
237 var e ImportEntry
238
239 var ml uint32
240 if err := readVarUint32(p.r, &ml); err != nil {
241 return fmt.Errorf("read module length: %v", err)
242 }
243
244 mn := make([]byte, ml)
245 if err := read(p.r, mn); err != nil {
246 return fmt.Errorf("read module name: %v", err)
247 }
248 e.Module = string(mn)
249
250 var fl uint32
251 if err := readVarUint32(p.r, &fl); err != nil {
252 return fmt.Errorf("read field length: %v", err)
253 }
254
255 fn := make([]byte, fl)
256 if err := read(p.r, fn); err != nil {
257 return fmt.Errorf("read field name")
258 }
259 e.Field = string(fn)
260
261 var kind uint8
262 if err := read(p.r, &kind); err != nil {
263 return fmt.Errorf("read kind: %v", err)
264 }
265 e.Kind = ExternalKind(kind)
266
267 switch e.Kind {
268 case ExtKindFunction:
269 e.FunctionType = &FunctionType{}
270 if err := readVarUint32(p.r, &e.FunctionType.Index); err != nil {
271 return fmt.Errorf("read function type index: %v", err)
272 }
273 case ExtKindTable:
274 e.TableType = &TableType{}
275 if err := readVarInt7(p.r, &e.TableType.ElemType); err != nil {
276 return fmt.Errorf("read table element type: %v", err)
277 }
278
279 if err := p.parseResizableLimits(&e.TableType.Limits); err != nil {
280 return fmt.Errorf("read table resizable limits: %v", err)
281 }
282 case ExtKindMemory:
283 e.MemoryType = &MemoryType{}
284 if err := p.parseResizableLimits(&e.MemoryType.Limits); err != nil {
285 return fmt.Errorf("read memory resizable limits: %v", err)
286 }
287 case ExtKindGlobal:
288 e.GlobalType = &GlobalType{}
289 if err := readVarInt7(p.r, &e.GlobalType.ContentType); err != nil {
290 return fmt.Errorf("read global content type: %v", err)
291 }
292
293 var m uint8
294 if err := readVarUint1(p.r, &m); err != nil {
295 return fmt.Errorf("read global mutability: %v", err)
296 }
297 e.GlobalType.Mutable = m == 1
298 }
299
300 s.Entries = append(s.Entries, e)
301 return nil
302 })
303 if err != nil {
304 return nil, err
305 }
306
307 return &s, nil
308 }
309
310 func (p *parser) parseFunctionSection(base *section) (*SectionFunction, error) {
311 s := SectionFunction{section: base}
312
313 err := p.loopCount(func() error {
314 var t uint32
315 if err := readVarUint32(p.r, &t); err != nil {
316 return fmt.Errorf("read function type: %v", err)
317 }
318
319 s.Types = append(s.Types, t)
320 return nil
321 })
322 if err != nil {
323 return nil, err
324 }
325
326 return &s, nil
327 }
328
329 func (p *parser) parseTableSection(base *section) (*SectionTable, error) {
330 s := SectionTable{section: base}
331
332 err := p.loopCount(func() error {
333 var e TableType
334
335 if err := p.parseTableType(&e); err != nil {
336 return fmt.Errorf("read table type: %v", err)
337 }
338
339 s.Entries = append(s.Entries, e)
340 return nil
341 })
342 if err != nil {
343 return nil, err
344 }
345
346 return &s, nil
347 }
348
349 func (p *parser) parseMemorySection(base *section) (*SectionMemory, error) {
350 s := SectionMemory{section: base}
351
352 err := p.loopCount(func() error {
353 var e MemoryType
354
355 if err := p.parseResizableLimits(&e.Limits); err != nil {
356 return fmt.Errorf("read memory resizable limits: %v", err)
357 }
358
359 s.Entries = append(s.Entries, e)
360 return nil
361 })
362 if err != nil {
363 return nil, err
364 }
365
366 return &s, nil
367 }
368
369 func (p *parser) parseGlobalSection(base *section) (*SectionGlobal, error) {
370 s := SectionGlobal{section: base}
371
372 err := p.loopCount(func() error {
373 var e GlobalVariable
374
375 if err := readVarInt7(p.r, &e.Type.ContentType); err != nil {
376 return fmt.Errorf("read global content type: %v", err)
377 }
378
379 if err := read(p.r, &e.Type.Mutable); err != nil {
380 return fmt.Errorf("read global mutability: %v", err)
381 }
382
383 if err := readInitExpr(p.r, &e.Init); err != nil {
384 return fmt.Errorf("read global init expression: %v", err)
385 }
386
387 s.Globals = append(s.Globals, e)
388 return nil
389 })
390 if err != nil {
391 return nil, err
392 }
393
394 return &s, nil
395 }
396
397 func (p *parser) parseExportSection(base *section) (*SectionExport, error) {
398 s := SectionExport{section: base}
399
400 err := p.loopCount(func() error {
401 var e ExportEntry
402
403 var fl uint32
404 if err := readVarUint32(p.r, &fl); err != nil {
405 return fmt.Errorf("read field length: %v", err)
406 }
407
408 f := make([]byte, fl)
409 if err := read(p.r, f); err != nil {
410 return fmt.Errorf("read field")
411 }
412 e.Field = string(f)
413
414 var kind uint8
415 if err := readVarUint7(p.r, &kind); err != nil {
416 return fmt.Errorf("read kind: %v", err)
417 }
418 e.Kind = ExternalKind(kind)
419
420 if err := readVarUint32(p.r, &e.Index); err != nil {
421 return fmt.Errorf("read index: %v", err)
422 }
423
424 s.Entries = append(s.Entries, e)
425 return nil
426 })
427 if err != nil {
428 return nil, err
429 }
430
431 return &s, nil
432 }
433
434 func (p *parser) parseStartSection(base *section) (*SectionStart, error) {
435 s := SectionStart{section: base}
436
437 if err := readVarUint32(p.r, &s.Index); err != nil {
438 return nil, fmt.Errorf("read start index: %v", err)
439 }
440
441 return &s, nil
442 }
443
444 func (p *parser) parseElementSection(base *section) (*SectionElement, error) {
445 s := SectionElement{section: base}
446
447 err := p.loopCount(func() error {
448 var e ElemSegment
449
450 if err := readVarUint32(p.r, &e.Index); err != nil {
451 return fmt.Errorf("read element index: %v", err)
452 }
453
454 if err := readInitExpr(p.r, &e.Offset); err != nil {
455 return fmt.Errorf("read offset expression: %v", err)
456 }
457
458 var numElem uint32
459 if err := readVarUint32(p.r, &numElem); err != nil {
460 return fmt.Errorf("read number of elements: %v", err)
461 }
462 e.Elems = make([]uint32, int(numElem))
463 for i := range e.Elems {
464 if err := readVarUint32(p.r, &e.Elems[i]); err != nil {
465 return fmt.Errorf("read element function index %d: %v", i, err)
466 }
467 }
468
469 s.Entries = append(s.Entries, e)
470 return nil
471 })
472 if err != nil {
473 return nil, err
474 }
475
476 return &s, nil
477 }
478
479 func (p *parser) parseCodeSection(base *section) (*SectionCode, error) {
480 s := SectionCode{section: base}
481
482 err := p.loopCount(func() error {
483 var e FunctionBody
484
485 var bs uint32
486 if err := readVarUint32(p.r, &bs); err != nil {
487 return fmt.Errorf("read body size: %v", err)
488 }
489
490 end := p.r.Index() + int(bs)
491
492 p.loopCount(func() error {
493 var l LocalEntry
494
495 if err := readVarUint32(p.r, &l.Count); err != nil {
496 return fmt.Errorf("read local entry count: %v", err)
497 }
498 if err := read(p.r, &l.Type); err != nil {
499 return fmt.Errorf("read local entry value type: %v", err)
500 }
501
502 e.Locals = append(e.Locals, l)
503
504 return nil
505 })
506
507 numBytes := end - p.r.Index()
508 e.Code = make([]byte, numBytes)
509 if err := read(p.r, e.Code); err != nil {
510 return fmt.Errorf("read function bytecode: %v", err)
511 }
512
513 s.Bodies = append(s.Bodies, e)
514 return nil
515 })
516 if err != nil {
517 return nil, err
518 }
519
520 return &s, nil
521 }
522
523 func (p *parser) parseDataSection(base *section) (*SectionData, error) {
524 s := SectionData{section: base}
525
526 const (
527 isPassive = 0x01
528 hasMemIndex = 0x02
529 )
530
531 err := p.loopCount(func() error {
532 var e DataSegment
533
534 var initFlags uint32
535 if err := readVarUint32(p.r, &initFlags); err != nil {
536 return fmt.Errorf("read data segment flags: %v", err)
537 }
538
539 if initFlags&hasMemIndex != 0 {
540 if err := readVarUint32(p.r, &e.Index); err != nil {
541 return fmt.Errorf("read data segment index: %v", err)
542 }
543 }
544
545 if initFlags&isPassive == 0 {
546 if err := readInitExpr(p.r, &e.Offset); err != nil {
547 return fmt.Errorf("read data section offset initializer: %v", err)
548 }
549 }
550
551 var size uint32
552 if err := readVarUint32(p.r, &size); err != nil {
553 return fmt.Errorf("read data section size: %v", err)
554 }
555
556 e.Data = make([]byte, size)
557 if err := read(p.r, e.Data); err != nil {
558 return fmt.Errorf("read data section data: %v", err)
559 }
560
561 s.Entries = append(s.Entries, e)
562 return nil
563 })
564 if err != nil {
565 return nil, err
566 }
567
568 return &s, nil
569 }
570
571 func (p *parser) parseDataCountSection(base *section) (*SectionDataCount, error) {
572 s := SectionDataCount{section: base}
573
574 if err := readVarUint32(p.r, &s.NumSegments); err != nil {
575 return nil, fmt.Errorf("read data count section: %v", err)
576 }
577
578 return &s, nil
579 }
580
581 // name types are used to identify the type in a Name section.
582 const (
583 nameTypeModule uint8 = iota // 0x00
584 nameTypeFunction // 0x01
585 nameTypeLocal // 0x02
586 )
587
588 func (p *parser) parseNameSection(base *section, name string, n uint32) (*SectionName, error) {
589 s := SectionName{
590 section: base,
591 SectionName: name,
592 }
593
594 end := p.r.Index() + int(n)
595 for p.r.Index() < end {
596 var t uint8
597 if err := read(p.r, &t); err != nil {
598 return nil, fmt.Errorf("read name type: %v", err)
599 }
600
601 var pl uint32
602 if err := readVarUint32(p.r, &pl); err != nil {
603 return nil, fmt.Errorf("read payload length: %v", err)
604 }
605
606 switch t {
607 case nameTypeModule:
608 var l uint32
609 if err := readVarUint32(p.r, &l); err != nil {
610 return nil, fmt.Errorf("read module name length: %v", err)
611 }
612
613 name := make([]byte, l)
614 if err := read(p.r, name); err != nil {
615 return nil, fmt.Errorf("read module name: %v", err)
616 }
617
618 s.Module = string(name)
619 case nameTypeFunction:
620 s.Functions = &NameMap{}
621 if err := p.parseNameMap(s.Functions); err != nil {
622 return nil, fmt.Errorf("read function name map: %v", err)
623 }
624 case nameTypeLocal:
625 s.Locals = &Locals{}
626 p.loopCount(func() error {
627 var l LocalName
628 if err := readVarUint32(p.r, &l.Index); err != nil {
629 return fmt.Errorf("read local func index: %v", err)
630 }
631 if err := p.parseNameMap(&l.LocalMap); err != nil {
632 return fmt.Errorf("read local name map: %v", err)
633 }
634 s.Locals.Funcs = append(s.Locals.Funcs, l)
635 return nil
636 })
637 default:
638 subsection := SectionNameUnknown{
639 ID: t,
640 Payload: make([]byte, pl),
641 }
642 if err := read(p.r, subsection.Payload); err != nil {
643 return nil, fmt.Errorf("read name subsection payload: %v", err)
644 }
645 s.UnknownSections = append(s.UnknownSections, subsection)
646 }
647 }
648
649 if p.r.Index() != end {
650 return nil, fmt.Errorf("read %d bytes past the end of the name section", p.r.Index()-end)
651 }
652
653 return &s, nil
654 }
655
656 const (
657 linkingTypeSegment = 5 // WASM_SEGMENT_INFO
658 linkingTypeSymbolTable = 8 // WASM_SYMBOL_TABLE
659 )
660
661 func (p *parser) parseLinkingSection(base *section, name string) (*SectionLinking, error) {
662 // Parse the linking section, as specified here:
663 // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md#linking-metadata-section
664 s := SectionLinking{
665 section: base,
666 SectionName: name,
667 }
668
669 end := p.r.Index() + int(base.size)
670
671 // Check version of the linking section.
672 var version uint32
673 if err := readVarUint32(p.r, &version); err != nil {
674 return nil, fmt.Errorf("read linking section version: %v", err)
675 }
676 if version != 2 {
677 return nil, fmt.Errorf("unsupported linking section version %d (expected 2)", version)
678 }
679
680 // Read each subsection, and parse it if it is a known subsection kind.
681 for p.r.Index() < end {
682 var subsectionType uint8
683 if err := read(p.r, &subsectionType); err != nil {
684 return nil, fmt.Errorf("read subsection type: %v", err)
685 }
686
687 var subsectionLength uint32
688 if err := readVarUint32(p.r, &subsectionLength); err != nil {
689 return nil, fmt.Errorf("read subsection length: %v", err)
690 }
691
692 switch subsectionType {
693 case linkingTypeSegment:
694 // Read the segments of this object file.
695 var numSegments uint32
696 if err := readVarUint32(p.r, &numSegments); err != nil {
697 return nil, fmt.Errorf("read number of segments: %v", err)
698 }
699 for i := 0; i < int(numSegments); i++ {
700 var segment LinkingSegment
701 if err := readString(p.r, &segment.Name); err != nil {
702 return nil, fmt.Errorf("read segment name: %v", err)
703 }
704 if err := readVarUint32(p.r, &segment.Alignment); err != nil {
705 return nil, fmt.Errorf("read segment alignment: %v", err)
706 }
707 if err := readVarUint32(p.r, &segment.Flags); err != nil {
708 return nil, fmt.Errorf("read segment flags: %v", err)
709 }
710 s.Segments = append(s.Segments, segment)
711 }
712 case linkingTypeSymbolTable:
713 // Read the symbol table of this object file.
714 // Unfortunately, the specification isn't complete. I had to look at
715 // the LLVM implementation to figure out all the fields:
716 // https://github.com/llvm/llvm-project/blob/release/18.x/llvm/lib/Object/WasmObjectFile.cpp#L600
717 var numSymbols uint32
718 if err := readVarUint32(p.r, &numSymbols); err != nil {
719 return nil, fmt.Errorf("read number of symbols: %v", err)
720 }
721 for i := 0; i < int(numSymbols); i++ {
722 var kind uint8
723 if err := read(p.r, &kind); err != nil {
724 return nil, fmt.Errorf("read symbol kind: %v", err)
725 }
726 var flags uint32
727 if err := readVarUint32(p.r, &flags); err != nil {
728 return nil, fmt.Errorf("read symbol flags: %v", err)
729 }
730 symbol := LinkingSymbol{
731 Kind: LinkingSymbolKind(kind),
732 Flags: LinkingSymbolFlags(flags),
733 }
734 isDefined := symbol.Flags&LinkingSymbolFlagUndefined == 0
735 isExplicitName := symbol.Flags&LinkingSymbolFlagExplicitName != 0
736 switch symbol.Kind {
737 case LinkingSymbolKindFunction, LinkingSymbolKindGlobal:
738 if err := readVarUint32(p.r, &symbol.Index); err != nil {
739 return nil, fmt.Errorf("read symbol index: %v", err)
740 }
741 if isDefined || isExplicitName {
742 if err := readString(p.r, &symbol.Name); err != nil {
743 return nil, fmt.Errorf("read symbol name: %v", err)
744 }
745 }
746 case LinkingSymbolKindData:
747 if err := readString(p.r, &symbol.Name); err != nil {
748 return nil, fmt.Errorf("read symbol name: %v", err)
749 }
750 if isDefined {
751 if err := readVarUint32(p.r, &symbol.Index); err != nil {
752 return nil, fmt.Errorf("read symbol index: %v", err)
753 }
754 if err := readVarUint64(p.r, &symbol.Offset); err != nil {
755 return nil, fmt.Errorf("read symbol offset: %v", err)
756 }
757 if err := readVarUint64(p.r, &symbol.Size); err != nil {
758 return nil, fmt.Errorf("read symbol size: %v", err)
759 }
760 }
761 case LinkingSymbolKindSection:
762 if err := readVarUint32(p.r, &symbol.Index); err != nil {
763 return nil, fmt.Errorf("read symbol index: %v", err)
764 }
765 case LinkingSymbolKindTable:
766 if err := readVarUint32(p.r, &symbol.Index); err != nil {
767 return nil, fmt.Errorf("read symbol index: %v", err)
768 }
769 if isDefined || isExplicitName {
770 if err := readString(p.r, &symbol.Name); err != nil {
771 return nil, fmt.Errorf("read symbol name: %v", err)
772 }
773 }
774 default:
775 return nil, fmt.Errorf("unknown symbol kind: %v", symbol.Kind)
776 }
777 s.Symbols = append(s.Symbols, symbol)
778 }
779 default:
780 // Unknown subsection, so store it as binary data.
781 subsection := SectionLinkingUnknown{
782 ID: subsectionType,
783 Payload: make([]byte, subsectionLength),
784 }
785 if err := read(p.r, subsection.Payload); err != nil {
786 return nil, fmt.Errorf("read linking subsection payload: %v", err)
787 }
788 s.UnknownSections = append(s.UnknownSections, subsection)
789 }
790 }
791
792 return &s, nil
793 }
794
795 func (p *parser) parseResizableLimits(l *ResizableLimits) error {
796 var hasMax uint8
797 if err := readVarUint1(p.r, &hasMax); err != nil {
798 return fmt.Errorf("flags: %v", err)
799 }
800 if err := readVarUint32(p.r, &l.Initial); err != nil {
801 return fmt.Errorf("initial: %v", err)
802 }
803 if hasMax == 0 {
804 return nil
805 }
806 if err := readVarUint32(p.r, &l.Maximum); err != nil {
807 return fmt.Errorf("maximum: %v", err)
808 }
809 return nil
810 }
811
812 func (p *parser) parseTableType(t *TableType) error {
813 refType, err := readByte(p.r)
814 if err != nil {
815 return fmt.Errorf("read table type limits: %v", err)
816 }
817 t.ElemType = int8(refType)
818 if err := p.parseResizableLimits(&t.Limits); err != nil {
819 return fmt.Errorf("read memory resizable limits: %v", err)
820 }
821 return nil
822 }
823
824 // loopCount reads a varuint32 count and and calls the f n times. All sections
825 // except custom start with this pattern.
826 //
827 // If f returns an error, further processing is not done and the error is
828 // returned to the caller.
829 func (p *parser) loopCount(f func() error) error {
830 var n uint32
831 if err := readVarUint32(p.r, &n); err != nil {
832 return fmt.Errorf("read section count: %v", err)
833 }
834
835 for i := uint32(0); i < n; i++ {
836 if err := f(); err != nil {
837 return fmt.Errorf("entry %d: %v", i, err)
838 }
839 }
840
841 return nil
842 }
843
844 func (p *parser) parseNameMap(v *NameMap) error {
845 p.loopCount(func() error {
846 var n Naming
847
848 if err := readVarUint32(p.r, &n.Index); err != nil {
849 return fmt.Errorf("read naming index: %v", err)
850 }
851
852 var l uint32
853 if err := readVarUint32(p.r, &l); err != nil {
854 return fmt.Errorf("read naming length: %v", err)
855 }
856
857 name := make([]byte, l)
858 if err := read(p.r, name); err != nil {
859 return fmt.Errorf("read name: %v", err)
860 }
861
862 n.Name = string(name)
863 v.Names = append(v.Names, n)
864
865 return nil
866 })
867
868 return nil
869 }
870