Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LocalFileSystem with range request that ends beyond end of file #6751

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions object_store/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,23 +897,26 @@ pub(crate) fn chunked_stream(

pub(crate) fn read_range(file: &mut File, path: &PathBuf, range: Range<usize>) -> Result<Bytes> {
let to_read = range.end - range.start;
file.seek(SeekFrom::Start(range.start as u64))
let seek_idx = file
.seek(SeekFrom::Start(range.start as u64))
.context(SeekSnafu { path })?;

let mut buf = Vec::with_capacity(to_read);
let read = file
.take(to_read as u64)
.read_to_end(&mut buf)
.context(UnableToReadBytesSnafu { path })?;

ensure!(
read == to_read,
seek_idx == range.start as u64,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears this will always be true, even if seeking beyond EOF.

OutOfRangeSnafu {
path,
expected: to_read,
actual: read
expected: range.start,
actual: seek_idx as usize
}
);

let mut buf = Vec::with_capacity(to_read);
file.take(to_read as u64)
.read_to_end(&mut buf)
.context(UnableToReadBytesSnafu { path })?;
Comment on lines +914 to +916
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, this read will simply return 0 when reading beyond EOF.


// The output buffer could be smaller than `to_read` bytes if the end of the range is beyond
// the end of the file.
Ok(buf.into())
}

Expand Down Expand Up @@ -1155,6 +1158,44 @@ mod tests {
assert_eq!(&*read_data, data);
}

#[tokio::test]
async fn range_request_start_beyond_end_of_file() {
let root = TempDir::new().unwrap();
let integration = LocalFileSystem::new_with_prefix(root.path()).unwrap();

let location = Path::from("some_file");

let data = Bytes::from("arbitrary data");

integration
.put(&location, data.clone().into())
.await
.unwrap();

integration
.get_range(&location, 100..200)
.await
.expect_err("Should error with start range beyond end of file");
}

#[tokio::test]
async fn range_request_beyond_end_of_file() {
let root = TempDir::new().unwrap();
let integration = LocalFileSystem::new_with_prefix(root.path()).unwrap();

let location = Path::from("some_file");

let data = Bytes::from("arbitrary data");

integration
.put(&location, data.clone().into())
.await
.unwrap();

let read_data = integration.get_range(&location, 0..100).await.unwrap();
assert_eq!(&*read_data, data);
}

#[tokio::test]
#[cfg(target_family = "unix")]
// Fails on github actions runner (which runs the tests as root)
Expand Down
Loading