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}