Some(header) => header,
};
+ header.check_header_size()?;
+
if header.htype == format::PXAR_HARDLINK {
// The only "dangling" header without an 'Entry' in front of it because it does not
// carry its own metadata.
)
};
seq_read_exact(&mut self.input, dest).await?;
+ self.current_header.check_header_size()?;
+
Ok(())
}
where
T: SeqWrite + ?Sized,
{
+ let header = format::Header::with_content_size(htype, data.len() as u64);
+ header.check_header_size()?;
+
seq_write_struct(
&mut *output,
- format::Header::with_content_size(htype, data.len() as u64),
+ header,
)
.await?;
seq_write_all(output, data).await
where
T: SeqWrite + ?Sized,
{
+ let header = format::Header::with_content_size(htype, 1 + data.len() as u64);
+ header.check_header_size()?;
+
seq_write_struct(
&mut *output,
- format::Header::with_content_size(htype, 1 + data.len() as u64),
+ header,
)
.await?;
seq_write_all(&mut *output, data).await?;
let file_offset = seq_write_position(&mut self.output).await?;
self.start_file_do(Some(metadata), file_name).await?;
+ let header = format::Header::with_content_size(format::PXAR_PAYLOAD, file_size);
+ header.check_header_size()?;
+
seq_write_struct(
&mut self.output,
- format::Header::with_content_size(format::PXAR_PAYLOAD, file_size),
+ header,
)
.await?;
pub fn content_size(&self) -> u64 {
self.full_size() - (size_of::<Self>() as u64)
}
+
+ #[inline]
+ pub fn max_content_size(&self) -> u64 {
+ match self.htype {
+ // + null-termination
+ PXAR_FILENAME => crate::util::MAX_FILENAME_LEN + 1,
+ // + null-termination
+ PXAR_SYMLINK => crate::util::MAX_PATH_LEN + 1,
+ // + null-termination + offset
+ PXAR_HARDLINK => crate::util::MAX_PATH_LEN + 1 + (size_of::<u64>() as u64),
+ PXAR_DEVICE => size_of::<Device>() as u64,
+ PXAR_XATTR | PXAR_FCAPS => crate::util::MAX_XATTR_LEN,
+ PXAR_ACL_USER | PXAR_ACL_DEFAULT_USER => size_of::<acl::User>() as u64,
+ PXAR_ACL_GROUP | PXAR_ACL_DEFAULT_GROUP => size_of::<acl::Group>() as u64,
+ PXAR_ACL_DEFAULT => size_of::<acl::Default>() as u64,
+ PXAR_ACL_GROUP_OBJ => size_of::<acl::GroupObject> as u64,
+ PXAR_QUOTA_PROJID => size_of::<QuotaProjectId>() as u64,
+ PXAR_ENTRY => size_of::<Entry>() as u64,
+ PXAR_PAYLOAD | PXAR_GOODBYE => u64::MAX - (size_of::<Self>() as u64),
+ _ => u64::MAX - (size_of::<Self>() as u64),
+ }
+ }
+
+ #[inline]
+ pub fn check_header_size(&self) -> io::Result<()> {
+ if self.full_size() < size_of::<Header>() as u64 {
+ io_bail!("invalid header {} - too small ({})", self, self.full_size());
+ }
+
+ if self.content_size() > self.max_content_size() {
+ io_bail!("invalid content size ({} > {}) of entry with {}", self.content_size(), self.max_content_size(), self);
+ }
+ Ok(())
+ }
+}
}
#[derive(Clone, Debug, Default, Endian)]
unsafe fn ignore_drop(_: *const ()) {}
+pub const MAX_PATH_LEN:u64 = 4 * 1024;
+// let's play it safe
+pub const MAX_FILENAME_LEN:u64 = MAX_PATH_LEN;
+// name + attr
+pub const MAX_XATTR_LEN:u64 = 255 + 64*1024;
+
pub fn validate_filename(name: &[u8]) -> io::Result<()> {
if name.is_empty() {
io_bail!("illegal path found (empty)");
io_bail!("illegal path found: '..'");
}
+ if (name.len() as u64) > MAX_FILENAME_LEN {
+ io_bail!("filename too long (> {})", MAX_FILENAME_LEN);
+ }
+
Ok(())
}