Skip to content

Commit 286ea4c

Browse files
author
Pascal Seitz
committed
add fuzzer, fix memcopy overlap
1 parent 8daa6ec commit 286ea4c

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

fuzz/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

fuzz/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
[package]
3+
name = "lz4_flex-fuzz"
4+
version = "0.0.0"
5+
authors = ["Automatically generated"]
6+
publish = false
7+
edition = "2018"
8+
9+
[package.metadata]
10+
cargo-fuzz = true
11+
12+
[dependencies]
13+
libfuzzer-sys = "0.3"
14+
15+
[dependencies.lz4_flex]
16+
path = ".."
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "fuzz_target_1"
24+
path = "fuzz_targets/fuzz_target_1.rs"
25+
test = false
26+
doc = false

fuzz/fuzz_targets/fuzz_target_1.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
4+
use lz4_flex::block::decompress::decompress_size_prepended;
5+
use lz4_flex::block::compress::compress_prepend_size;
6+
fuzz_target!(|data: &[u8]| {
7+
// fuzzed code goes here
8+
let compressed = compress_prepend_size(data);
9+
let decompressed = decompress_size_prepended(&compressed).unwrap();
10+
assert_eq!(data, decompressed);
11+
});

src/block/decompress.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,16 @@ fn is_safe_distance(input_pos: usize, in_len: usize) -> bool {
136136
input_pos < in_len
137137
}
138138

139+
/// We copy 24 byte blocks, because aligned copies are faster
140+
const BLOCK_COPY_SIZE: usize = 24;
141+
139142
#[inline]
140143
fn block_copy_from_src(source: *const u8, dst_ptr: *mut u8, num_items: usize) {
141-
debug_assert!(num_items <= 24);
144+
debug_assert!(num_items <= BLOCK_COPY_SIZE);
142145
unsafe {
143146
let dst_ptr_end = dst_ptr.add(num_items);
144147
if (dst_ptr as usize) < dst_ptr_end as usize {
145-
std::ptr::copy_nonoverlapping(source, dst_ptr, 24);
148+
std::ptr::copy_nonoverlapping(source, dst_ptr, BLOCK_COPY_SIZE);
146149
}
147150
}
148151
}
@@ -209,8 +212,9 @@ pub fn decompress_into(input: &[u8], output: &mut Vec<u8>) -> Result<(), Error>
209212
let start_ptr = unsafe { output_ptr.sub(offset as usize) };
210213

211214
let match_length = (4 + (token & 0xF)) as usize;
212-
// Write the duplicate segment to the output buffer.
213-
if (output_ptr as usize) < unsafe { start_ptr.add(match_length) } as usize {
215+
// Write the duplicate segment to the output buffer from the output buffer
216+
// The blocks can overlap, make sure they are at least BLOCK_COPY_SIZE apart
217+
if (output_ptr as usize) < unsafe { start_ptr.add(match_length).add(BLOCK_COPY_SIZE) } as usize {
214218
duplicate_overlapping(&mut output_ptr, start_ptr, match_length);
215219
} else {
216220
unsafe {

0 commit comments

Comments
 (0)