Skip to content

Commit 06eede0

Browse files
committed
clarify
1 parent 1d9cab0 commit 06eede0

File tree

2 files changed

+58
-32
lines changed

2 files changed

+58
-32
lines changed

sdk/pinocchio/src/sysvars/slot_hashes/raw.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@
88

99
use super::*;
1010

11-
/// Validates that a buffer is properly sized for `SlotHashes` data.
11+
/// Validates buffer format for `SlotHashes` data and calculates entry capacity.
1212
///
13-
/// Does not ensure the buffer doesn't exceed available sysvar data
14-
/// from the given offset. A later syscall will fail in this case.
13+
/// Validates that the buffer follows the correct format:
14+
/// - If `offset == 0`: Buffer must have `8 + (N × 40)` format (header + entries)
15+
/// - If `offset != 0`: Buffer must be a multiple of 40 bytes (entries only)
1516
///
16-
/// This function assumes the mainnet slot hashes sysvar length of `MAX_SIZE` (20,488).
17+
/// Does not validate that `offset + buffer_len ≤ MAX_SIZE`; this is checked
18+
/// separately in `validate_fetch_offset`, and the syscall will fail anyway if
19+
/// `offset + buffer_len > MAX_SIZE`.
1720
///
18-
/// Returns the number of entries that will be copied into the buffer.
21+
/// Returns the number of entries that can fit in the buffer.
1922
#[inline(always)]
20-
pub(crate) fn validate_buffer_size(
23+
pub(crate) fn validate_and_get_buffer_capacity(
2124
buffer_len: usize,
2225
offset: usize,
2326
) -> Result<usize, ProgramError> {
@@ -78,24 +81,25 @@ pub fn validate_fetch_offset(offset: usize, buffer_len: usize) -> Result<(), Pro
7881
///
7982
/// # Returns
8083
///
81-
/// Since `num_entries` is used, it is returned for caller's convenience, as the
82-
/// caller will almost certainly want to use this information.
84+
/// Returns the number of entries:
85+
/// - If `offset == 0`: The actual entry count read from the sysvar header
86+
/// - If `offset != 0`: The number of entries that can fit in the buffer
87+
///
88+
/// The return value helps callers understand the structure of the copied data.
8389
#[inline(always)]
8490
pub fn fetch_into(buffer: &mut [u8], offset: usize) -> Result<usize, ProgramError> {
85-
let num_entries = validate_buffer_size(buffer.len(), offset)?;
91+
let num_entries = validate_and_get_buffer_capacity(buffer.len(), offset)?;
8692

8793
validate_fetch_offset(offset, buffer.len())?;
8894

89-
// SAFETY: `buffer.len()` and `offset` are both validated above. It is possible
90-
// that the two added together are greater than `MAX_SIZE`, but the syscall will
91-
// fail in that case.
95+
// SAFETY: Buffer format and offset alignment validated above.
9296
unsafe { fetch_into_unchecked(buffer, offset) }?;
9397

9498
if offset == 0 {
95-
// If header is preset, read entries from it
99+
// Buffer includes header: return actual entry count from sysvar data
96100
Ok(read_entry_count_from_bytes(buffer).unwrap_or(0))
97101
} else {
98-
// Otherwise, return the number of entries that can fit in the buffer
102+
// Buffer excludes header: return calculated entry capacity
99103
Ok(num_entries)
100104
}
101105
}

sdk/pinocchio/src/sysvars/slot_hashes/test_raw.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,73 +10,95 @@ fn test_validate_buffer_size() {
1010

1111
// Too small to fit header
1212
let small_len = 4;
13-
assert!(raw::validate_buffer_size(small_len, 0).is_err());
13+
assert!(raw::validate_and_get_buffer_capacity(small_len, 0).is_err());
1414

1515
// Misaligned: header + partial entry
1616
let misaligned_len = NUM_ENTRIES_SIZE + 39;
17-
assert!(raw::validate_buffer_size(misaligned_len, 0).is_err());
17+
assert!(raw::validate_and_get_buffer_capacity(misaligned_len, 0).is_err());
1818

1919
// Valid cases with offset = 0
2020
let valid_empty_len = NUM_ENTRIES_SIZE;
21-
assert_eq!(raw::validate_buffer_size(valid_empty_len, 0).unwrap(), 0);
21+
assert_eq!(
22+
raw::validate_and_get_buffer_capacity(valid_empty_len, 0).unwrap(),
23+
0
24+
);
2225

2326
let valid_one_len = NUM_ENTRIES_SIZE + ENTRY_SIZE;
24-
assert_eq!(raw::validate_buffer_size(valid_one_len, 0).unwrap(), 1);
27+
assert_eq!(
28+
raw::validate_and_get_buffer_capacity(valid_one_len, 0).unwrap(),
29+
1
30+
);
2531

2632
let valid_max_len = NUM_ENTRIES_SIZE + MAX_ENTRIES * ENTRY_SIZE;
2733
assert_eq!(
28-
raw::validate_buffer_size(valid_max_len, 0).unwrap(),
34+
raw::validate_and_get_buffer_capacity(valid_max_len, 0).unwrap(),
2935
MAX_ENTRIES
3036
);
3137

3238
// Edge case: exactly at the boundary (MAX_SIZE)
33-
assert_eq!(raw::validate_buffer_size(MAX_SIZE, 0).unwrap(), MAX_ENTRIES);
39+
assert_eq!(
40+
raw::validate_and_get_buffer_capacity(MAX_SIZE, 0).unwrap(),
41+
MAX_ENTRIES
42+
);
3443

3544
// ===== Tests with offset != 0 (buffer doesn't include header) =====
3645

3746
// Valid cases with non-zero offset - buffer contains only entry data
3847

3948
// Buffer for exactly 1 entry
40-
assert_eq!(raw::validate_buffer_size(ENTRY_SIZE, 8).unwrap(), 1);
49+
assert_eq!(
50+
raw::validate_and_get_buffer_capacity(ENTRY_SIZE, 8).unwrap(),
51+
1
52+
);
4153

4254
// Buffer for exactly 2 entries
43-
assert_eq!(raw::validate_buffer_size(2 * ENTRY_SIZE, 8).unwrap(), 2);
55+
assert_eq!(
56+
raw::validate_and_get_buffer_capacity(2 * ENTRY_SIZE, 8).unwrap(),
57+
2
58+
);
4459

4560
// Buffer for maximum entries (without header space)
4661
assert_eq!(
47-
raw::validate_buffer_size(MAX_ENTRIES * ENTRY_SIZE, 8).unwrap(),
62+
raw::validate_and_get_buffer_capacity(MAX_ENTRIES * ENTRY_SIZE, 8).unwrap(),
4863
MAX_ENTRIES
4964
);
5065

5166
// Buffer for 10 entries
52-
assert_eq!(raw::validate_buffer_size(10 * ENTRY_SIZE, 48).unwrap(), 10);
67+
assert_eq!(
68+
raw::validate_and_get_buffer_capacity(10 * ENTRY_SIZE, 48).unwrap(),
69+
10
70+
);
5371

5472
// Error cases with non-zero offset
5573

5674
// Misaligned buffer - not a multiple of ENTRY_SIZE
57-
assert!(raw::validate_buffer_size(ENTRY_SIZE + 1, 8).is_err());
58-
assert!(raw::validate_buffer_size(ENTRY_SIZE - 1, 8).is_err());
59-
assert!(raw::validate_buffer_size(39, 8).is_err()); // 39 is not divisible by 40
75+
assert!(raw::validate_and_get_buffer_capacity(ENTRY_SIZE + 1, 8).is_err());
76+
assert!(raw::validate_and_get_buffer_capacity(ENTRY_SIZE - 1, 8).is_err());
77+
assert!(raw::validate_and_get_buffer_capacity(39, 8).is_err()); // 39 is not divisible by 40
6078

6179
// Large buffers that would exceed MAX_SIZE - these now pass validate_buffer_size
6280
// (the syscall will fail later, but that's acceptable)
6381
assert_eq!(
64-
raw::validate_buffer_size((MAX_ENTRIES + 1) * ENTRY_SIZE, 8).unwrap(),
82+
raw::validate_and_get_buffer_capacity((MAX_ENTRIES + 1) * ENTRY_SIZE, 8).unwrap(),
6583
MAX_ENTRIES + 1
6684
);
6785
assert_eq!(
68-
raw::validate_buffer_size((MAX_ENTRIES + 10) * ENTRY_SIZE, 48).unwrap(),
86+
raw::validate_and_get_buffer_capacity((MAX_ENTRIES + 10) * ENTRY_SIZE, 48).unwrap(),
6987
MAX_ENTRIES + 10
7088
);
7189

7290
// Empty buffer with offset (valid - 0 entries)
73-
assert_eq!(raw::validate_buffer_size(0, 8).unwrap(), 0);
91+
assert_eq!(raw::validate_and_get_buffer_capacity(0, 8).unwrap(), 0);
7492

7593
// ===== Additional edge cases =====
7694

7795
// Large offset values (should still work for buffer size validation)
78-
assert_eq!(raw::validate_buffer_size(5 * ENTRY_SIZE, 1000).unwrap(), 5);
79-
assert!(raw::validate_buffer_size(5 * ENTRY_SIZE + 1, 2000).is_err()); // misaligned
96+
assert_eq!(
97+
raw::validate_and_get_buffer_capacity(5 * ENTRY_SIZE, 1000).unwrap(),
98+
5
99+
);
100+
assert!(raw::validate_and_get_buffer_capacity(5 * ENTRY_SIZE + 1, 2000).is_err());
101+
// misaligned
80102
}
81103

82104
#[test]

0 commit comments

Comments
 (0)