From 77d00a4f54ba65a2ab04a25ba501cf704e25fe60 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Fri, 9 Oct 2026 13:04:44 -0300 Subject: [PATCH] fix(fs): reject negative offsets when seeking from the start (#3633) In plugins/fs/src/commands.rs seek, `SeekFrom::Start(offset as u64)` turned -1 into u64::MAX. The offset is now converted with u64::try_from and a negative one is an error. E2E spec added. --- .changes/fix-fs-seek-negative.md | 6 ++++++ packages/api-e2e/test/specs/fs.spec.ts | 13 +++++++++++++ plugins/fs/src/commands.rs | 19 ++++++++++--------- 3 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 .changes/fix-fs-seek-negative.md diff --git a/.changes/fix-fs-seek-negative.md b/.changes/fix-fs-seek-negative.md new file mode 100644 index 000000000..0e46ce23a --- /dev/null +++ b/.changes/fix-fs-seek-negative.md @@ -0,0 +1,6 @@ +--- +fs: patch +fs-js: patch +--- + +`FileHandle.seek` now rejects a negative offset with `SeekMode.Start` instead of seeking to a huge position. diff --git a/packages/api-e2e/test/specs/fs.spec.ts b/packages/api-e2e/test/specs/fs.spec.ts index 790ee9105..68e9f22a3 100644 --- a/packages/api-e2e/test/specs/fs.spec.ts +++ b/packages/api-e2e/test/specs/fs.spec.ts @@ -371,6 +371,19 @@ describePlugin('fs', () => { }) }) + it('FileHandle.seek rejects a negative offset from the start', async () => { + const message = await tauriError(async (api, path) => { + const baseDir = api.fs.BaseDirectory.AppData + const file = await api.fs.create(path, { baseDir }) + try { + await file.seek(-1, api.fs.SeekMode.Start) + } finally { + await file.close() + } + }, `${dir}/seek.txt`) + expect(message).toMatch(/must not be negative/) + }) + it('a closed FileHandle cannot be used again', async () => { const message = await tauriError(async (api, path) => { const baseDir = api.fs.BaseDirectory.AppData diff --git a/plugins/fs/src/commands.rs b/plugins/fs/src/commands.rs index 958e01de3..c66bb0d5a 100644 --- a/plugins/fs/src/commands.rs +++ b/plugins/fs/src/commands.rs @@ -888,16 +888,17 @@ pub async fn seek( whence: SeekMode, ) -> CommandResult { use std::io::{Seek, SeekFrom}; + let position = match whence { + SeekMode::Start => SeekFrom::Start(u64::try_from(offset).map_err(|_| { + format!("invalid seek offset {offset}: it must not be negative with SeekMode.Start") + })?), + SeekMode::Current => SeekFrom::Current(offset), + SeekMode::End => SeekFrom::End(offset), + }; let file: std::sync::Arc> = webview.resources_table().get(rid)?; - StdFileResource::with_lock(&file, |file| { - file.seek(match whence { - SeekMode::Start => SeekFrom::Start(offset as u64), - SeekMode::Current => SeekFrom::Current(offset), - SeekMode::End => SeekFrom::End(offset), - }) - }) - .map_err(|e| format!("failed to seek file with error: {e}")) - .map_err(Into::into) + StdFileResource::with_lock(&file, |file| file.seek(position)) + .map_err(|e| format!("failed to seek file with error: {e}")) + .map_err(Into::into) } #[cfg(target_os = "android")]