fix: panic on readbuf too small for block
This commit is contained in:
Generated
+1
-1
@@ -249,7 +249,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "droplet-rs"
|
name = "droplet-rs"
|
||||||
version = "0.16.2"
|
version = "0.16.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Drop-OSS"]
|
authors = ["Drop-OSS"]
|
||||||
name = "droplet-rs"
|
name = "droplet-rs"
|
||||||
version = "0.16.2"
|
version = "0.16.3"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
description = "Droplet is a `napi.rs` Rust/Node.js package full of high-performance and low-level utils for Drop"
|
description = "Droplet is a `napi.rs` Rust/Node.js package full of high-performance and low-level utils for Drop"
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ pub async fn generate_manifest_rusty<T: Fn(String), V: Fn(f32)>(
|
|||||||
let manifest = manifest.clone();
|
let manifest = manifest.clone();
|
||||||
let reader_semaphore = reader_semaphore.clone();
|
let reader_semaphore = reader_semaphore.clone();
|
||||||
futures.spawn(async move {
|
futures.spawn(async move {
|
||||||
let mut read_buf = vec![0; 1024 * 1024 * 64];
|
let mut read_buf = vec![0u8; 1024 * 1024 * 8];
|
||||||
|
|
||||||
let uuid = uuid::Uuid::new_v4().to_string();
|
let uuid = uuid::Uuid::new_v4().to_string();
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
@@ -189,9 +189,10 @@ pub async fn generate_manifest_rusty<T: Fn(String), V: Fn(f32)>(
|
|||||||
}
|
}
|
||||||
total += amount;
|
total += amount;
|
||||||
hasher.update(&read_buf[0..amount]);
|
hasher.update(&read_buf[0..amount]);
|
||||||
if total as u64 > length {
|
}
|
||||||
panic!("read too much: target {}, got {}", length, total);
|
|
||||||
}
|
if total as u64 > length {
|
||||||
|
panic!("read too much: target {}, got {}", length, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_length += length;
|
chunk_length += length;
|
||||||
|
|||||||
@@ -28,27 +28,53 @@ impl ZipVersionBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArchiveReader {
|
struct ArchiveReader<'a> {
|
||||||
archive: FileReader,
|
archive: FileReader,
|
||||||
|
prev_block: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncRead for ArchiveReader {
|
impl<'a> AsyncRead for ArchiveReader<'a> {
|
||||||
fn poll_read(
|
fn poll_read(
|
||||||
self: std::pin::Pin<&mut Self>,
|
mut self: std::pin::Pin<&mut Self>,
|
||||||
_cx: &mut std::task::Context<'_>,
|
_cx: &mut std::task::Context<'_>,
|
||||||
buf: &mut tokio::io::ReadBuf<'_>,
|
buf: &mut tokio::io::ReadBuf<'_>,
|
||||||
) -> std::task::Poll<std::io::Result<()>> {
|
) -> std::task::Poll<std::io::Result<()>> {
|
||||||
|
if let Some(block) = &mut self.prev_block {
|
||||||
|
let to_read = buf.remaining().min(block.len());
|
||||||
|
let result = block.split_off(..to_read);
|
||||||
|
let result = result.unwrap(); // SAFETY: above .min statement
|
||||||
|
buf.put_slice(result);
|
||||||
|
|
||||||
|
// If the block is empty, we can read more
|
||||||
|
if block.is_empty() {
|
||||||
|
self.prev_block = None;
|
||||||
|
} else {
|
||||||
|
return Poll::Ready(Ok(()));
|
||||||
|
}
|
||||||
|
}
|
||||||
let block = match self.archive.read_block() {
|
let block = match self.archive.read_block() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => return Poll::Ready(Err(std::io::Error::other(err.to_string()))),
|
Err(err) => return Poll::Ready(Err(std::io::Error::other(err.to_string()))),
|
||||||
};
|
};
|
||||||
|
|
||||||
let block = match block {
|
let mut block = match block {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return Poll::Ready(Ok(())),
|
None => return Poll::Ready(Ok(())),
|
||||||
};
|
};
|
||||||
|
|
||||||
buf.put_slice(block);
|
let write_amount = buf.remaining().min(block.len());
|
||||||
|
let to_write = block.split_off(..write_amount);
|
||||||
|
let to_write = to_write.unwrap(); // SAFETY: above .min statement
|
||||||
|
buf.put_slice(to_write);
|
||||||
|
|
||||||
|
if !block.is_empty() {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if self.prev_block.is_some() {
|
||||||
|
panic!("replacing prev_block while it contains data")
|
||||||
|
}
|
||||||
|
self.prev_block.replace(&block[buf.remaining()..]);
|
||||||
|
}
|
||||||
|
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +121,10 @@ impl VersionBackend for ZipVersionBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Box::new(ArchiveReader { archive }))
|
Ok(Box::new(ArchiveReader {
|
||||||
|
archive,
|
||||||
|
prev_block: None,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn peek_file(&self, sub_path: String) -> anyhow::Result<VersionFile> {
|
async fn peek_file(&self, sub_path: String) -> anyhow::Result<VersionFile> {
|
||||||
|
|||||||
Reference in New Issue
Block a user