fix(overlaybd): validate index bounds before allocation - #98
Conversation
|
🔍 OpenCodeReview found 2 issue(s) in this PR.
|
09082a1 to
12c6398
Compare
| let total_index_memory = metadata.iter().try_fold(0usize, |total, layer| { | ||
| total | ||
| .checked_add(stack_index_memory_bytes(layer.index_size)?) | ||
| .context("stack index memory size overflow") | ||
| })?; | ||
| ensure!( | ||
| total_index_memory <= MAX_STACK_INDEX_MEMORY_BYTES, | ||
| "stack index memory {total_index_memory} exceeds limit {MAX_STACK_INDEX_MEMORY_BYTES}" | ||
| ); |
There was a problem hiding this comment.
[bug · medium]
This limit is enforced only when merge_readonly_indexes runs. In open_files_ro_with_premerged_cache, both cache-hit branches return a decoded merged index before calling this function, so the same layer stack can bypass MAX_STACK_INDEX_MEMORY_BYTES whenever a cache artifact exists. Move the metadata-based validation to a helper invoked immediately after metadata loading (before cache lookup), or also apply it on each cache-hit path, so behavior and the memory policy do not depend on cache state.
| #[tokio::test] | ||
| async fn rejects_sealed_index_size_out_of_bounds() { | ||
| let temp_dir = TempDir::new().unwrap(); | ||
| let data = create_sealed_layer(&temp_dir, "bad-index-size", 8192, &[(0, 0x22)]).await; | ||
| let file_size = data.size().await.unwrap(); | ||
| let trailer = verify_ht(&(data.clone() as Arc<dyn VirtualFile>), true, file_size) | ||
| .await | ||
| .unwrap(); | ||
| let stride = size_of::<DiskSegmentMapping>() as u64; | ||
| let remaining = file_size - HEADER_SIZE - trailer.index_offset.get(); | ||
| let bad_index_size = remaining / stride + 1; |
There was a problem hiding this comment.
[test · low]
The new bounds tests only exercise clearly invalid values. Add direct acceptance tests for the inclusive boundaries used by validate_index_bounds, especially an index ending exactly at file_size - HEADER_SIZE and a zero-count index at a valid boundary. Otherwise an accidental <=/< regression could reject valid sealed layers while all these rejection tests continue to pass.
What
Validate OverlayBD index offsets and mapping counts against the backing file before allocating or reading an index.
The loader now:
u64until checked conversion;Why
At the affected base,
load_indexcalculatedcount * size_of::<DiskSegmentMapping>()and allocated that buffer before checking whether the trailer-described range existed in the file. A corrupted trailer could therefore drive excessive allocation or arithmetic failure before returning a malformed-layer error.Closes #97.
Scope and non-goals
This PR changes parser validation only. It does not change the OverlayBD wire format, valid layer layout, index ordering, compression, or remote backend behavior.
Design and behavior changes
For sealed data files, the valid range ends at the start of the 4 KiB trailer. For index-only writable files, it ends at the current file length.
Compatibility and operations
Validation
make fmtmake clippymake test-unitmake -C services test(required whenservices/changes)maketargetCommands and results:
The library suite is listed with one test thread because several tests share the process-global transient I/O worker; the parallel invocation can close that shared channel and cascade unrelated
channel closedfailures.Risks and reviewer notes
The main review point is
validate_index_boundsinstorage/overlaybd/src/lsmt/file/helper.rs. In particular, sealed files reserveHEADER_SIZEat the end for the trailer, while direct index-file loading intentionally validates against the full file length.Checklist