From 73ffc417c6b40b157b9b0815a2993e03ca6825ba Mon Sep 17 00:00:00 2001 From: kromych Date: Sat, 22 Oct 2022 23:18:45 -0700 Subject: [PATCH 1/2] Cargo fmt, cargo pedantic --- benches/bench.rs | 58 +++++++----- build.rs | 6 +- src/data.rs | 100 +++++++++------------ src/error.rs | 2 +- src/lib.rs | 2 +- src/lznt1.rs | 222 +++++++++++++++++++++------------------------ tests/test.rs | 229 ++++++++++++++++++++++++++++------------------- 7 files changed, 322 insertions(+), 297 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index 12edb4c..83252a7 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,17 +1,17 @@ #![feature(test)] -extern crate test; extern crate lzxpress; +extern crate test; use test::Bencher; extern "C" { - fn decompress_lznt1( + fn decompress_lznt1( in_buf: *const u8, in_buf_max_size: i32, out_buf: *mut u8, out_buf_max_size: i32, - pout_buf_size: *mut i32 + pout_buf_size: *mut i32, ) -> bool; } @@ -20,7 +20,7 @@ extern "C" { fn bench_lznt1_decompress_rtl(b: &mut Bencher) { let compression_format_lznt1 = 0x0002 as u16; let compression_engine_standard = 0x0000 as u16; - use ntapi::ntrtl::{RtlDecompressBuffer}; + use ntapi::ntrtl::RtlDecompressBuffer; let compressed_data = include_bytes!("../tests/block1.compressed.bin"); let mut mutable_compressed_data = compressed_data.to_vec(); @@ -36,7 +36,14 @@ fn bench_lznt1_decompress_rtl(b: &mut Bencher) { let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); - let _ntstatus = RtlDecompressBuffer(compression_format_lznt1 | compression_engine_standard, pdst, dstlen, psrc, srclen, &mut dstlen2); + let _ntstatus = RtlDecompressBuffer( + compression_format_lznt1 | compression_engine_standard, + pdst, + dstlen, + psrc, + srclen, + &mut dstlen2, + ); dst.set_len(dstlen2 as usize); }; @@ -48,22 +55,17 @@ fn bench_lznt1_decompress_cpp(b: &mut Bencher) { let compressed_data = include_bytes!("../tests/block1.compressed.bin"); b.iter(|| { - let _ret = unsafe { + unsafe { let psrc = compressed_data.as_ptr(); let srclen = compressed_data.len() as i32; - let dstlen = 0x100000; + let dstlen = 0x0010_0000; let mut dstlen2: i32 = 0; let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); - let _status = decompress_lznt1( - psrc, - srclen, - pdst, - dstlen, - &mut dstlen2); + let _status = decompress_lznt1(psrc, srclen, pdst, dstlen, &mut dstlen2); dst.set_len(dstlen2 as usize); }; }); @@ -83,9 +85,9 @@ fn bench_lznt1_decompress2_push(b: &mut Bencher) { let compressed_data = include_bytes!("../tests/block1.compressed.bin"); b.iter(|| { - let dstlen = 0x100000; + let dstlen = 0x0010_0000; let mut out_buf: Vec = Vec::with_capacity(dstlen); - let _uncompressed = lzxpress::lznt1::decompress2_push(compressed_data, &mut out_buf).unwrap(); + lzxpress::lznt1::decompress2_push(compressed_data, &mut out_buf).unwrap(); }); } @@ -94,24 +96,25 @@ fn bench_lznt1_decompress2_no_push(b: &mut Bencher) { let compressed_data = include_bytes!("../tests/block1.compressed.bin"); b.iter(|| { - let dstlen = 0x100000; + let dstlen = 0x0010_0000; let mut out_buf: Vec = Vec::with_capacity(dstlen); unsafe { out_buf.set_len(dstlen); } - let _uncompressed = lzxpress::lznt1::decompress2_no_push(compressed_data, &mut out_buf).unwrap(); + lzxpress::lznt1::decompress2_no_push(compressed_data, &mut out_buf).unwrap(); }); } - #[bench] #[cfg(windows)] fn bench_lzxpress_decompress_rtl(b: &mut Bencher) { let compression_format_xpress = 0x0003 as u16; let compression_engine_standard = 0x0000 as u16; - use ntapi::ntrtl::{RtlDecompressBuffer}; + use ntapi::ntrtl::RtlDecompressBuffer; - let compressed_data = include_bytes!("../tests/clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904"); + let compressed_data = include_bytes!( + "../tests/clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904" + ); let mut mutable_compressed_data = compressed_data.to_vec(); b.iter(|| { @@ -125,16 +128,25 @@ fn bench_lzxpress_decompress_rtl(b: &mut Bencher) { let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); - let _ntstatus = RtlDecompressBuffer(compression_format_xpress | compression_engine_standard, pdst, dstlen, psrc, srclen, &mut dstlen2); + let _ntstatus = RtlDecompressBuffer( + compression_format_xpress | compression_engine_standard, + pdst, + dstlen, + psrc, + srclen, + &mut dstlen2, + ); }; }); } #[bench] fn bench_lzxpress_decompress(b: &mut Bencher) { - let compressed_data = include_bytes!("../tests/clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904"); + let compressed_data = include_bytes!( + "../tests/clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904" + ); b.iter(|| { let _uncompressed = lzxpress::data::decompress(compressed_data); }); -} \ No newline at end of file +} diff --git a/build.rs b/build.rs index 4be66ba..0918295 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,5 @@ extern crate cc; fn main() { - cc::Build::new() - .file("tests/lznt1.c") - .compile("libfoo.a"); -} \ No newline at end of file + cc::Build::new().file("tests/lznt1.c").compile("libfoo.a"); +} diff --git a/src/data.rs b/src/data.rs index c3017b8..adb2d93 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,48 +1,38 @@ -use std::mem; use std::cmp; +use std::mem; pub use crate::error::Error; -macro_rules! store32le{ - ($dst:expr,$idx:expr,$val:expr)=>{ - { - $dst[$idx + 0] = $val as u8; - $dst[$idx + 1] = ($val >> 8) as u8; - $dst[$idx + 2] = ($val >> 16) as u8; - $dst[$idx + 3] = ($val >> 24) as u8; - } - } - } - -macro_rules! load16le{ - ($dst:expr,$src:expr,$idx:expr)=>{ - { - $dst = (u32::from($src[$idx + 1]) << 8 - | u32::from($src[$idx])) as usize; - } - } +macro_rules! store32le { + ($dst:expr,$idx:expr,$val:expr) => {{ + $dst[$idx + 0] = $val as u8; + $dst[$idx + 1] = ($val >> 8) as u8; + $dst[$idx + 2] = ($val >> 16) as u8; + $dst[$idx + 3] = ($val >> 24) as u8; + }}; +} + +macro_rules! load16le { + ($dst:expr,$src:expr,$idx:expr) => {{ + $dst = (u32::from($src[$idx + 1]) << 8 | u32::from($src[$idx])) as usize; + }}; } -macro_rules! load32le{ - ($dst:expr,$src:expr,$idx:expr)=>{ - { - $dst = ((u32::from($src[$idx + 3]) << 24) +macro_rules! load32le { + ($dst:expr,$src:expr,$idx:expr) => {{ + $dst = ((u32::from($src[$idx + 3]) << 24) | (u32::from($src[$idx + 2]) << 16) - | (u32::from($src[$idx + 1]) << 8) + | (u32::from($src[$idx + 1]) << 8) | u32::from($src[$idx])) as usize; - } - } + }}; } -pub fn decompress( - in_buf: &[u8] -) -> Result, Error> -{ - let mut out_idx: usize = 0; - let mut in_idx: usize = 0; +pub fn decompress(in_buf: &[u8]) -> Result, Error> { + let mut out_idx: usize = 0; + let mut in_idx: usize = 0; let mut nibble_idx: usize = 0; - let mut flags: usize = 0; + let mut flags: usize = 0; let mut flag_count: usize = 0; let mut length: usize; @@ -83,7 +73,7 @@ pub fn decompress( in_idx += mem::size_of::(); offset = (length / 8) + 1; - length = length % 8; + length %= 8; if length == 7 { if nibble_idx == 0 { @@ -149,29 +139,25 @@ pub fn decompress( Ok(out_buf) } -pub fn compress( - in_buf: &[u8] -) -> Result, Error> -{ - - let mut in_idx: usize = 0; - let mut out_idx: usize; +pub fn compress(in_buf: &[u8]) -> Result, Error> { + let mut in_idx: usize = 0; + let mut out_idx: usize; let mut byte_left: usize; - let mut max_off: usize; + let mut max_off: usize; let mut match_off: usize; - let mut max_len: usize; + let mut max_len: usize; let mut best_len: usize; - let mut flags: u32 = 0; - let mut flag_count: u32 = 0; + let mut flags: u32 = 0; + let mut flag_count: u32 = 0; let mut flag_out_off: usize = 0; let mut nibble_index: usize = 0; let mut metadata_size: usize; - let mut metadata: usize; - let mut _dest_off: usize; + let mut metadata: usize; + let mut _dest_off: usize; let mut str1_off: usize; let mut str2_off: usize; @@ -247,7 +233,7 @@ pub fn compress( if match_len < 7 { // Classical meta-data - metadata = (match_off << 3) + match_len; + metadata = (match_off << 3) + match_len; out_buf.push(metadata as u8); out_buf.push((metadata >> 8) as u8); metadata_size += mem::size_of::(); @@ -272,23 +258,21 @@ pub fn compress( has_extra_len = true; } + } else if match_len < 15 { + out_buf[nibble_index] |= (match_len << 4) as u8; + nibble_index = 0; } else { - if match_len < 15 { - out_buf[nibble_index] |= (match_len << 4) as u8; - nibble_index = 0; - } else { - out_buf[nibble_index] |= (15 << 4) as u8; - nibble_index = 0; + out_buf[nibble_index] |= (15 << 4) as u8; + nibble_index = 0; - has_extra_len = true; - } + has_extra_len = true; } if has_extra_len { match_len -= 15; if match_len < 255 { - out_buf.push(match_len as u8); + out_buf.push(match_len as u8); metadata_size += mem::size_of::(); } else { out_buf.push(255); @@ -337,4 +321,4 @@ pub fn compress( store32le!(out_buf, flag_out_off, flags); Ok(out_buf) -} \ No newline at end of file +} diff --git a/src/error.rs b/src/error.rs index 5db65dd..8b0ec48 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,4 +7,4 @@ pub enum Error { CorruptedData, // An unknown error Other, -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 1e68350..a68da36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,3 @@ -pub mod error; pub mod data; +pub mod error; pub mod lznt1; diff --git a/src/lznt1.rs b/src/lznt1.rs index f17a7a4..68f937e 100644 --- a/src/lznt1.rs +++ b/src/lznt1.rs @@ -4,42 +4,31 @@ pub use crate::error::Error; const LZNT1_COMPRESSED_FLAG: usize = 0x8000; -macro_rules! load16le{ - ($dst:expr,$src:expr,$idx:expr)=>{ - { - $dst = (u32::from($src[$idx + 1]) << 8 - | u32::from($src[$idx])) as usize; - } - } +macro_rules! load16le { + ($dst:expr,$src:expr,$idx:expr) => {{ + $dst = (u32::from($src[$idx + 1]) << 8 | u32::from($src[$idx])) as usize; + }}; } -pub fn decompress( - in_buf: &[u8] -) -> Result, Error> -{ - +pub fn decompress(in_buf: &[u8]) -> Result, Error> { let mut out_buf: Vec = Vec::with_capacity(in_buf.len()); match decompress2_push(in_buf, &mut out_buf) { - Err(e) => println!("{:?}", e), - _ => () + Err(e) => println!("{e:?}"), + _ => (), } - + Ok(out_buf) } -pub fn decompress2_push_old( - in_buf: &[u8], - out_buf: &mut Vec -) -> Result<(), Error> -{ +pub fn decompress2_push_old(in_buf: &[u8], out_buf: &mut Vec) -> Result<(), Error> { let mut out_idx: usize = 0; - let mut in_idx: usize = 0; + let mut in_idx: usize = 0; - let mut header: usize; - let mut length: usize; - let mut block_len: usize; - let mut offset: usize; + let mut header: usize; + let mut length: usize; + let mut block_len: usize; + let mut offset: usize; let mut _block_id = 0; while in_idx < in_buf.len() { @@ -50,90 +39,88 @@ pub fn decompress2_push_old( if block_len > (in_buf.len() - in_idx) { return Err(Error::MemLimit); - } else { - if header & LZNT1_COMPRESSED_FLAG != 0 { - let in_base_idx = in_idx; - let out_base_idx = out_idx; - while (in_idx - in_base_idx) < block_len { - if in_idx >= in_buf.len() { - break; - } + } else if header & LZNT1_COMPRESSED_FLAG != 0 { + let in_base_idx = in_idx; + let out_base_idx = out_idx; + while (in_idx - in_base_idx) < block_len { + if in_idx >= in_buf.len() { + break; + } - let flags = in_buf[in_idx]; - in_idx += mem::size_of::(); + let flags = in_buf[in_idx]; + in_idx += mem::size_of::(); - for n in 0..8 { - if ((flags >> n) & 1) == 0 { - if in_idx >= in_buf.len() || (in_idx - in_base_idx) >= block_len { - break; - } - out_buf.push(in_buf[in_idx]); - out_idx += mem::size_of::(); - in_idx += mem::size_of::(); - } else { - let flag; - if in_idx >= in_buf.len() || (in_idx - in_base_idx) >= block_len { - break; - } - load16le!(flag, in_buf, in_idx); - in_idx += mem::size_of::(); - - let mut pos = out_idx - out_base_idx - 1; - let mut l_mask = 0xFFF; - let mut o_shift = 12; - while pos >= 0x10 { - l_mask >>= 1; - o_shift -= 1; - pos >>= 1; - } + for n in 0..8 { + if ((flags >> n) & 1) == 0 { + if in_idx >= in_buf.len() || (in_idx - in_base_idx) >= block_len { + break; + } + out_buf.push(in_buf[in_idx]); + out_idx += mem::size_of::(); + in_idx += mem::size_of::(); + } else { + let flag; + if in_idx >= in_buf.len() || (in_idx - in_base_idx) >= block_len { + break; + } + load16le!(flag, in_buf, in_idx); + in_idx += mem::size_of::(); + + let mut pos = out_idx - out_base_idx - 1; + let mut l_mask = 0xFFF; + let mut o_shift = 12; + while pos >= 0x10 { + l_mask >>= 1; + o_shift -= 1; + pos >>= 1; + } - length = (flag & l_mask) + 3; - offset = (flag >> o_shift) + 1; - if length >= offset { - let count = (0xfff / offset) + 1; - if offset > out_idx { - return Err(Error::CorruptedData); - } + length = (flag & l_mask) + 3; + offset = (flag >> o_shift) + 1; + if length >= offset { + let count = (0xfff / offset) + 1; + if offset > out_idx { + return Err(Error::CorruptedData); + } - let chunk_pos = out_idx - offset; - let chunk_len = offset; - - let mut x = 0; - while x < length { - for _i in 0..count { - for _j in 0..chunk_len { - out_buf.push(out_buf[chunk_pos + _j]); - out_idx += mem::size_of::(); - x += 1; - if x >= length { - break; - } - } + let chunk_pos = out_idx - offset; + let chunk_len = offset; + let mut x = 0; + while x < length { + for _i in 0..count { + for _j in 0..chunk_len { + out_buf.push(out_buf[chunk_pos + _j]); + out_idx += mem::size_of::(); + x += 1; if x >= length { break; } } - } - } else { - for _i in 0..length { - if offset > out_idx { - return Err(Error::CorruptedData); + + if x >= length { + break; } - out_buf.push(out_buf[out_idx - offset]); - out_idx += mem::size_of::(); } } + } else { + for _i in 0..length { + if offset > out_idx { + return Err(Error::CorruptedData); + } + out_buf.push(out_buf[out_idx - offset]); + out_idx += mem::size_of::(); + } } } } - } else { - // Not compressed - for _i in 0..block_len { - out_buf.push(in_buf[in_idx]); - out_idx += mem::size_of::(); - in_idx += mem::size_of::(); - } + } + } else { + // Not compressed + for _i in 0..block_len { + out_buf.push(in_buf[in_idx]); + out_idx += mem::size_of::(); + in_idx += mem::size_of::(); } } @@ -144,19 +131,14 @@ pub fn decompress2_push_old( Ok(()) } - -pub fn decompress2_push( - in_buf: &[u8], - out_buf: &mut Vec -) -> Result<(), Error> -{ +pub fn decompress2_push(in_buf: &[u8], out_buf: &mut Vec) -> Result<(), Error> { let mut out_idx: usize = 0; - let mut in_idx: usize = 0; + let mut in_idx: usize = 0; - let mut header: usize; - let mut length: usize; - let mut chunk_len: usize; - let mut offset: usize; + let mut header: usize; + let mut length: usize; + let mut chunk_len: usize; + let mut offset: usize; let mut _block_id = 0; @@ -227,7 +209,7 @@ pub fn decompress2_push( length = out_buf_max_size - out_idx; } */ - + for _i in 0..length { if offset > out_idx { return Err(Error::CorruptedData); @@ -241,7 +223,9 @@ pub fn decompress2_push( flag_bit = (flag_bit + 1) % 8; if flag_bit == 0 { - if (in_idx - in_base_idx) >= chunk_len { break; } + if (in_idx - in_base_idx) >= chunk_len { + break; + } flags = in_buf[in_idx]; in_idx += mem::size_of::(); } @@ -262,18 +246,14 @@ pub fn decompress2_push( Ok(()) } -pub fn decompress2_no_push( - in_buf: &[u8], - out_buf: &mut Vec -) -> Result<(), Error> -{ +pub fn decompress2_no_push(in_buf: &[u8], out_buf: &mut Vec) -> Result<(), Error> { let mut out_idx: usize = 0; - let mut in_idx: usize = 0; + let mut in_idx: usize = 0; - let mut header: usize; - let mut length: usize; - let mut chunk_len: usize; - let mut offset: usize; + let mut header: usize; + let mut length: usize; + let mut chunk_len: usize; + let mut offset: usize; let mut _block_id = 0; @@ -351,7 +331,7 @@ pub fn decompress2_no_push( if (out_idx + length) >= out_buf_max_size { length = out_buf_max_size - out_idx; } - + for _i in 0..length { if offset > out_idx { return Err(Error::CorruptedData); @@ -368,7 +348,9 @@ pub fn decompress2_no_push( flag_bit = (flag_bit + 1) % 8; if flag_bit == 0 { - if (in_idx - in_base_idx) >= chunk_len { break; } + if (in_idx - in_base_idx) >= chunk_len { + break; + } flags = in_buf[in_idx]; in_idx += mem::size_of::(); } @@ -395,4 +377,4 @@ pub fn decompress2_no_push( } Ok(()) -} \ No newline at end of file +} diff --git a/tests/test.rs b/tests/test.rs index a22d397..bd7f811 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2,55 +2,50 @@ extern crate lzxpress; use std::str; -const TEST_STRING: &'static str = "this is a test. and this is a test too"; -const TEST_DATA: &'static [u8] = &[ - 0x00, 0x20, 0x00, 0x04, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x10, 0x00, 0x61, 0x20, 0x74, 0x65, 0x73, - 0x74, 0x2E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x9F, - 0x00, 0x04, 0x20, 0x74, 0x6F, 0x6F ]; +const TEST_STRING: &str = "this is a test. and this is a test too"; +const TEST_DATA: &[u8] = &[ + 0x00, 0x20, 0x00, 0x04, 0x74, 0x68, 0x69, 0x73, 0x20, 0x10, 0x00, 0x61, 0x20, 0x74, 0x65, 0x73, + 0x74, 0x2E, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x9F, 0x00, 0x04, 0x20, 0x74, 0x6F, 0x6F, +]; // Issue 19382: samba:fuzz_lzxpress: Heap-buffer-overflow in lzxpress_decompress // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20083&q=samba&can=2 -const TEST_OSSFUZZ_20083_DATA: &'static [u8] = include_bytes!("clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904"); -const TEST_OSSFUZZ_5698056963227648_DATA: &'static [u8] = include_bytes!("clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5698056963227648"); +const TEST_OSSFUZZ_20083_DATA: &[u8] = + include_bytes!("clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5724999789051904"); +const TEST_OSSFUZZ_5698056963227648_DATA: &[u8] = + include_bytes!("clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5698056963227648"); // Examples: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/72da4f8d-2ba3-437d-b772-2e4173713a0b?redirectedfrom=MSDN -const TEST_STRING2: &'static str = "abcdefghijklmnopqrstuvwxyz"; -const TEST_DATA2: &'static [u8] = &[ - 0x3f, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a ]; - -const TEST_STRING3: &'static str = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; -const TEST_DATA3: &'static [u8] = &[ - 0xff, 0xff, 0xff, 0x1f, 0x61, 0x62, 0x63, 0x17, - 0x00, 0x0f, 0xff, 0x26, 0x01 ]; - - -const TEST_LZNT1_STRING1: &'static str = "F# F# G A A G F# E D D E F# F# E E F# F# G A A G F# E D D E F# E D D E E F# D E F# G F# D E F# G F# E D E A F# F# G A A G F# E D D E F# E D D\0"; -const TEST_LZNT1_DATA1: &'static [u8] = &[ - 0x38, 0xb0, 0x88, 0x46, 0x23, 0x20, 0x00, 0x20, - 0x47, 0x20, 0x41, 0x00, 0x10, 0xa2, 0x47, 0x01, - 0xa0, 0x45, 0x20, 0x44, 0x00, 0x08, 0x45, 0x01, - 0x50, 0x79, 0x00, 0xc0, 0x45, 0x20, 0x05, 0x24, - 0x13, 0x88, 0x05, 0xb4, 0x02, 0x4a, 0x44, 0xef, - 0x03, 0x58, 0x02, 0x8c, 0x09, 0x16, 0x01, 0x48, - 0x45, 0x00, 0xbe, 0x00, 0x9e, 0x00, 0x04, 0x01, - 0x18, 0x90, 0x00 +const TEST_STRING2: &str = "abcdefghijklmnopqrstuvwxyz"; +const TEST_DATA2: &[u8] = &[ + 0x3f, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, +]; + +const TEST_STRING3: &str = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; +const TEST_DATA3: &[u8] = &[ + 0xff, 0xff, 0xff, 0x1f, 0x61, 0x62, 0x63, 0x17, 0x00, 0x0f, 0xff, 0x26, 0x01, +]; + +const TEST_LZNT1_STRING1: &str = "F# F# G A A G F# E D D E F# F# E E F# F# G A A G F# E D D E F# E D D E E F# D E F# G F# D E F# G F# E D E A F# F# G A A G F# E D D E F# E D D\0"; +const TEST_LZNT1_DATA1: &[u8] = &[ + 0x38, 0xb0, 0x88, 0x46, 0x23, 0x20, 0x00, 0x20, 0x47, 0x20, 0x41, 0x00, 0x10, 0xa2, 0x47, 0x01, + 0xa0, 0x45, 0x20, 0x44, 0x00, 0x08, 0x45, 0x01, 0x50, 0x79, 0x00, 0xc0, 0x45, 0x20, 0x05, 0x24, + 0x13, 0x88, 0x05, 0xb4, 0x02, 0x4a, 0x44, 0xef, 0x03, 0x58, 0x02, 0x8c, 0x09, 0x16, 0x01, 0x48, + 0x45, 0x00, 0xbe, 0x00, 0x9e, 0x00, 0x04, 0x01, 0x18, 0x90, 0x00, ]; -const TEST_LZNT1_COMPRESSED_DATA: &'static [u8] = include_bytes!("block1.compressed.bin"); -const TEST_LZNT1_UNCOMPRESSED_DATA: &'static [u8] = include_bytes!("block1.uncompressed.bin"); +const TEST_LZNT1_COMPRESSED_DATA: &[u8] = include_bytes!("block1.compressed.bin"); +const TEST_LZNT1_UNCOMPRESSED_DATA: &[u8] = include_bytes!("block1.uncompressed.bin"); extern "C" { fn decompress_lznt1( - in_buf: *const u8, - in_buf_max_size: i32, - out_buf: *mut u8, - out_buf_max_size: i32, - pout_buf_size: *mut i32 - ) -> bool; + in_buf: *const u8, + in_buf_max_size: i32, + out_buf: *mut u8, + out_buf_max_size: i32, + pout_buf_size: *mut i32, + ) -> bool; } #[cfg(test)] @@ -62,23 +57,32 @@ mod tests { let uncompressed = lzxpress::data::decompress(TEST_DATA).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } - assert!(uncompressed.len() == TEST_STRING.len(), "uncompressed.len = {}, TEST_STRING.len = {}", uncompressed.len(), TEST_STRING.len()); + assert!( + uncompressed.len() == TEST_STRING.len(), + "uncompressed.len = {}, TEST_STRING.len = {}", + uncompressed.len(), + TEST_STRING.len() + ); assert_eq!(uncompressed, TEST_STRING.as_bytes()); } - #[test] fn test_decompress2() { let uncompressed = lzxpress::data::decompress(TEST_DATA2).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } - assert!(uncompressed.len() == TEST_STRING2.len(), "uncompressed.len = {}, TEST_STRING.len = {}", uncompressed.len(), TEST_STRING2.len()); + assert!( + uncompressed.len() == TEST_STRING2.len(), + "uncompressed.len = {}, TEST_STRING.len = {}", + uncompressed.len(), + TEST_STRING2.len() + ); assert_eq!(uncompressed, TEST_STRING2.as_bytes()); } @@ -87,10 +91,15 @@ mod tests { let uncompressed = lzxpress::data::decompress(TEST_DATA3).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } - assert!(uncompressed.len() == TEST_STRING3.len(), "uncompressed.len = {}, TEST_STRING.len = {}", uncompressed.len(), TEST_STRING3.len()); + assert!( + uncompressed.len() == TEST_STRING3.len(), + "uncompressed.len = {}, TEST_STRING.len = {}", + uncompressed.len(), + TEST_STRING3.len() + ); assert_eq!(uncompressed, TEST_STRING3.as_bytes()); } @@ -100,7 +109,7 @@ mod tests { match result { Err(_e) => assert!(true), - _ => panic!("This test should fail because of failed data.") + _ => panic!("This test should fail because of failed data."), } } @@ -110,7 +119,7 @@ mod tests { match result { Err(_e) => assert!(true), - _ => panic!("This test should fail because of failed data.") + _ => panic!("This test should fail because of failed data."), } } @@ -123,24 +132,33 @@ mod tests { let uncompressed = lzxpress::data::decompress(compressed.as_slice()).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } assert_eq!(uncompressed, TEST_STRING.as_bytes()); - assert!(uncompressed.len() == TEST_STRING.len(), "uncompressed.len = {}, TEST_STRING.len = {}", uncompressed.len(), TEST_STRING.len()); - + assert!( + uncompressed.len() == TEST_STRING.len(), + "uncompressed.len = {}, TEST_STRING.len = {}", + uncompressed.len(), + TEST_STRING.len() + ); } #[test] fn test_compress2() { let compressed = lzxpress::data::compress(TEST_STRING2.as_bytes()).unwrap(); - assert!(compressed.len() == TEST_DATA2.len(), "compressed.len = {}, TEST_DATA2.len = {}", compressed.len(), TEST_DATA2.len()); + assert!( + compressed.len() == TEST_DATA2.len(), + "compressed.len = {}, TEST_DATA2.len = {}", + compressed.len(), + TEST_DATA2.len() + ); assert_eq!(compressed, TEST_DATA2); let uncompressed = lzxpress::data::decompress(compressed.as_slice()).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } assert_eq!(uncompressed, TEST_STRING2.as_bytes()); } @@ -149,18 +167,23 @@ mod tests { fn test_compress3() { let compressed = lzxpress::data::compress(TEST_STRING3.as_bytes()).unwrap(); - println!("{}", TEST_STRING3); + println!("{TEST_STRING3}"); if let Ok(s) = str::from_utf8(&compressed) { - println!("{}", s); + println!("{s}"); } - assert!(compressed.len() == TEST_DATA3.len(), "compressed.len = {}, TEST_DATA2.len = {}", compressed.len(), TEST_DATA3.len()); + assert!( + compressed.len() == TEST_DATA3.len(), + "compressed.len = {}, TEST_DATA2.len = {}", + compressed.len(), + TEST_DATA3.len() + ); assert_eq!(compressed, TEST_DATA3); let uncompressed = lzxpress::data::decompress(compressed.as_slice()).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } assert_eq!(uncompressed, TEST_STRING3.as_bytes()); } @@ -170,10 +193,15 @@ mod tests { let uncompressed = lzxpress::lznt1::decompress(TEST_LZNT1_DATA1).unwrap(); if let Ok(s) = str::from_utf8(&uncompressed) { - println!("{}", s); + println!("{s}"); } - assert!(uncompressed.len() == TEST_LZNT1_STRING1.len(), "uncompressed.len = {}, TEST_LZNT1_STRING1.len = {}", uncompressed.len(), TEST_LZNT1_STRING1.len()); + assert!( + uncompressed.len() == TEST_LZNT1_STRING1.len(), + "uncompressed.len = {}, TEST_LZNT1_STRING1.len = {}", + uncompressed.len(), + TEST_LZNT1_STRING1.len() + ); assert_eq!(uncompressed, TEST_LZNT1_STRING1.as_bytes()); } @@ -184,19 +212,24 @@ mod tests { // let mut output = File::create("rust.uncompressed.bin").expect("Unable to open"); // output.write(c).expect("Unable to open"); - assert!(uncompressed.len() == 0x100000, "uncompressed.len = {} (expected len = 0x10000)", uncompressed.len()); + assert!( + uncompressed.len() == 0x0010_0000, + "uncompressed.len = {} (expected len = 0x10000)", + uncompressed.len() + ); assert_eq!(uncompressed, TEST_LZNT1_UNCOMPRESSED_DATA); } - + #[test] #[cfg(windows)] fn test_lznt1_decompress_vs_rtl() { unsafe { - let uncompressed_local = lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); + let uncompressed_local = + lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); let compression_format_lznt1 = 0x0002 as u16; let compression_engine_standard = 0x0000 as u16; - use ntapi::ntrtl::{RtlDecompressBuffer}; + use ntapi::ntrtl::RtlDecompressBuffer; let mut mutable_compressed_data = TEST_LZNT1_COMPRESSED_DATA.to_vec(); let psrc = mutable_compressed_data.as_mut_ptr(); @@ -208,46 +241,63 @@ mod tests { let mut uncompressed_rtl = Vec::with_capacity(dstlen as usize); let pdst = uncompressed_rtl.as_mut_ptr(); - let _ntstatus = RtlDecompressBuffer(compression_format_lznt1 | compression_engine_standard, pdst, dstlen, psrc, srclen, &mut dstlen2); + let _ntstatus = RtlDecompressBuffer( + compression_format_lznt1 | compression_engine_standard, + pdst, + dstlen, + psrc, + srclen, + &mut dstlen2, + ); uncompressed_rtl.set_len(dstlen2 as usize); - assert!(dstlen == dstlen2, "dstlen = {} and dstlen2 = {})", dstlen, dstlen2); - assert!(uncompressed_local.len() == uncompressed_rtl.len(), "uncompressed_local.len = {} and uncompressed_rtl = {})", uncompressed_local.len(), uncompressed_rtl.len()); + assert!( + dstlen == dstlen2, + "dstlen = {} and dstlen2 = {})", + dstlen, + dstlen2 + ); + assert!( + uncompressed_local.len() == uncompressed_rtl.len(), + "uncompressed_local.len = {} and uncompressed_rtl = {})", + uncompressed_local.len(), + uncompressed_rtl.len() + ); assert_eq!(uncompressed_local, uncompressed_rtl); } } - #[test] #[cfg(windows)] fn test_lznt1_decompress_vs_no_push_optz() { unsafe { - let uncompressed_local = lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); + let uncompressed_local = + lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); let dstlen = 0x100000; - let mut out_buf: Vec = Vec::with_capacity(dstlen); + let mut out_buf: Vec = Vec::with_capacity(dstlen); out_buf.set_len(dstlen); - let _res = lzxpress::lznt1::decompress2_no_push( - TEST_LZNT1_COMPRESSED_DATA, - &mut out_buf - ); + let _res = + lzxpress::lznt1::decompress2_no_push(TEST_LZNT1_COMPRESSED_DATA, &mut out_buf); - assert!(uncompressed_local.len() == out_buf.len(), + assert!( + uncompressed_local.len() == out_buf.len(), "uncompressed_local.len = {} and out_buf = {})", uncompressed_local.len(), - out_buf.len()); + out_buf.len() + ); assert_eq!(uncompressed_local, out_buf); } - } #[test] #[cfg(windows)] fn test_lznt1_decompress_vs_cpp() { unsafe { - let uncompressed_local = lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); - + let uncompressed_local = + lzxpress::lznt1::decompress(TEST_LZNT1_COMPRESSED_DATA).unwrap(); + let psrc = TEST_LZNT1_COMPRESSED_DATA.as_ptr(); let srclen = TEST_LZNT1_COMPRESSED_DATA.len() as i32; @@ -256,24 +306,23 @@ mod tests { let mut dst = Vec::with_capacity(dstlen as usize); let pdst = dst.as_mut_ptr(); - let _status = decompress_lznt1( - psrc, - srclen, - pdst, - dstlen, - &mut dstlen2); + let _status = decompress_lznt1(psrc, srclen, pdst, dstlen, &mut dstlen2); dst.set_len(dstlen2 as usize); - assert!(dstlen == dstlen2, "dstlen = {} and dstlen2 = {} and srclen = {}", + assert!( + dstlen == dstlen2, + "dstlen = {} and dstlen2 = {} and srclen = {}", dstlen, dstlen2, - srclen); - assert!(uncompressed_local.len() == dst.len(), + srclen + ); + assert!( + uncompressed_local.len() == dst.len(), "uncompressed_local.len = {} and uncompressed_rtl = {})", uncompressed_local.len(), - dst.len()); + dst.len() + ); assert_eq!(uncompressed_local, dst); } - } -} \ No newline at end of file +} From b05408631c1c31cc9a7333815373cfaf367577e8 Mon Sep 17 00:00:00 2001 From: kromych Date: Sat, 22 Oct 2022 23:34:28 -0700 Subject: [PATCH 2/2] Return success if position == length as in MS-XCA --- src/data.rs | 15 ++++++++++----- tests/fast.compressed.ffffffff.bin | Bin 0 -> 3435 bytes tests/fast.uncompressed.ffffffff.bin | Bin 0 -> 4096 bytes tests/test.rs | 12 ++++++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 tests/fast.compressed.ffffffff.bin create mode 100644 tests/fast.uncompressed.ffffffff.bin diff --git a/src/data.rs b/src/data.rs index adb2d93..1280972 100644 --- a/src/data.rs +++ b/src/data.rs @@ -65,7 +65,12 @@ pub fn decompress(in_buf: &[u8]) -> Result, Error> { in_idx += mem::size_of::(); out_idx += mem::size_of::(); } else { - if (in_idx + 1) >= in_buf.len() { + if in_idx == in_buf.len() { + // [MS-XCA] - v20210625, 2.4.4 + break; + } + + if (in_idx + 1) > in_buf.len() { return Err(Error::MemLimit); } @@ -77,7 +82,7 @@ pub fn decompress(in_buf: &[u8]) -> Result, Error> { if length == 7 { if nibble_idx == 0 { - if in_idx >= in_buf.len() { + if in_idx > in_buf.len() { return Err(Error::MemLimit); } @@ -85,7 +90,7 @@ pub fn decompress(in_buf: &[u8]) -> Result, Error> { nibble_idx = in_idx; in_idx += mem::size_of::(); } else { - if nibble_idx >= in_buf.len() { + if nibble_idx > in_buf.len() { return Err(Error::MemLimit); } @@ -94,7 +99,7 @@ pub fn decompress(in_buf: &[u8]) -> Result, Error> { } if length == 15 { - if in_idx >= in_buf.len() { + if in_idx > in_buf.len() { return Err(Error::MemLimit); } @@ -102,7 +107,7 @@ pub fn decompress(in_buf: &[u8]) -> Result, Error> { in_idx += mem::size_of::(); if length == 255 { - if (in_idx + 1) >= in_buf.len() { + if (in_idx + 1) > in_buf.len() { return Err(Error::MemLimit); } diff --git a/tests/fast.compressed.ffffffff.bin b/tests/fast.compressed.ffffffff.bin new file mode 100644 index 0000000000000000000000000000000000000000..987721b32fed566e5ba75ac54dc9aa6c3bf4fda6 GIT binary patch literal 3435 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 B1IYjY literal 0 HcmV?d00001 diff --git a/tests/fast.uncompressed.ffffffff.bin b/tests/fast.uncompressed.ffffffff.bin new file mode 100644 index 0000000000000000000000000000000000000000..1af518316fe3e1f9af5ef642c0f55c739b96cb8a GIT binary patch literal 4096 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 VDLxOncG2^4`WHbzl#2ti{|DPIHIo1U literal 0 HcmV?d00001 diff --git a/tests/test.rs b/tests/test.rs index bd7f811..06e1afe 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -15,6 +15,10 @@ const TEST_OSSFUZZ_20083_DATA: &[u8] = const TEST_OSSFUZZ_5698056963227648_DATA: &[u8] = include_bytes!("clusterfuzz-testcase-minimized-fuzz_ndr_drsuapi_TYPE_OUT-5698056963227648"); +const TEST_FAST_FFFFFFFF_COMPRESSED_DATA: &[u8] = include_bytes!("fast.compressed.ffffffff.bin"); +const TEST_FAST_FFFFFFFF_UNCOMPRESSED_DATA: &[u8] = + include_bytes!("fast.uncompressed.ffffffff.bin"); + // Examples: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/72da4f8d-2ba3-437d-b772-2e4173713a0b?redirectedfrom=MSDN const TEST_STRING2: &str = "abcdefghijklmnopqrstuvwxyz"; const TEST_DATA2: &[u8] = &[ @@ -103,6 +107,14 @@ mod tests { assert_eq!(uncompressed, TEST_STRING3.as_bytes()); } + #[test] + fn test_decompress4() { + assert_eq!( + &lzxpress::data::decompress(TEST_FAST_FFFFFFFF_COMPRESSED_DATA).unwrap(), + TEST_FAST_FFFFFFFF_UNCOMPRESSED_DATA + ); + } + #[test] fn test_decompress_err1() { let result = lzxpress::data::decompress(TEST_OSSFUZZ_20083_DATA);