diff --git a/src/api/s3/get.rs b/src/api/s3/get.rs index 02500bf4..bb6fbd3d 100644 --- a/src/api/s3/get.rs +++ b/src/api/s3/get.rs @@ -698,9 +698,14 @@ fn body_from_blocks_range( // range, as well as their "true offset", which is their actual offset in the complete // file (whereas block.offset designates the offset of the block WITHIN THE PART // block.part_number, which is not the same in the case of a multipart upload) + // A version with no blocks yields no data, so the capacity hint must not index + // into an empty slice. + let capacity_block_size = all_blocks + .first() + .map_or(1024, |(_, b)| std::cmp::max(b.size, 1024)); let mut blocks: Vec<(VersionBlock, u64)> = Vec::with_capacity(std::cmp::min( all_blocks.len(), - 4 + ((end - begin) / std::cmp::max(all_blocks[0].1.size, 1024)) as usize, + 4 + ((end - begin) / capacity_block_size) as usize, )); let mut block_offset: u64 = 0; for (_, b) in all_blocks.iter() { diff --git a/src/api/s3/multipart.rs b/src/api/s3/multipart.rs index 16c8b6aa..1f493a24 100644 --- a/src/api/s3/multipart.rs +++ b/src/api/s3/multipart.rs @@ -476,7 +476,13 @@ pub async fn handle_complete_multipart_upload( size: total_size, etag: etag.clone(), }, - final_version.blocks.items()[0].1.hash, + final_version + .blocks + .items() + .first() + .ok_or_internal_error("Multipart completion produced a final version with no blocks")? + .1 + .hash, )); let final_object = Object::new(*bucket_id, key.clone(), vec![object_version]);