@@ -1978,7 +1978,7 @@ def core_func1(args):
19781978 result ,n = unpack_result (mem1 [retp + 4 ])
19791979 assert (n == 4 and result == CopyResult .COMPLETED )
19801980
1981- [ret ] = canon_stream_write (StreamType (U8Type ()), opts1 , wsi , 12345 , 0 )
1981+ [ret ] = canon_stream_write (StreamType (U8Type ()), opts1 , wsi , 0 , 0 )
19821982 assert (ret == definitions .BLOCKED )
19831983
19841984 fut4 .set ()
@@ -1988,7 +1988,7 @@ def core_func1(args):
19881988 assert (mem1 [retp + 0 ] == wsi )
19891989 assert (mem1 [retp + 4 ] == 0 )
19901990
1991- [ret ] = canon_stream_write (StreamType (U8Type ()), opts1 , wsi , 12345 , 0 )
1991+ [ret ] = canon_stream_write (StreamType (U8Type ()), opts1 , wsi , 0 , 0 )
19921992 assert (ret == 0 )
19931993
19941994 [errctxi ] = canon_error_context_new (opts1 , 0 , 0 )
@@ -2032,7 +2032,7 @@ def core_func2(args):
20322032 fut2 .set ()
20332033 thread .wait_until (fut3 .is_set )
20342034
2035- [ret ] = canon_stream_read (StreamType (U8Type ()), opts2 , rsi , 12345 , 0 )
2035+ [ret ] = canon_stream_read (StreamType (U8Type ()), opts2 , rsi , 0 , 0 )
20362036 assert (ret == 0 )
20372037
20382038 mem2 [0 :8 ] = bytes (8 )
@@ -2047,7 +2047,7 @@ def core_func2(args):
20472047
20482048 thread .wait_until (fut4 .is_set )
20492049
2050- [ret ] = canon_stream_read (StreamType (U8Type ()), opts2 , rsi , 12345 , 0 )
2050+ [ret ] = canon_stream_read (StreamType (U8Type ()), opts2 , rsi , 0 , 0 )
20512051 assert (ret == definitions .BLOCKED )
20522052
20532053 [event ] = canon_waitable_set_wait (MemInst (mem2 , 'i32' ), seti , retp )
@@ -2851,12 +2851,74 @@ def core_func(args):
28512851 [] = canon_stream_drop_readable (StreamType (elemt ), rsi )
28522852 [] = canon_stream_drop_writable (StreamType (elemt ), wsi )
28532853
2854+ # A zero-length buffer's pointer is still checked for alignment and bounds
2855+ # (though it may point at the very end of memory), unless the element type
2856+ # is empty, in which case the pointer is ignored.
2857+ [packed ] = canon_stream_new (StreamType (elemt ))
2858+ rsi ,wsi = unpack_new_ends (packed )
2859+ if elemt is None :
2860+ bad_ptrs = []
2861+ ok_ptr = 0xdeadbeef
2862+ else :
2863+ align = alignment (elemt , 'i32' )
2864+ bad_ptrs = [len (mem ) + align ] + ([1 ] if align > 1 else [])
2865+ ok_ptr = len (mem )
2866+ for ptr in bad_ptrs :
2867+ expect_fail (lambda : canon_stream_read (StreamType (elemt ), async_opts , rsi , ptr , 0 ))
2868+ expect_fail (lambda : canon_stream_write (StreamType (elemt ), async_opts , wsi , ptr , 0 ))
2869+ [ret ] = canon_stream_read (StreamType (elemt ), async_opts , rsi , ok_ptr , 0 )
2870+ assert (ret == definitions .BLOCKED )
2871+ [ret ] = canon_stream_write (StreamType (elemt ), async_opts , wsi , ok_ptr , 0 )
2872+ result ,n = unpack_result (ret )
2873+ assert (n == 0 and result == CopyResult .COMPLETED )
2874+ [ret ] = canon_stream_cancel_read (StreamType (elemt ), True , rsi )
2875+ result ,n = unpack_result (ret )
2876+ assert (n == 0 and result == CopyResult .CANCELLED )
2877+ [] = canon_stream_drop_readable (StreamType (elemt ), rsi )
2878+ [] = canon_stream_drop_writable (StreamType (elemt ), wsi )
2879+
28542880 [] = canon_waitable_set_drop (seti )
28552881 return []
28562882
28572883 lift_and_run (sync_opts , inst , ft , core_func , lambda :[], lambda _ :())
28582884
28592885
2886+ def test_self_copy_trap (elemt ):
2887+ store = Store ()
2888+ inst = ComponentInstance (store )
2889+ mem = bytearray (40 )
2890+ sync_opts = mk_opts (memory = MemInst (mem , 'i32' ), async_ = False )
2891+ async_opts = mk_opts (memory = MemInst (mem , 'i32' ), async_ = True )
2892+ future_t = FutureType (elemt )
2893+ stream_t = StreamType (elemt )
2894+
2895+ # Reading and writing the same future or stream from within the same
2896+ # component instance traps for non-number element types as soon as both ends
2897+ # have provided a buffer, even if no elements would be copied.
2898+ ft = FuncType ([], [], async_ = True )
2899+ def core_func (args ):
2900+ [packed ] = canon_future_new (future_t )
2901+ rfi ,wfi = unpack_new_ends (packed )
2902+ [ret ] = canon_future_write (future_t , async_opts , wfi , 0 )
2903+ assert (ret == definitions .BLOCKED )
2904+ expect_fail (lambda : canon_future_read (future_t , async_opts , rfi , 0 ))
2905+
2906+ for write_first in [True , False ]:
2907+ for write_len in [0 , 1 ]:
2908+ for read_len in [0 , 1 ]:
2909+ [packed ] = canon_stream_new (stream_t )
2910+ rsi ,wsi = unpack_new_ends (packed )
2911+ write = lambda : canon_stream_write (stream_t , async_opts , wsi , 0 , write_len )
2912+ read = lambda : canon_stream_read (stream_t , async_opts , rsi , 0 , read_len )
2913+ first , second = (write , read ) if write_first else (read , write )
2914+ [ret ] = first ()
2915+ assert (ret == definitions .BLOCKED )
2916+ expect_fail (second )
2917+ return []
2918+
2919+ lift_and_run (sync_opts , inst , ft , core_func , lambda :[], lambda _ :())
2920+
2921+
28602922def test_async_flat_params ():
28612923 store = Store ()
28622924 heap = Heap (1000 )
@@ -3148,6 +3210,8 @@ def on_resolve(v):
31483210test_self_copy (None )
31493211test_self_copy (U8Type ())
31503212test_self_copy (F64Type ())
3213+ test_self_copy_trap (BoolType ())
3214+ test_self_copy_trap (StringType ())
31513215test_async_flat_params ()
31523216test_threads ()
31533217test_sync_threads ()
0 commit comments