Merge 'Use u64 for file offsets in I/O and calculate such offsets in u64' from Preston Thorpe

Using `usize` to compute file offsets caps us at ~16GB on 32-bit
systems. For example, with 4 KiB pages we can only address up to 1048576
pages; attempting the next page overflows a 32-bit usize and can wrap
the write offset, corrupting data. Switching our I/O APIs and offset
math to u64 avoids this overflow on 32-bit targets

Closes #2791
This commit is contained in:
Pekka Enberg
2025-09-02 09:06:49 +03:00
committed by GitHub
16 changed files with 220 additions and 128 deletions

View File

@@ -578,7 +578,7 @@ impl turso_core::DatabaseStorage for DatabaseFile {
if !(512..=65536).contains(&size) || size & (size - 1) != 0 {
return Err(turso_core::LimboError::NotADB);
}
let pos = (page_idx - 1) * size;
let pos = (page_idx as u64 - 1) * size as u64;
self.file.pread(pos, c)
}
@@ -590,7 +590,7 @@ impl turso_core::DatabaseStorage for DatabaseFile {
c: turso_core::Completion,
) -> turso_core::Result<turso_core::Completion> {
let size = buffer.len();
let pos = (page_idx - 1) * size;
let pos = (page_idx as u64 - 1) * size as u64;
self.file.pwrite(pos, buffer, c)
}
@@ -602,7 +602,7 @@ impl turso_core::DatabaseStorage for DatabaseFile {
_io_ctx: &turso_core::IOContext,
c: turso_core::Completion,
) -> turso_core::Result<turso_core::Completion> {
let pos = first_page_idx.saturating_sub(1) * page_size;
let pos = first_page_idx.saturating_sub(1) as u64 * page_size as u64;
let c = self.file.pwritev(pos, buffers, c)?;
Ok(c)
}
@@ -620,7 +620,7 @@ impl turso_core::DatabaseStorage for DatabaseFile {
len: usize,
c: turso_core::Completion,
) -> turso_core::Result<turso_core::Completion> {
let c = self.file.truncate(len, c)?;
let c = self.file.truncate(len as u64, c)?;
Ok(c)
}
}