@@ -6,27 +6,74 @@ extern crate std;
66
77#[ test]
88fn test_validate_buffer_size ( ) {
9+ // ===== Tests with offset = 0 (buffer includes header) =====
10+
11+ // Too small to fit header
912 let small_len = 4 ;
10- assert ! ( raw:: validate_buffer_size( small_len) . is_err( ) ) ;
13+ assert ! ( raw:: validate_buffer_size( small_len, 0 ) . is_err( ) ) ;
1114
15+ // Misaligned: header + partial entry
1216 let misaligned_len = NUM_ENTRIES_SIZE + 39 ;
13- assert ! ( raw:: validate_buffer_size( misaligned_len) . is_err( ) ) ;
17+ assert ! ( raw:: validate_buffer_size( misaligned_len, 0 ) . is_err( ) ) ;
1418
19+ // Too large: more than MAX_ENTRIES
1520 let oversized_len = NUM_ENTRIES_SIZE + ( MAX_ENTRIES + 1 ) * ENTRY_SIZE ;
16- assert ! ( raw:: validate_buffer_size( oversized_len) . is_err( ) ) ;
21+ assert ! ( raw:: validate_buffer_size( oversized_len, 0 ) . is_err( ) ) ;
1722
23+ // Valid cases with offset = 0
1824 let valid_empty_len = NUM_ENTRIES_SIZE ;
19- assert ! ( raw:: validate_buffer_size( valid_empty_len) . is_ok ( ) ) ;
25+ assert_eq ! ( raw:: validate_buffer_size( valid_empty_len, 0 ) . unwrap ( ) , 0 ) ;
2026
2127 let valid_one_len = NUM_ENTRIES_SIZE + ENTRY_SIZE ;
22- assert ! ( raw:: validate_buffer_size( valid_one_len) . is_ok ( ) ) ;
28+ assert_eq ! ( raw:: validate_buffer_size( valid_one_len, 0 ) . unwrap ( ) , 1 ) ;
2329
2430 let valid_max_len = NUM_ENTRIES_SIZE + MAX_ENTRIES * ENTRY_SIZE ;
25- assert ! ( raw:: validate_buffer_size( valid_max_len) . is_ok( ) ) ;
31+ assert_eq ! (
32+ raw:: validate_buffer_size( valid_max_len, 0 ) . unwrap( ) ,
33+ MAX_ENTRIES
34+ ) ;
35+
36+ // Edge case: exactly at the boundary (MAX_SIZE)
37+ assert_eq ! ( raw:: validate_buffer_size( MAX_SIZE , 0 ) . unwrap( ) , MAX_ENTRIES ) ;
38+
39+ // ===== Tests with offset != 0 (buffer doesn't include header) =====
40+
41+ // Valid cases with non-zero offset - buffer contains only entry data
42+
43+ // Buffer for exactly 1 entry
44+ assert_eq ! ( raw:: validate_buffer_size( ENTRY_SIZE , 8 ) . unwrap( ) , 1 ) ;
45+
46+ // Buffer for exactly 2 entries
47+ assert_eq ! ( raw:: validate_buffer_size( 2 * ENTRY_SIZE , 8 ) . unwrap( ) , 2 ) ;
48+
49+ // Buffer for maximum entries (without header space)
50+ assert_eq ! (
51+ raw:: validate_buffer_size( MAX_ENTRIES * ENTRY_SIZE , 8 ) . unwrap( ) ,
52+ MAX_ENTRIES
53+ ) ;
54+
55+ // Buffer for 10 entries
56+ assert_eq ! ( raw:: validate_buffer_size( 10 * ENTRY_SIZE , 48 ) . unwrap( ) , 10 ) ;
2657
27- // Edge case: exactly at the boundary
28- let boundary_len = NUM_ENTRIES_SIZE + MAX_ENTRIES * ENTRY_SIZE ;
29- assert ! ( raw:: validate_buffer_size( boundary_len) . is_ok( ) ) ;
58+ // Error cases with non-zero offset
59+
60+ // Misaligned buffer - not a multiple of ENTRY_SIZE
61+ assert ! ( raw:: validate_buffer_size( ENTRY_SIZE + 1 , 8 ) . is_err( ) ) ;
62+ assert ! ( raw:: validate_buffer_size( ENTRY_SIZE - 1 , 8 ) . is_err( ) ) ;
63+ assert ! ( raw:: validate_buffer_size( 39 , 8 ) . is_err( ) ) ; // 39 is not divisible by 40
64+
65+ // Too many entries - more than MAX_ENTRIES
66+ assert ! ( raw:: validate_buffer_size( ( MAX_ENTRIES + 1 ) * ENTRY_SIZE , 8 ) . is_err( ) ) ;
67+ assert ! ( raw:: validate_buffer_size( ( MAX_ENTRIES + 10 ) * ENTRY_SIZE , 48 ) . is_err( ) ) ;
68+
69+ // Empty buffer with offset (valid - 0 entries)
70+ assert_eq ! ( raw:: validate_buffer_size( 0 , 8 ) . unwrap( ) , 0 ) ;
71+
72+ // ===== Additional edge cases =====
73+
74+ // Large offset values (should still work for buffer size validation)
75+ assert_eq ! ( raw:: validate_buffer_size( 5 * ENTRY_SIZE , 1000 ) . unwrap( ) , 5 ) ;
76+ assert ! ( raw:: validate_buffer_size( 5 * ENTRY_SIZE + 1 , 2000 ) . is_err( ) ) ; // misaligned
3077}
3178
3279#[ test]
@@ -90,9 +137,10 @@ fn test_fetch_into_host_stub() {
90137 let n3 = raw:: fetch_into ( & mut one_entry, 0 ) . expect ( "fetch_into(one_entry, 0)" ) ;
91138 assert_eq ! ( n3, 0 ) ;
92139
93- // 4. Header-skipped fetch should fail because header is missing .
140+ // 4. Header-skipped fetch should succeed and return the number of entries that fit .
94141 let mut skip_header = std:: vec![ 0u8 ; ENTRY_SIZE ] ;
95- assert ! ( raw:: fetch_into( & mut skip_header, 8 ) . is_err( ) ) ;
142+ let entries_count = raw:: fetch_into ( & mut skip_header, 8 ) . expect ( "fetch_into(skip_header, 8)" ) ;
143+ assert_eq ! ( entries_count, 1 ) ; // Buffer can fit exactly 1 entry
96144
97145 // 5. Mis-aligned buffer size should error.
98146 let mut misaligned = std:: vec![ 0u8 ; NUM_ENTRIES_SIZE + 39 ] ;
@@ -106,3 +154,32 @@ fn test_fetch_into_host_stub() {
106154 let mut small = std:: vec![ 0u8 ; 200 ] ;
107155 assert ! ( raw:: fetch_into( & mut small, MAX_SIZE - 199 ) . is_err( ) ) ;
108156}
157+
158+ /// Test that `fetch_into` with offset correctly avoids interpreting slot
159+ /// data as entry count.
160+ #[ cfg( test) ]
161+ #[ test]
162+ fn test_fetch_into_offset_avoids_incorrect_entry_count ( ) {
163+ // The core issue: when fetch_into is called with offset != 0, the first
164+ // 8 bytes of the buffer contains header data, NOT entry data.
165+ let mut buffer = std:: vec![ 0u8 ; 3 * ENTRY_SIZE ] ;
166+
167+ // Call fetch_into with offset 8 (skipping the 8-byte header)
168+ let result = raw:: fetch_into ( & mut buffer, 8 ) ;
169+
170+ assert ! (
171+ result. is_ok( ) ,
172+ "fetch_into should succeed with offset that skips header"
173+ ) ;
174+
175+ let entries_that_fit = result. unwrap ( ) ;
176+ assert_eq ! (
177+ entries_that_fit, 3 ,
178+ "Should return number of entries that fit in buffer, not some slot number"
179+ ) ;
180+
181+ // Buffer for exactly 1 entry starting from offset 48 (2nd entry)
182+ let mut second_entry_buffer = std:: vec![ 0u8 ; ENTRY_SIZE ] ;
183+ let second_result = raw:: fetch_into ( & mut second_entry_buffer, 48 ) . unwrap ( ) ;
184+ assert_eq ! ( second_result, 1 ) ;
185+ }
0 commit comments