address review: check short ZIP composite data and the layer mask channel before allocating the result

This commit is contained in:
Dylan M. Taylor
2026-11-03 23:28:47 +00:00
parent 0329e2e024
commit ae7d3e717a
+14
View File
@@ -293,6 +293,11 @@ impl Psd {
if comp == 0 && size.checked_mul(want).is_none_or(|need| need > r.remaining()) {
return Err(Error::Truncated);
}
if let PlaneStream::Zip(v) = &stream
&& size.checked_mul(want).is_none_or(|need| v.len() < need)
{
return Err(Error::Truncated);
}
// Opaque black until a channel says otherwise.
let mut data = budget.filled(n, [0.0f32, 0.0, 0.0, 1.0])?;
let mut black = if self.mode == ColorMode::Cmyk && want > 3 { Some(budget.filled(n, 0.0f32)?) } else { None };
@@ -357,6 +362,15 @@ impl Psd {
self.check_channel(c.offset, c.len, sw, sh)?;
}
}
// The layer mask's channel too: it is decoded after the result is allocated.
if let Some(m) = l.mask.filter(|m| !m.disabled)
&& let Some(c) = l.channels.iter().find(|c| c.id == -2)
{
let (mw, mh) = (m.rect.width() as usize, m.rect.height() as usize);
if mw > 0 && mh > 0 {
self.check_channel(c.offset, c.len, mw, mh)?;
}
}
let mut out = budget.filled(n, [0.0f32; 4])?;
if sw > 0 && sh > 0 {
// The source rows / columns that land inside the output (64-bit: file bounds can span