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  }