fix(sync): S-04 — eliminate TOCTOU by recording actual bytes written
This commit is contained in:
+5
-2
@@ -336,9 +336,12 @@ pub fn sync_single_file_to_vault(
|
||||
|
||||
// Bei Überschreiben einer ehemals größeren Datei überzählige alte Chunks entfernen
|
||||
db.truncate_chunks_after(node_id, chunk_idx.saturating_sub(1))?;
|
||||
db.update_node_size_and_time(node_id, local_size, local_mtime)?;
|
||||
// S-04: Verwende bytes_written statt local_size zur Vermeidung von TOCTOU-Diskrepanzen
|
||||
db.update_node_size_and_time(node_id, bytes_written, local_mtime)?;
|
||||
|
||||
Ok(FileTransferResult::Transferred { size: local_size })
|
||||
Ok(FileTransferResult::Transferred {
|
||||
size: bytes_written,
|
||||
})
|
||||
}
|
||||
|
||||
/// Synchronisiert eine Datei aus dem Tresor auf die lokale Festplatte (Pull).
|
||||
|
||||
@@ -643,3 +643,49 @@ fn test_s03_symlink_skipping_and_cycle_protection() {
|
||||
}
|
||||
let _ = fs::remove_dir_all(&temp_root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_s04_toctou_file_size_uses_bytes_written() {
|
||||
let temp_root =
|
||||
std::env::temp_dir().join(format!("sanctum_s04_test_{}", rand::random::<u64>()));
|
||||
let container_path = temp_root.join("test.sanctum");
|
||||
let file_path = temp_root.join("race_file.bin");
|
||||
|
||||
fs::create_dir_all(&temp_root).unwrap();
|
||||
let initial_data = vec![0xABu8; 12345];
|
||||
fs::write(&file_path, &initial_data).unwrap();
|
||||
|
||||
let (db, dek) = create_test_container(&container_path);
|
||||
|
||||
// Sync file to vault
|
||||
let res = sanctum::sync::sync_single_file_to_vault(
|
||||
&db,
|
||||
0,
|
||||
&dek,
|
||||
FORMAT_VERSION,
|
||||
&file_path,
|
||||
1,
|
||||
"race_file.bin",
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.expect("Sync single file to vault");
|
||||
|
||||
match res {
|
||||
sanctum::sync::FileTransferResult::Transferred { size } => {
|
||||
assert_eq!(size, 12345);
|
||||
}
|
||||
_ => panic!("Expected FileTransferResult::Transferred"),
|
||||
}
|
||||
|
||||
let node = db
|
||||
.resolve_path_in_vault("/race_file.bin", 0, &dek)
|
||||
.unwrap()
|
||||
.expect("Node must exist");
|
||||
assert_eq!(
|
||||
node.size, 12345,
|
||||
"Knotengröße muss exakt bytes_written entsprechen"
|
||||
);
|
||||
|
||||
let _ = fs::remove_dir_all(&temp_root);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user