github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wasm/binary/section.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 8 "github.com/bananabytelabs/wazero/api" 9 "github.com/bananabytelabs/wazero/internal/leb128" 10 "github.com/bananabytelabs/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 memorySizer memorySizer, 109 memoryLimitPages uint32, 110 ) (*wasm.Memory, error) { 111 vs, _, err := leb128.DecodeUint32(r) 112 if err != nil { 113 return nil, fmt.Errorf("error reading size") 114 } 115 if vs > 1 { 116 return nil, fmt.Errorf("at most one memory allowed in module, but read %d", vs) 117 } else if vs == 0 { 118 // memory count can be zero. 119 return nil, nil 120 } 121 122 return decodeMemory(r, memorySizer, memoryLimitPages) 123 } 124 125 func decodeGlobalSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Global, error) { 126 vs, _, err := leb128.DecodeUint32(r) 127 if err != nil { 128 return nil, fmt.Errorf("get size of vector: %w", err) 129 } 130 131 result := make([]wasm.Global, vs) 132 for i := uint32(0); i < vs; i++ { 133 if err = decodeGlobal(r, enabledFeatures, &result[i]); err != nil { 134 return nil, fmt.Errorf("global[%d]: %w", i, err) 135 } 136 } 137 return result, nil 138 } 139 140 func decodeExportSection(r *bytes.Reader) ([]wasm.Export, map[string]*wasm.Export, error) { 141 vs, _, sizeErr := leb128.DecodeUint32(r) 142 if sizeErr != nil { 143 return nil, nil, fmt.Errorf("get size of vector: %v", sizeErr) 144 } 145 146 exportMap := make(map[string]*wasm.Export, vs) 147 exportSection := make([]wasm.Export, vs) 148 for i := wasm.Index(0); i < vs; i++ { 149 export := &exportSection[i] 150 err := decodeExport(r, export) 151 if err != nil { 152 return nil, nil, fmt.Errorf("read export: %w", err) 153 } 154 if _, ok := exportMap[export.Name]; ok { 155 return nil, nil, fmt.Errorf("export[%d] duplicates name %q", i, export.Name) 156 } else { 157 exportMap[export.Name] = export 158 } 159 } 160 return exportSection, exportMap, nil 161 } 162 163 func decodeStartSection(r *bytes.Reader) (*wasm.Index, error) { 164 vs, _, err := leb128.DecodeUint32(r) 165 if err != nil { 166 return nil, fmt.Errorf("get function index: %w", err) 167 } 168 return &vs, nil 169 } 170 171 func decodeElementSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.ElementSegment, error) { 172 vs, _, err := leb128.DecodeUint32(r) 173 if err != nil { 174 return nil, fmt.Errorf("get size of vector: %w", err) 175 } 176 177 result := make([]wasm.ElementSegment, vs) 178 for i := uint32(0); i < vs; i++ { 179 if err = decodeElementSegment(r, enabledFeatures, &result[i]); err != nil { 180 return nil, fmt.Errorf("read element: %w", err) 181 } 182 } 183 return result, nil 184 } 185 186 func decodeCodeSection(r *bytes.Reader) ([]wasm.Code, error) { 187 codeSectionStart := uint64(r.Len()) 188 vs, _, err := leb128.DecodeUint32(r) 189 if err != nil { 190 return nil, fmt.Errorf("get size of vector: %w", err) 191 } 192 193 result := make([]wasm.Code, vs) 194 for i := uint32(0); i < vs; i++ { 195 err = decodeCode(r, codeSectionStart, &result[i]) 196 if err != nil { 197 return nil, fmt.Errorf("read %d-th code segment: %v", i, err) 198 } 199 } 200 return result, nil 201 } 202 203 func decodeDataSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.DataSegment, error) { 204 vs, _, err := leb128.DecodeUint32(r) 205 if err != nil { 206 return nil, fmt.Errorf("get size of vector: %w", err) 207 } 208 209 result := make([]wasm.DataSegment, vs) 210 for i := uint32(0); i < vs; i++ { 211 if err = decodeDataSegment(r, enabledFeatures, &result[i]); err != nil { 212 return nil, fmt.Errorf("read data segment: %w", err) 213 } 214 } 215 return result, nil 216 } 217 218 func decodeDataCountSection(r *bytes.Reader) (count *uint32, err error) { 219 v, _, err := leb128.DecodeUint32(r) 220 if err != nil && err != io.EOF { 221 // data count is optional, so EOF is fine. 222 return nil, err 223 } 224 return &v, nil 225 }