@@ -92,13 +92,18 @@ pub trait SparkUnsafeObject {
9292 let addr = self . get_element_offset ( index, 1 ) ;
9393 // SAFETY: addr points to valid element data within the UnsafeRow/UnsafeArray region.
9494 // The caller ensures index is within bounds.
95+ debug_assert ! (
96+ !addr. is_null( ) ,
97+ "get_boolean: null pointer at index {index}"
98+ ) ;
9599 unsafe { * addr != 0 }
96100 }
97101
98102 /// Returns byte value at the given index of the object.
99103 fn get_byte ( & self , index : usize ) -> i8 {
100104 let addr = self . get_element_offset ( index, 1 ) ;
101105 // SAFETY: addr points to valid element data (1 byte) within the row/array region.
106+ debug_assert ! ( !addr. is_null( ) , "get_byte: null pointer at index {index}" ) ;
102107 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 1 ) } ;
103108 i8:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
104109 }
@@ -107,6 +112,7 @@ pub trait SparkUnsafeObject {
107112 fn get_short ( & self , index : usize ) -> i16 {
108113 let addr = self . get_element_offset ( index, 2 ) ;
109114 // SAFETY: addr points to valid element data (2 bytes) within the row/array region.
115+ debug_assert ! ( !addr. is_null( ) , "get_short: null pointer at index {index}" ) ;
110116 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 2 ) } ;
111117 i16:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
112118 }
@@ -115,6 +121,7 @@ pub trait SparkUnsafeObject {
115121 fn get_int ( & self , index : usize ) -> i32 {
116122 let addr = self . get_element_offset ( index, 4 ) ;
117123 // SAFETY: addr points to valid element data (4 bytes) within the row/array region.
124+ debug_assert ! ( !addr. is_null( ) , "get_int: null pointer at index {index}" ) ;
118125 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 4 ) } ;
119126 i32:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
120127 }
@@ -123,6 +130,7 @@ pub trait SparkUnsafeObject {
123130 fn get_long ( & self , index : usize ) -> i64 {
124131 let addr = self . get_element_offset ( index, 8 ) ;
125132 // SAFETY: addr points to valid element data (8 bytes) within the row/array region.
133+ debug_assert ! ( !addr. is_null( ) , "get_long: null pointer at index {index}" ) ;
126134 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 8 ) } ;
127135 i64:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
128136 }
@@ -131,6 +139,7 @@ pub trait SparkUnsafeObject {
131139 fn get_float ( & self , index : usize ) -> f32 {
132140 let addr = self . get_element_offset ( index, 4 ) ;
133141 // SAFETY: addr points to valid element data (4 bytes) within the row/array region.
142+ debug_assert ! ( !addr. is_null( ) , "get_float: null pointer at index {index}" ) ;
134143 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 4 ) } ;
135144 f32:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
136145 }
@@ -139,6 +148,7 @@ pub trait SparkUnsafeObject {
139148 fn get_double ( & self , index : usize ) -> f64 {
140149 let addr = self . get_element_offset ( index, 8 ) ;
141150 // SAFETY: addr points to valid element data (8 bytes) within the row/array region.
151+ debug_assert ! ( !addr. is_null( ) , "get_double: null pointer at index {index}" ) ;
142152 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 8 ) } ;
143153 f64:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
144154 }
@@ -149,6 +159,11 @@ pub trait SparkUnsafeObject {
149159 let addr = self . get_row_addr ( ) + offset as i64 ;
150160 // SAFETY: addr points to valid UTF-8 string data within the variable-length region.
151161 // Offset and length are read from the fixed-length portion of the row/array.
162+ debug_assert ! ( addr != 0 , "get_string: null address at index {index}" ) ;
163+ debug_assert ! (
164+ len >= 0 ,
165+ "get_string: negative length {len} at index {index}"
166+ ) ;
152167 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr as * const u8 , len as usize ) } ;
153168
154169 from_utf8 ( slice) . unwrap ( )
@@ -160,13 +175,19 @@ pub trait SparkUnsafeObject {
160175 let addr = self . get_row_addr ( ) + offset as i64 ;
161176 // SAFETY: addr points to valid binary data within the variable-length region.
162177 // Offset and length are read from the fixed-length portion of the row/array.
178+ debug_assert ! ( addr != 0 , "get_binary: null address at index {index}" ) ;
179+ debug_assert ! (
180+ len >= 0 ,
181+ "get_binary: negative length {len} at index {index}"
182+ ) ;
163183 unsafe { std:: slice:: from_raw_parts ( addr as * const u8 , len as usize ) }
164184 }
165185
166186 /// Returns date value at the given index of the object.
167187 fn get_date ( & self , index : usize ) -> i32 {
168188 let addr = self . get_element_offset ( index, 4 ) ;
169189 // SAFETY: addr points to valid element data (4 bytes) within the row/array region.
190+ debug_assert ! ( !addr. is_null( ) , "get_date: null pointer at index {index}" ) ;
170191 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 4 ) } ;
171192 i32:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
172193 }
@@ -175,6 +196,10 @@ pub trait SparkUnsafeObject {
175196 fn get_timestamp ( & self , index : usize ) -> i64 {
176197 let addr = self . get_element_offset ( index, 8 ) ;
177198 // SAFETY: addr points to valid element data (8 bytes) within the row/array region.
199+ debug_assert ! (
200+ !addr. is_null( ) ,
201+ "get_timestamp: null pointer at index {index}"
202+ ) ;
178203 let slice: & [ u8 ] = unsafe { std:: slice:: from_raw_parts ( addr, 8 ) } ;
179204 i64:: from_le_bytes ( slice. try_into ( ) . unwrap ( ) )
180205 }
@@ -287,6 +312,7 @@ impl SparkUnsafeRow {
287312 // SAFETY: row_addr points to valid Spark UnsafeRow data with at least
288313 // ceil(num_fields/64) * 8 bytes of null bitset. The caller ensures index < num_fields.
289314 // word_offset is within the bitset region since (index >> 6) << 3 < bitset size.
315+ debug_assert ! ( self . row_addr != -1 , "is_null_at: row not initialized" ) ;
290316 unsafe {
291317 let mask: i64 = 1i64 << ( index & 0x3f ) ;
292318 let word_offset = ( self . row_addr + ( ( ( index >> 6 ) as i64 ) << 3 ) ) as * const i64 ;
@@ -300,6 +326,7 @@ impl SparkUnsafeRow {
300326 // SAFETY: row_addr points to valid Spark UnsafeRow data with at least
301327 // ceil(num_fields/64) * 8 bytes of null bitset. The caller ensures index < num_fields.
302328 // Writing is safe because we have mutable access and the memory is owned by the JVM.
329+ debug_assert ! ( self . row_addr != -1 , "set_not_null_at: row not initialized" ) ;
303330 unsafe {
304331 let mask: i64 = 1i64 << ( index & 0x3f ) ;
305332 let word_offset = ( self . row_addr + ( ( ( index >> 6 ) as i64 ) << 3 ) ) as * mut i64 ;
@@ -498,6 +525,18 @@ fn append_columns(
498525 for i in row_start..row_end {
499526 // SAFETY: row_addresses_ptr and row_sizes_ptr are JNI arrays with at least
500527 // row_end elements. i is in [row_start, row_end) so the offset is in bounds.
528+ debug_assert!(
529+ !row_addresses_ptr. is_null( ) ,
530+ "append_columns: null row_addresses_ptr"
531+ ) ;
532+ debug_assert!(
533+ !row_sizes_ptr. is_null( ) ,
534+ "append_columns: null row_sizes_ptr"
535+ ) ;
536+ debug_assert!(
537+ i < row_end,
538+ "append_columns: index {i} out of bounds (row_end={row_end})"
539+ ) ;
501540 let row_addr = unsafe { * row_addresses_ptr. add( i) } ;
502541 let row_size = unsafe { * row_sizes_ptr. add( i) } ;
503542 row. point_to( row_addr, row_size) ;
@@ -630,6 +669,18 @@ fn append_columns(
630669 for i in row_start..row_end {
631670 // SAFETY: row_addresses_ptr and row_sizes_ptr are JNI arrays with at least
632671 // row_end elements. i is in [row_start, row_end) so the offset is in bounds.
672+ debug_assert ! (
673+ !row_addresses_ptr. is_null( ) ,
674+ "append_columns: null row_addresses_ptr"
675+ ) ;
676+ debug_assert ! (
677+ !row_sizes_ptr. is_null( ) ,
678+ "append_columns: null row_sizes_ptr"
679+ ) ;
680+ debug_assert ! (
681+ i < row_end,
682+ "append_columns: index {i} out of bounds (row_end={row_end})"
683+ ) ;
633684 let row_addr = unsafe { * row_addresses_ptr. add ( i) } ;
634685 let row_size = unsafe { * row_sizes_ptr. add ( i) } ;
635686 row. point_to ( row_addr, row_size) ;
@@ -652,6 +703,18 @@ fn append_columns(
652703 for i in row_start..row_end {
653704 // SAFETY: row_addresses_ptr and row_sizes_ptr are JNI arrays with at least
654705 // row_end elements. i is in [row_start, row_end) so the offset is in bounds.
706+ debug_assert ! (
707+ !row_addresses_ptr. is_null( ) ,
708+ "append_columns: null row_addresses_ptr"
709+ ) ;
710+ debug_assert ! (
711+ !row_sizes_ptr. is_null( ) ,
712+ "append_columns: null row_sizes_ptr"
713+ ) ;
714+ debug_assert ! (
715+ i < row_end,
716+ "append_columns: index {i} out of bounds (row_end={row_end})"
717+ ) ;
655718 let row_addr = unsafe { * row_addresses_ptr. add ( i) } ;
656719 let row_size = unsafe { * row_sizes_ptr. add ( i) } ;
657720 row. point_to ( row_addr, row_size) ;
@@ -681,6 +744,18 @@ fn append_columns(
681744 for i in row_start..row_end {
682745 // SAFETY: row_addresses_ptr and row_sizes_ptr are JNI arrays with at least
683746 // row_end elements. i is in [row_start, row_end) so the offset is in bounds.
747+ debug_assert ! (
748+ !row_addresses_ptr. is_null( ) ,
749+ "append_columns: null row_addresses_ptr"
750+ ) ;
751+ debug_assert ! (
752+ !row_sizes_ptr. is_null( ) ,
753+ "append_columns: null row_sizes_ptr"
754+ ) ;
755+ debug_assert ! (
756+ i < row_end,
757+ "append_columns: index {i} out of bounds (row_end={row_end})"
758+ ) ;
684759 let row_addr = unsafe { * row_addresses_ptr. add ( i) } ;
685760 let row_size = unsafe { * row_sizes_ptr. add ( i) } ;
686761 row. point_to ( row_addr, row_size) ;
0 commit comments