1 package binary
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7
8 "github.com/tetratelabs/wazero/internal/leb128"
9 "github.com/tetratelabs/wazero/internal/wasm"
10 )
11
12 const (
13
14 subsectionIDModuleName = uint8(0)
15
16 subsectionIDFunctionNames = uint8(1)
17
18
19 subsectionIDLocalNames = uint8(2)
20 )
21
22
23
24
25
26
27
28
29
30 func decodeNameSection(r *bytes.Reader, limit uint64) (result *wasm.NameSection, err error) {
31
32
33 result = &wasm.NameSection{}
34
35
36 var subsectionID uint8
37
38 var subsectionSize uint32
39 var bytesRead uint64
40 for limit > 0 {
41 if subsectionID, err = r.ReadByte(); err != nil {
42 if err == io.EOF {
43 return result, nil
44 }
45
46 return nil, fmt.Errorf("failed to read a subsection ID: %w", err)
47 }
48 limit--
49
50 if subsectionSize, bytesRead, err = leb128.DecodeUint32(r); err != nil {
51 return nil, fmt.Errorf("failed to read the size of subsection[%d]: %w", subsectionID, err)
52 }
53 limit -= bytesRead
54
55 switch subsectionID {
56 case subsectionIDModuleName:
57 if result.ModuleName, _, err = decodeUTF8(r, "module name"); err != nil {
58 return nil, err
59 }
60 case subsectionIDFunctionNames:
61 if result.FunctionNames, err = decodeFunctionNames(r); err != nil {
62 return nil, err
63 }
64 case subsectionIDLocalNames:
65 if result.LocalNames, err = decodeLocalNames(r); err != nil {
66 return nil, err
67 }
68 default:
69
70 if _, err = io.CopyN(io.Discard, r, int64(subsectionSize)); err != nil {
71 return nil, fmt.Errorf("failed to skip subsection[%d]: %w", subsectionID, err)
72 }
73 }
74 limit -= uint64(subsectionSize)
75 }
76 return
77 }
78
79 func decodeFunctionNames(r *bytes.Reader) (wasm.NameMap, error) {
80 functionCount, err := decodeFunctionCount(r, subsectionIDFunctionNames)
81 if err != nil {
82 return nil, err
83 }
84
85 result := make(wasm.NameMap, functionCount)
86 for i := uint32(0); i < functionCount; i++ {
87 functionIndex, err := decodeFunctionIndex(r, subsectionIDFunctionNames)
88 if err != nil {
89 return nil, err
90 }
91
92 name, _, err := decodeUTF8(r, "function[%d] name", functionIndex)
93 if err != nil {
94 return nil, err
95 }
96 result[i] = wasm.NameAssoc{Index: functionIndex, Name: name}
97 }
98 return result, nil
99 }
100
101 func decodeLocalNames(r *bytes.Reader) (wasm.IndirectNameMap, error) {
102 functionCount, err := decodeFunctionCount(r, subsectionIDLocalNames)
103 if err != nil {
104 return nil, err
105 }
106
107 result := make(wasm.IndirectNameMap, functionCount)
108 for i := uint32(0); i < functionCount; i++ {
109 functionIndex, err := decodeFunctionIndex(r, subsectionIDLocalNames)
110 if err != nil {
111 return nil, err
112 }
113
114 localCount, _, err := leb128.DecodeUint32(r)
115 if err != nil {
116 return nil, fmt.Errorf("failed to read the local count for function[%d]: %w", functionIndex, err)
117 }
118
119 locals := make(wasm.NameMap, localCount)
120 for j := uint32(0); j < localCount; j++ {
121 localIndex, _, err := leb128.DecodeUint32(r)
122 if err != nil {
123 return nil, fmt.Errorf("failed to read a local index of function[%d]: %w", functionIndex, err)
124 }
125
126 name, _, err := decodeUTF8(r, "function[%d] local[%d] name", functionIndex, localIndex)
127 if err != nil {
128 return nil, err
129 }
130 locals[j] = wasm.NameAssoc{Index: localIndex, Name: name}
131 }
132 result[i] = wasm.NameMapAssoc{Index: functionIndex, NameMap: locals}
133 }
134 return result, nil
135 }
136
137 func decodeFunctionIndex(r *bytes.Reader, subsectionID uint8) (uint32, error) {
138 functionIndex, _, err := leb128.DecodeUint32(r)
139 if err != nil {
140 return 0, fmt.Errorf("failed to read a function index in subsection[%d]: %w", subsectionID, err)
141 }
142 return functionIndex, nil
143 }
144
145 func decodeFunctionCount(r *bytes.Reader, subsectionID uint8) (uint32, error) {
146 functionCount, _, err := leb128.DecodeUint32(r)
147 if err != nil {
148 return 0, fmt.Errorf("failed to read the function count of subsection[%d]: %w", subsectionID, err)
149 }
150 return functionCount, nil
151 }
152
View as plain text