parse unknown chunks at the end of "simple format" webp files

the spec seems to imply that simple format files should only contain a VP8/VP8L chunk, but it's not clear, and many of
the webp test vectors contain non-standard trailing informational chunks.
This commit is contained in:
Jessa 2023-10-13 17:03:29 -07:00
parent 9ad299dc99
commit 075e753fba
2 changed files with 23 additions and 25 deletions

View File

@ -181,11 +181,23 @@ pub async fn sanitize_async_with_config<R: AsyncRead + AsyncSkip>(input: R, conf
}
}
ensure_attach!(
!reader.has_remaining().await?,
ParseError::InvalidInput,
ExtraUnparsedInput,
);
// It's not clear whether the WebP spec accepts unknown chunks at the end of simple format files, but many of the
// WebP test vectors contain non-standard trailing informational chunks.
while reader.has_remaining().await? {
let (name, InputSpan { offset, len }) = reader
.read_any_header()
.await
.attach_printable("while parsing unknown chunks")?;
match name {
ALPH | ANIM | EXIF | ICCP | VP8 | VP8L | VP8X | XMP => {
bail_attach!(ParseError::InvalidChunkLayout, MultipleChunks(name))
}
ANMF => bail_attach!(ParseError::InvalidChunkLayout, "non-contiguous ANMF chunk"),
_ => ensure_attach!(config.allow_unknown_chunks, ParseError::UnsupportedChunk(name)),
}
reader.skip_data().await?;
log::info!("{name} @ 0x{offset:08x}: {len} bytes");
}
ensure_attach!(
!file_reader.has_remaining().await?,
@ -227,22 +239,6 @@ async fn sanitize_extended<R: AsyncRead + AsyncSkip>(
log::info!("{name} @ 0x{offset:08x}: {len} bytes", name = XMP);
}
while reader.has_remaining().await? {
let (name, InputSpan { offset, len }) = reader
.read_any_header()
.await
.attach_printable("while parsing unknown chunks")?;
match name {
ALPH | ANIM | EXIF | ICCP | VP8 | VP8L | VP8X | XMP => {
bail_attach!(ParseError::InvalidChunkLayout, MultipleChunks(name))
}
ANMF => bail_attach!(ParseError::InvalidChunkLayout, "non-contiguous ANMF chunk"),
_ => ensure_attach!(config.allow_unknown_chunks, ParseError::UnsupportedChunk(name)),
}
reader.skip_data().await?;
log::info!("{name} @ 0x{offset:08x}: {len} bytes");
}
Ok(())
}

View File

@ -1,20 +1,22 @@
use std::io::Cursor;
use mediasan_common_test::{init_logger, TestType};
use webpsan::sanitize;
use webpsan::{sanitize_with_config, Config};
const CONFIG: Config = Config { allow_unknown_chunks: true };
#[test]
fn test_data() {
init_logger();
mediasan_common_test::test_data(".webp", |test_type, data| match test_type {
TestType::Valid => {
sanitize(Cursor::new(data)).unwrap();
sanitize_with_config(Cursor::new(data), CONFIG).unwrap();
}
TestType::InvalidPass => {
sanitize(Cursor::new(data)).unwrap();
sanitize_with_config(Cursor::new(data), CONFIG).unwrap();
}
TestType::InvalidFail => {
dbg!(sanitize(Cursor::new(data)).unwrap_err());
dbg!(sanitize_with_config(Cursor::new(data), CONFIG).unwrap_err());
}
});
}