From b33dc356c45a88dc314c50db0ee5400382ac8f9f Mon Sep 17 00:00:00 2001 From: Marrub Date: Sat, 9 Mar 2019 17:07:18 -0500 Subject: [PATCH] gzip header loading --- source/marathon/defl.rs | 62 ++++++++++++++++++++++++++++++++++++++++ source/marathon/mod.rs | 1 + tests/data/gzipbad1.bin | Bin 0 -> 4 bytes tests/data/gzipbad2.bin | Bin 0 -> 12 bytes tests/data/gzipbad3.bin | Bin 0 -> 13 bytes tests/data/gzipbad4.bin | Bin 0 -> 14 bytes tests/data/gzipbad5.bin | Bin 0 -> 11 bytes tests/data/gzipbad6.bin | Bin 0 -> 11 bytes tests/data/gzipbad7.bin | Bin 0 -> 11 bytes tests/data/gzipok1.bin | Bin 0 -> 15 bytes tests/data/gzipok2.bin | Bin 0 -> 12 bytes tests/data/gzipok3.bin | Bin 0 -> 12 bytes tests/defl.rs | 29 +++++++++++++++++++ 13 files changed, 92 insertions(+) create mode 100644 source/marathon/defl.rs create mode 100644 tests/data/gzipbad1.bin create mode 100644 tests/data/gzipbad2.bin create mode 100644 tests/data/gzipbad3.bin create mode 100644 tests/data/gzipbad4.bin create mode 100644 tests/data/gzipbad5.bin create mode 100644 tests/data/gzipbad6.bin create mode 100644 tests/data/gzipbad7.bin create mode 100644 tests/data/gzipok1.bin create mode 100644 tests/data/gzipok2.bin create mode 100644 tests/data/gzipok3.bin create mode 100644 tests/defl.rs diff --git a/source/marathon/defl.rs b/source/marathon/defl.rs new file mode 100644 index 0000000..b07bd3b --- /dev/null +++ b/source/marathon/defl.rs @@ -0,0 +1,62 @@ +//! DEFLATE loader. + +use crate::durandal::err::*; + +/// Loads a GZIP file header. +pub fn load_gzip_header(b: &[u8]) -> ResultS +{ + const FHCRC: u8 = 1 << 1; + const FEXTRA: u8 = 1 << 2; + const FNAME: u8 = 1 << 3; + const FCOMMENT: u8 = 1 << 4; + + read_data! { + 10, LE in b => + id = u16[0]; + cm = u8[2]; + fl = u8[3]; + } + + if id != 0x8B1F || cm != 8 { + bail!("not gzip format"); + } + + let mut p = 10; + + if fl & FEXTRA != 0 { + read_data!(p + 2, LE in b => xlen = u16[p] usize;); + + if p + 2 + xlen > b.len() { + bail!("not enough data"); + } + + p += xlen; + } + + if fl & FNAME != 0 { + p = skip_zero_terminated_item(&b[p..])?; + } + + if fl & FCOMMENT != 0 { + p = skip_zero_terminated_item(&b[p..])?; + } + + if fl & FHCRC != 0 { + read_data!(p + 2, LE in b => _crc = u16[p];); + + p += 2; + } + + Ok(p) +} + +fn skip_zero_terminated_item(b: &[u8]) -> ResultS +{ + if let Some(i) = b.iter().position(|&n| n == 0) { + Ok(i) + } else { + bail!("no end of zero terminated item"); + } +} + +// EOF diff --git a/source/marathon/mod.rs b/source/marathon/mod.rs index 86fc790..f596331 100644 --- a/source/marathon/mod.rs +++ b/source/marathon/mod.rs @@ -1,5 +1,6 @@ //! Library for file format data readers. +pub mod defl; pub mod machdr; pub mod map; pub mod phy; diff --git a/tests/data/gzipbad1.bin b/tests/data/gzipbad1.bin new file mode 100644 index 0000000000000000000000000000000000000000..d56535ea992018f2c05b353da3d417f9a64fc7e0 GIT binary patch literal 4 Lcmb2|=3oE-0x=Q+0KEVJ literal 0 HcmV?d00001 diff --git a/tests/data/gzipok2.bin b/tests/data/gzipok2.bin new file mode 100644 index 0000000000000000000000000000000000000000..cafa27cdb56c9813bdf017e142cd80c585b9a7c8 GIT binary patch literal 12 Qcmb2|=HOre0p?W<010jZXaE2J literal 0 HcmV?d00001 diff --git a/tests/data/gzipok3.bin b/tests/data/gzipok3.bin new file mode 100644 index 0000000000000000000000000000000000000000..347a4aaa3c60cb84687e7e18ad94af91d2c95084 GIT binary patch literal 12 Qcmb2|<`7^20p?W<0137MZ~y=R literal 0 HcmV?d00001 diff --git a/tests/defl.rs b/tests/defl.rs new file mode 100644 index 0000000..58a503b --- /dev/null +++ b/tests/defl.rs @@ -0,0 +1,29 @@ +use maraiah::marathon::defl::{self, load_gzip_header}; + +include!("data/rand.rs"); + +#[test] +fn defl_must_succeed() +{ + assert!(load_gzip_header(include_bytes!("data/gzipok1.bin")).is_ok()); + assert!(load_gzip_header(include_bytes!("data/gzipok2.bin")).is_ok()); + assert!(load_gzip_header(include_bytes!("data/gzipok3.bin")).is_ok()); +} + +#[test] +fn defl_must_not_succeed() +{ + for inp in &RANDOM { + assert!(defl::load_gzip_header(inp).is_err()); + } + + assert!(load_gzip_header(include_bytes!("data/gzipbad1.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad2.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad3.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad4.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad5.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad6.bin")).is_err()); + assert!(load_gzip_header(include_bytes!("data/gzipbad7.bin")).is_err()); +} + +// EOF