github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/wasm/binary/section.go (about) 1 package binary 2 3 import ( 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 func decodeTypeSection(enabledFeatures api.CoreFeatures, r *bytes.Reader) ([]wasm.FunctionType, error) { 14 vs, _, err := leb128.DecodeUint32(r) 15 if err != nil { 16 return nil, fmt.Errorf("get size of vector: %w", err) 17 } 18 19 result := make([]wasm.FunctionType, vs) 20 for i := uint32(0); i < vs; i++ { 21 if err = decodeFunctionType(enabledFeatures, r, &result[i]); err != nil { 22 return nil, fmt.Errorf("read %d-th type: %v", i, err) 23 } 24 } 25 return result, nil 26 } 27 28 // decodeImportSection decodes the decoded import segments plus the count per wasm.ExternType. 29 func decodeImportSection( 30 r *bytes.Reader, 31 memorySizer memorySizer, 32 memoryLimitPages uint32, 33 enabledFeatures api.CoreFeatures, 34 ) (result []wasm.Import, 35 perModule map[string][]*wasm.Import, 36 funcCount, globalCount, memoryCount, tableCount wasm.Index, err error, 37 ) { 38 vs, _, err := leb128.DecodeUint32(r) 39 if err != nil { 40 err = fmt.Errorf("get size of vector: %w", err) 41 return 42 } 43 44 perModule = make(map[string][]*wasm.Import) 45 result = make([]wasm.Import, vs) 46 for i := uint32(0); i < vs; i++ { 47 imp := &result[i] 48 if err = decodeImport(r, i, memorySizer, memoryLimitPages, enabledFeatures, imp); err != nil { 49 return 50 } 51 switch imp.Type { 52 case wasm.ExternTypeFunc: 53 imp.IndexPerType = funcCount 54 funcCount++ 55 case wasm.ExternTypeGlobal: 56 imp.IndexPerType = globalCount 57 globalCount++ 58 case wasm.ExternTypeMemory: 59 imp.IndexPerType = memoryCount 60 memoryCount++ 61 case wasm.ExternTypeTable: 62 imp.IndexPerType = tableCount 63 tableCount++ 64 } 65 perModule[imp.Module] = append(perModule[imp.Module], imp) 66 } 67 return 68 } 69 70 func decodeFunctionSection(r *bytes.Reader) ([]uint32, error) { 71 vs, _, err := leb128.DecodeUint32(r) 72 if err != nil { 73 return nil, fmt.Errorf("get size of vector: %w", err) 74 } 75 76 result := make([]uint32, vs) 77 for i := uint32(0); i < vs; i++ { 78 if result[i], _, err = leb128.DecodeUint32(r); err != nil { 79 return nil, fmt.Errorf("get type index: %w", err) 80 } 81 } 82 return result, err 83 } 84 85 func decodeTableSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Table, error) { 86 vs, _, err := leb128.DecodeUint32(r) 87 if err != nil { 88 return nil, fmt.Errorf("error reading size") 89 } 90 if vs > 1 { 91 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { 92 return nil, fmt.Errorf("at most one table allowed in module as %w", err) 93 } 94 } 95 96 ret := make([]wasm.Table, vs) 97 for i := range ret { 98 err = decodeTable(r, enabledFeatures, &ret[i]) 99 if err != nil { 100 return nil, err 101 } 102 } 103 return ret, nil 104 } 105 106 func decodeMemorySection( 107 r *bytes.Reader, 108 enabledFeatures api.CoreFeatures, 109 memorySizer memorySizer, 110 memoryLimitPages uint32, 111 ) (*wasm.Memory, error) { 112 vs, _, err := leb128.DecodeUint32(r) 113 if err != nil { 114 return nil, fmt.Errorf("error reading size") 115 } 116 if vs > 1 { 117 return nil, fmt.Errorf("at most one memory allowed in module, but read %d", vs) 118 } else if vs == 0 { 119 // memory count can be zero. 120 return nil, nil 121 } 122 123 return decodeMemory(r, enabledFeatures, memorySizer, memoryLimitPages) 124 } 125 126 func decodeGlobalSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Global, error) { 127 vs, _, err := leb128.DecodeUint32(r) 128 if err != nil { 129 return nil, fmt.Errorf("get size of vector: %w", err) 130 } 131 132 result := make([]wasm.Global, vs) 133 for i := uint32(0); i < vs; i++ { 134 if err = decodeGlobal(r, enabledFeatures, &result[i]); err != nil { 135 return nil, fmt.Errorf("global[%d]: %w", i, err) 136 } 137 } 138 return result, nil 139 } 140 141 func decodeExportSection(r *bytes.Reader) ([]wasm.Export, map[string]*wasm.Export, error) { 142 vs, _, sizeErr := leb128.DecodeUint32(r) 143 if sizeErr != nil { 144 return nil, nil, fmt.Errorf("get size of vector: %v", sizeErr) 145 } 146 147 exportMap := make(map[string]*wasm.Export, vs) 148 exportSection := make([]wasm.Export, vs) 149 for i := wasm.Index(0); i < vs; i++ { 150 export := &exportSection[i] 151 err := decodeExport(r, export) 152 if err != nil { 153 return nil, nil, fmt.Errorf("read export: %w", err) 154 } 155 if _, ok := exportMap[export.Name]; ok { 156 return nil, nil, fmt.Errorf("export[%d] duplicates name %q", i, export.Name) 157 } else { 158 exportMap[export.Name] = export 159 } 160 } 161 return exportSection, exportMap, nil 162 } 163 164 func decodeStartSection(r *bytes.Reader) (*wasm.Index, error) { 165 vs, _, err := leb128.DecodeUint32(r) 166 if err != nil { 167 return nil, fmt.Errorf("get function index: %w", err) 168 } 169 return &vs, nil 170 } 171 172 func decodeElementSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.ElementSegment, error) { 173 vs, _, err := leb128.DecodeUint32(r) 174 if err != nil { 175 return nil, fmt.Errorf("get size of vector: %w", err) 176 } 177 178 result := make([]wasm.ElementSegment, vs) 179 for i := uint32(0); i < vs; i++ { 180 if err = decodeElementSegment(r, enabledFeatures, &result[i]); err != nil { 181 return nil, fmt.Errorf("read element: %w", err) 182 } 183 } 184 return result, nil 185 } 186 187 func decodeCodeSection(r *bytes.Reader) ([]wasm.Code, error) { 188 codeSectionStart := uint64(r.Len()) 189 vs, _, err := leb128.DecodeUint32(r) 190 if err != nil { 191 return nil, fmt.Errorf("get size of vector: %w", err) 192 } 193 194 result := make([]wasm.Code, vs) 195 for i := uint32(0); i < vs; i++ { 196 err = decodeCode(r, codeSectionStart, &result[i]) 197 if err != nil { 198 return nil, fmt.Errorf("read %d-th code segment: %v", i, err) 199 } 200 } 201 return result, nil 202 } 203 204 func decodeDataSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.DataSegment, error) { 205 vs, _, err := leb128.DecodeUint32(r) 206 if err != nil { 207 return nil, fmt.Errorf("get size of vector: %w", err) 208 } 209 210 result := make([]wasm.DataSegment, vs) 211 for i := uint32(0); i < vs; i++ { 212 if err = decodeDataSegment(r, enabledFeatures, &result[i]); err != nil { 213 return nil, fmt.Errorf("read data segment: %w", err) 214 } 215 } 216 return result, nil 217 } 218 219 func decodeDataCountSection(r *bytes.Reader) (count *uint32, err error) { 220 v, _, err := leb128.DecodeUint32(r) 221 if err != nil && err != io.EOF { 222 // data count is optional, so EOF is fine. 223 return nil, err 224 } 225 return &v, nil 226 }