@@ -370,3 +370,25 @@ def test_large_list_stress():
370370 # Spot-check first and last.
371371 assert FFI .read_i64 (FFI .at_idx (lst , 0 )) == 0
372372 assert FFI .read_i64 (FFI .at_idx (lst , count - 1 )) == count - 1
373+
374+
375+ def test_read_vector_raw_rejects_non_vectors ():
376+ """Regression: read_vector_raw / read_u8_vector used to dereference the
377+ underlying pointer without checks, so a bare RayObject() (obj == NULL)
378+ segfaulted the interpreter and an atom read garbage length bytes."""
379+ with pytest .raises (RuntimeError , match = "not a vector" ):
380+ r .read_vector_raw (r .RayObject ())
381+
382+ with pytest .raises (RuntimeError , match = "not a u8 vector" ):
383+ r .read_u8_vector (r .RayObject ())
384+
385+ # Atoms alias `len` with their payload — must be rejected, not read.
386+ with pytest .raises (RuntimeError , match = "not a vector" ):
387+ r .read_vector_raw (FFI .init_i64 (5 ))
388+
389+ with pytest .raises (RuntimeError , match = "not a u8 vector" ):
390+ r .read_u8_vector (FFI .init_u8 (5 ))
391+
392+ # Real vectors still read fine.
393+ vec = FFI .init_vector (r .TYPE_I64 , [1 , 2 , 3 ])
394+ assert len (FFI .read_vector_raw (vec )) == 3 * 8
0 commit comments