Skip to content

Commit 29b9522

Browse files
committed
fix(cache): add safety guards to checkpoint restore and optimize API calls
- Replaced direct `llama_cpp` API calls with cached function pointers (`self._get_size_ext`, etc.) for better performance and consistency. - Added sequence ID validation with verbose error logging to prevent cross-sequence contamination. - Added strict state size validation before restoration to prevent buffer overflows and backend segmentation faults.
1 parent 77b4cd5 commit 29b9522

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

llama_cpp/llama_cache.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,15 @@ def save_checkpoint(
419419
flags = self._flag_partial
420420

421421
# 1. Query the required buffer size
422-
size = llama_cpp.llama_state_seq_get_size_ext(self._ctx, seq_id, flags)
422+
size = self._get_size_ext(self._ctx, seq_id, flags)
423423
if size == 0:
424424
if self.verbose:
425425
print("HybridCheckpointCache: size=0, skip")
426426
return False
427427

428428
# 2. Allocate buffer and extract data
429429
buffer = (ctypes.c_uint8 * size)()
430-
n_written = llama_cpp.llama_state_seq_get_data_ext(self._ctx, buffer, size, seq_id, flags)
430+
n_written = self._get_data_ext(self._ctx, buffer, size, seq_id, flags)
431431
if n_written != size:
432432
if self.verbose:
433433
print(f"HybridCheckpointCache: get failed {n_written}/{size}")
@@ -466,13 +466,24 @@ def restore_checkpoint(self, cp: HybridCheckpoint, seq_id: int = 0) -> bool:
466466
"""
467467
Injects a previously saved RNN state checkpoint back into the C++ backend memory.
468468
"""
469+
# 1. Verify sequence ID matches to prevent cross-sequence contamination
469470
if cp.seq_id != seq_id:
471+
if self.verbose:
472+
print(f"HybridCheckpointCache: [Error] Sequence ID mismatch: checkpoint has {cp.seq_id}, requested {seq_id}", file=sys.stderr)
470473
return False
471474
flags = self._flag_partial
472475

473-
# Copy data back to a ctypes buffer and push to backend
476+
# 2. Verify the underlying C++ context still expects the exact same state size.
477+
# This prevents buffer overflows if the backend context was unexpectedly altered or reallocated.
478+
current_size = self._get_size_ext(self._ctx, seq_id, flags)
479+
if current_size != cp.size:
480+
if self.verbose:
481+
print(f"HybridCheckpointCache: [Warning] State size mismatch before restore: expected {cp.size}, got {current_size} → possible invalidation")
482+
return False
483+
484+
# 3. Copy data back to a ctypes buffer and push to the C++ backend
474485
buffer = (ctypes.c_uint8 * cp.size).from_buffer_copy(cp.data)
475-
ret = llama_cpp.llama_state_seq_set_data_ext(
486+
ret = self._set_data_ext(
476487
self._ctx, buffer, cp.size, seq_id, flags
477488
)
478489
success = (ret == cp.size)

0 commit comments

Comments
 (0)