diff --git a/iroh/src/client/blobs.rs b/iroh/src/client/blobs.rs index 89d2904405..91b40b9098 100644 --- a/iroh/src/client/blobs.rs +++ b/iroh/src/client/blobs.rs @@ -1168,6 +1168,21 @@ mod tests { assert_eq!(reader.size(), 1024 * 128); assert_eq!(reader.response_size, 20); + // out of bounds - too long + let res = client.blobs().read_at(hash, 0, Some(1024 * 128 + 1)).await; + let err = res.unwrap_err(); + assert!(err.to_string().contains("out of bound")); + + // out of bounds - offset larger than blob + let res = client.blobs().read_at(hash, 1024 * 128 + 1, None).await; + let err = res.unwrap_err(); + assert!(err.to_string().contains("out of range")); + + // out of bounds - offset + length too large + let res = client.blobs().read_at(hash, 1024 * 127, Some(1025)).await; + let err = res.unwrap_err(); + assert!(err.to_string().contains("out of bound")); + Ok(()) } diff --git a/iroh/src/node/rpc.rs b/iroh/src/node/rpc.rs index e38740203b..bcdb84c87b 100644 --- a/iroh/src/node/rpc.rs +++ b/iroh/src/node/rpc.rs @@ -1230,6 +1230,24 @@ impl Handler { let entry = db.get(&req.hash).await?; let entry = entry.ok_or_else(|| anyhow!("Blob not found"))?; let size = entry.size(); + + anyhow::ensure!( + req.offset <= size.value(), + "requested offset is out of range: {} > {:?}", + req.offset, + size + ); + + let len = req.len.unwrap_or((size.value() - req.offset) as usize); + + anyhow::ensure!( + req.offset + len as u64 <= size.value(), + "requested range is out of bounds: offset: {}, len: {} > {:?}", + req.offset, + len, + size + ); + tx.send(Ok(ReadAtResponse::Entry { size, is_complete: entry.is_complete(), @@ -1237,8 +1255,6 @@ impl Handler { .await?; let mut reader = entry.data_reader().await?; - let len = req.len.unwrap_or((size.value() - req.offset) as usize); - let (num_chunks, chunk_size) = if len <= max_chunk_size { (1, len) } else {