Skip to content

Commit 7a15e4b

Browse files
authored
Fix LocalFileSystem with range request that ends beyond end of file (apache#6751)
* Fix LocalFileSystem with range request that ends beyond end of file * fix windows * add comment * Seek error * fix seek check * remove windows flag * Get file length from file metadata
1 parent a962522 commit 7a15e4b

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

object_store/src/local.rs

+59-1
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,27 @@ pub(crate) fn chunked_stream(
868868
}
869869

870870
pub(crate) fn read_range(file: &mut File, path: &PathBuf, range: Range<u64>) -> Result<Bytes> {
871-
let to_read = range.end - range.start;
871+
let file_metadata = file.metadata().map_err(|e| Error::Metadata {
872+
source: e.into(),
873+
path: path.to_string_lossy().to_string(),
874+
})?;
875+
876+
// If none of the range is satisfiable we should error, e.g. if the start offset is beyond the
877+
// extents of the file
878+
let file_len = file_metadata.len();
879+
if range.start >= file_len {
880+
return Err(Error::InvalidRange {
881+
source: InvalidGetRange::StartTooLarge {
882+
requested: range.start,
883+
length: file_len,
884+
},
885+
}
886+
.into());
887+
}
888+
889+
// Don't read past end of file
890+
let to_read = range.end.min(file_len) - range.start;
891+
872892
file.seek(SeekFrom::Start(range.start)).map_err(|source| {
873893
let path = path.into();
874894
Error::Seek { source, path }
@@ -1131,6 +1151,44 @@ mod tests {
11311151
assert_eq!(&*read_data, data);
11321152
}
11331153

1154+
#[tokio::test]
1155+
async fn range_request_start_beyond_end_of_file() {
1156+
let root = TempDir::new().unwrap();
1157+
let integration = LocalFileSystem::new_with_prefix(root.path()).unwrap();
1158+
1159+
let location = Path::from("some_file");
1160+
1161+
let data = Bytes::from("arbitrary data");
1162+
1163+
integration
1164+
.put(&location, data.clone().into())
1165+
.await
1166+
.unwrap();
1167+
1168+
integration
1169+
.get_range(&location, 100..200)
1170+
.await
1171+
.expect_err("Should error with start range beyond end of file");
1172+
}
1173+
1174+
#[tokio::test]
1175+
async fn range_request_beyond_end_of_file() {
1176+
let root = TempDir::new().unwrap();
1177+
let integration = LocalFileSystem::new_with_prefix(root.path()).unwrap();
1178+
1179+
let location = Path::from("some_file");
1180+
1181+
let data = Bytes::from("arbitrary data");
1182+
1183+
integration
1184+
.put(&location, data.clone().into())
1185+
.await
1186+
.unwrap();
1187+
1188+
let read_data = integration.get_range(&location, 0..100).await.unwrap();
1189+
assert_eq!(&*read_data, data);
1190+
}
1191+
11341192
#[tokio::test]
11351193
#[cfg(target_family = "unix")]
11361194
// Fails on github actions runner (which runs the tests as root)

0 commit comments

Comments
 (0)