@@ -544,6 +544,44 @@ mod tests {
544544 Ok ( ( ) )
545545 }
546546
547+ #[ test]
548+ fn test_rebuild_flatten_null_row_ignores_invalid_range_payload ( ) -> VortexResult < ( ) > {
549+ let elements = PrimitiveArray :: from_iter ( vec ! [ 1i32 , 2 , 3 ] ) . into_array ( ) ;
550+ let offsets = PrimitiveArray :: from_iter ( vec ! [ 0u32 , 999 , 2 ] ) . into_array ( ) ;
551+ let sizes = PrimitiveArray :: from_iter ( vec ! [ 2u32 , 999 , 1 ] ) . into_array ( ) ;
552+ let validity = Validity :: from_iter ( [ true , false , true ] ) ;
553+
554+ // SAFETY: this intentionally models a null row whose physical offset and size payloads are
555+ // invalid. Rebuild must ignore those payloads and only emit safe placeholder ranges for the
556+ // null row.
557+ let listview = unsafe { ListViewArray :: new_unchecked ( elements, offsets, sizes, validity) } ;
558+
559+ let mut ctx = SESSION . create_execution_ctx ( ) ;
560+ let flattened = listview. rebuild ( ListViewRebuildMode :: MakeZeroCopyToList , & mut ctx) ?;
561+
562+ assert_eq ! ( flattened. offset_at( 0 ) , 0 ) ;
563+ assert_eq ! ( flattened. size_at( 0 ) , 2 ) ;
564+ assert_eq ! ( flattened. offset_at( 1 ) , 2 ) ;
565+ assert_eq ! ( flattened. size_at( 1 ) , 0 ) ;
566+ assert_eq ! ( flattened. offset_at( 2 ) , 2 ) ;
567+ assert_eq ! ( flattened. size_at( 2 ) , 1 ) ;
568+ assert ! ( flattened. validity( ) ?. execute_is_valid( 0 , & mut ctx) ?) ;
569+ assert ! ( !flattened. validity( ) ?. execute_is_valid( 1 , & mut ctx) ?) ;
570+ assert ! ( flattened. validity( ) ?. execute_is_valid( 2 , & mut ctx) ?) ;
571+
572+ assert_arrays_eq ! (
573+ flattened. list_elements_at( 0 ) ?,
574+ PrimitiveArray :: from_iter( [ 1i32 , 2 ] ) ,
575+ & mut ctx
576+ ) ;
577+ assert_arrays_eq ! (
578+ flattened. list_elements_at( 2 ) ?,
579+ PrimitiveArray :: from_iter( [ 3i32 ] ) ,
580+ & mut ctx
581+ ) ;
582+ Ok ( ( ) )
583+ }
584+
547585 #[ test]
548586 fn test_rebuild_trim_elements_basic ( ) -> VortexResult < ( ) > {
549587 // Test trimming both leading and trailing unused elements while preserving gaps in the
0 commit comments