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  }