github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/imports/wasi_snapshot_preview1/args_test.go (about)

     1  package wasi_snapshot_preview1_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/tetratelabs/wazero"
     7  	"github.com/tetratelabs/wazero/internal/testing/require"
     8  	"github.com/tetratelabs/wazero/internal/wasip1"
     9  )
    10  
    11  func Test_argsGet(t *testing.T) {
    12  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc"))
    13  	defer r.Close(testCtx)
    14  
    15  	argvBuf := uint32(16) // arbitrary offset
    16  	argv := uint32(22)    // arbitrary offset
    17  	expectedMemory := []byte{
    18  		'?',                 // argvBuf is after this
    19  		'a', 0, 'b', 'c', 0, // null terminated "a", "bc"
    20  		'?',         // argv is after this
    21  		16, 0, 0, 0, // little endian-encoded offset of "a"
    22  		18, 0, 0, 0, // little endian-encoded offset of "bc"
    23  		'?', // stopped after encoding
    24  	}
    25  
    26  	maskMemory(t, mod, len(expectedMemory)+int(argvBuf))
    27  
    28  	// Invoke argsGet and check the memory side effects.
    29  	requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ArgsGetName, uint64(argv), uint64(argvBuf))
    30  	require.Equal(t, `
    31  ==> wasi_snapshot_preview1.args_get(argv=22,argv_buf=16)
    32  <== errno=ESUCCESS
    33  `, "\n"+log.String())
    34  
    35  	actual, ok := mod.Memory().Read(argvBuf-1, uint32(len(expectedMemory)))
    36  	require.True(t, ok)
    37  	require.Equal(t, expectedMemory, actual)
    38  }
    39  
    40  func Test_argsGet_Errors(t *testing.T) {
    41  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc"))
    42  	defer r.Close(testCtx)
    43  
    44  	memorySize := mod.Memory().Size()
    45  	validAddress := uint32(0) // arbitrary
    46  
    47  	tests := []struct {
    48  		name          string
    49  		argv, argvBuf uint32
    50  		expectedLog   string
    51  	}{
    52  		{
    53  			name:    "out-of-memory argv",
    54  			argv:    memorySize,
    55  			argvBuf: validAddress,
    56  			expectedLog: `
    57  ==> wasi_snapshot_preview1.args_get(argv=65536,argv_buf=0)
    58  <== errno=EFAULT
    59  `,
    60  		},
    61  		{
    62  			name:    "out-of-memory argvBuf",
    63  			argv:    validAddress,
    64  			argvBuf: memorySize,
    65  			expectedLog: `
    66  ==> wasi_snapshot_preview1.args_get(argv=0,argv_buf=65536)
    67  <== errno=EFAULT
    68  `,
    69  		},
    70  		{
    71  			name: "argv exceeds the maximum valid address by 1",
    72  			// 4*argCount is the size of the result of the pointers to args, 4 is the size of uint32
    73  			argv:    memorySize - 4*2 + 1,
    74  			argvBuf: validAddress,
    75  			expectedLog: `
    76  ==> wasi_snapshot_preview1.args_get(argv=65529,argv_buf=0)
    77  <== errno=EFAULT
    78  `,
    79  		},
    80  		{
    81  			name: "argvBuf exceeds the maximum valid address by 1",
    82  			argv: validAddress,
    83  			// "a", "bc" size = size of "a0bc0" = 5
    84  			argvBuf: memorySize - 5 + 1,
    85  			expectedLog: `
    86  ==> wasi_snapshot_preview1.args_get(argv=0,argv_buf=65532)
    87  <== errno=EFAULT
    88  `,
    89  		},
    90  	}
    91  
    92  	for _, tt := range tests {
    93  		tc := tt
    94  
    95  		t.Run(tc.name, func(t *testing.T) {
    96  			defer log.Reset()
    97  
    98  			requireErrnoResult(t, wasip1.ErrnoFault, mod, wasip1.ArgsGetName, uint64(tc.argv), uint64(tc.argvBuf))
    99  			require.Equal(t, tc.expectedLog, "\n"+log.String())
   100  		})
   101  	}
   102  }
   103  
   104  func Test_argsSizesGet(t *testing.T) {
   105  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc"))
   106  	defer r.Close(testCtx)
   107  
   108  	resultArgc := uint32(16)    // arbitrary offset
   109  	resultArgvLen := uint32(21) // arbitrary offset
   110  	expectedMemory := []byte{
   111  		'?',                // resultArgc is after this
   112  		0x2, 0x0, 0x0, 0x0, // little endian-encoded arg count
   113  		'?',                // resultArgvLen is after this
   114  		0x5, 0x0, 0x0, 0x0, // little endian-encoded size of null terminated strings
   115  		'?', // stopped after encoding
   116  	}
   117  
   118  	maskMemory(t, mod, int(resultArgc)+len(expectedMemory))
   119  
   120  	// Invoke argsSizesGet and check the memory side effects.
   121  	requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ArgsSizesGetName, uint64(resultArgc), uint64(resultArgvLen))
   122  	require.Equal(t, `
   123  ==> wasi_snapshot_preview1.args_sizes_get(result.argc=16,result.argv_len=21)
   124  <== errno=ESUCCESS
   125  `, "\n"+log.String())
   126  
   127  	actual, ok := mod.Memory().Read(resultArgc-1, uint32(len(expectedMemory)))
   128  	require.True(t, ok)
   129  	require.Equal(t, expectedMemory, actual)
   130  }
   131  
   132  func Test_argsSizesGet_Errors(t *testing.T) {
   133  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithArgs("a", "bc"))
   134  	defer r.Close(testCtx)
   135  
   136  	memorySize := mod.Memory().Size()
   137  	validAddress := uint32(0) // arbitrary valid address as arguments to args_sizes_get. We chose 0 here.
   138  
   139  	tests := []struct {
   140  		name          string
   141  		argc, argvLen uint32
   142  		expectedLog   string
   143  	}{
   144  		{
   145  			name:    "out-of-memory argc",
   146  			argc:    memorySize,
   147  			argvLen: validAddress,
   148  			expectedLog: `
   149  ==> wasi_snapshot_preview1.args_sizes_get(result.argc=65536,result.argv_len=0)
   150  <== errno=EFAULT
   151  `,
   152  		},
   153  		{
   154  			name:    "out-of-memory argvLen",
   155  			argc:    validAddress,
   156  			argvLen: memorySize,
   157  			expectedLog: `
   158  ==> wasi_snapshot_preview1.args_sizes_get(result.argc=0,result.argv_len=65536)
   159  <== errno=EFAULT
   160  `,
   161  		},
   162  		{
   163  			name:    "argc exceeds the maximum valid address by 1",
   164  			argc:    memorySize - 4 + 1, // 4 is the size of uint32, the type of the count of args
   165  			argvLen: validAddress,
   166  			expectedLog: `
   167  ==> wasi_snapshot_preview1.args_sizes_get(result.argc=65533,result.argv_len=0)
   168  <== errno=EFAULT
   169  `,
   170  		},
   171  		{
   172  			name:    "argvLen exceeds the maximum valid size by 1",
   173  			argc:    validAddress,
   174  			argvLen: memorySize - 4 + 1, // 4 is count of bytes to encode uint32le
   175  			expectedLog: `
   176  ==> wasi_snapshot_preview1.args_sizes_get(result.argc=0,result.argv_len=65533)
   177  <== errno=EFAULT
   178  `,
   179  		},
   180  	}
   181  
   182  	for _, tt := range tests {
   183  		tc := tt
   184  
   185  		t.Run(tc.name, func(t *testing.T) {
   186  			defer log.Reset()
   187  
   188  			requireErrnoResult(t, wasip1.ErrnoFault, mod, wasip1.ArgsSizesGetName, uint64(tc.argc), uint64(tc.argvLen))
   189  			require.Equal(t, tc.expectedLog, "\n"+log.String())
   190  		})
   191  	}
   192  }