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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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,
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 })?;

// 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