data.go

 1package binary
 2
 3import (
 4	"bytes"
 5	"fmt"
 6	"io"
 7
 8	"github.com/tetratelabs/wazero/api"
 9	"github.com/tetratelabs/wazero/internal/leb128"
10	"github.com/tetratelabs/wazero/internal/wasm"
11)
12
13// dataSegmentPrefix represents three types of data segments.
14//
15// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
16type dataSegmentPrefix = uint32
17
18const (
19	// dataSegmentPrefixActive is the prefix for the version 1.0 compatible data segment, which is classified as "active" in 2.0.
20	dataSegmentPrefixActive dataSegmentPrefix = 0x0
21	// dataSegmentPrefixPassive prefixes the "passive" data segment as in version 2.0 specification.
22	dataSegmentPrefixPassive dataSegmentPrefix = 0x1
23	// dataSegmentPrefixActiveWithMemoryIndex is the active prefix with memory index encoded which is defined for futur use as of 2.0.
24	dataSegmentPrefixActiveWithMemoryIndex dataSegmentPrefix = 0x2
25)
26
27func decodeDataSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.DataSegment) (err error) {
28	dataSegmentPrefx, _, err := leb128.DecodeUint32(r)
29	if err != nil {
30		err = fmt.Errorf("read data segment prefix: %w", err)
31		return
32	}
33
34	if dataSegmentPrefx != dataSegmentPrefixActive {
35		if err = enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
36			err = fmt.Errorf("non-zero prefix for data segment is invalid as %w", err)
37			return
38		}
39	}
40
41	switch dataSegmentPrefx {
42	case dataSegmentPrefixActive,
43		dataSegmentPrefixActiveWithMemoryIndex:
44		// Active data segment as in
45		// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
46		if dataSegmentPrefx == 0x2 {
47			d, _, err := leb128.DecodeUint32(r)
48			if err != nil {
49				return fmt.Errorf("read memory index: %v", err)
50			} else if d != 0 {
51				return fmt.Errorf("memory index must be zero but was %d", d)
52			}
53		}
54
55		err = decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpression)
56		if err != nil {
57			return fmt.Errorf("read offset expression: %v", err)
58		}
59	case dataSegmentPrefixPassive:
60		// Passive data segment doesn't need const expr nor memory index encoded.
61		// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
62		ret.Passive = true
63	default:
64		err = fmt.Errorf("invalid data segment prefix: 0x%x", dataSegmentPrefx)
65		return
66	}
67
68	vs, _, err := leb128.DecodeUint32(r)
69	if err != nil {
70		err = fmt.Errorf("get the size of vector: %v", err)
71		return
72	}
73
74	ret.Init = make([]byte, vs)
75	if _, err = io.ReadFull(r, ret.Init); err != nil {
76		err = fmt.Errorf("read bytes for init: %v", err)
77	}
78	return
79}