diff --git a/src/block/compress.rs b/src/block/compress.rs index c60fe017..04c85e43 100644 --- a/src/block/compress.rs +++ b/src/block/compress.rs @@ -521,7 +521,14 @@ fn push_u16(output: &mut impl Sink, el: u16) { #[inline(always)] // (always) necessary otherwise compiler fails to inline it #[cfg(feature = "safe-encode")] fn copy_literals_wild(output: &mut impl Sink, input: &[u8], input_start: usize, len: usize) { - output.extend_from_slice_wild(&input[input_start..input_start + len], len) + // Pass a wider slice (+8 bytes) so that slice_copy can use efficient fixed-size copy + // paths for small literals, matching the unsafe version's behavior of unconditionally + // copying 8/16/24 bytes. This is safe because: + // - MFLIMIT guarantees at least 12 bytes of input after `input_start + len` + // - get_maximum_output_size provides sufficient output capacity margin + debug_assert!(input_start + len + 8 <= input.len()); + debug_assert!(output.pos() + len + 8 <= output.capacity()); + output.extend_from_slice_wild(&input[input_start..input_start + len + 8], len) } #[inline] diff --git a/src/block/decompress_safe.rs b/src/block/decompress_safe.rs index df298f7f..fc8c4398 100644 --- a/src/block/decompress_safe.rs +++ b/src/block/decompress_safe.rs @@ -138,8 +138,11 @@ pub(crate) fn decompress_internal( output.extend_from_slice_wild(input, literal_length); input_pos += literal_length; - // clone as we don't want to mutate - let offset = read_u16(input, &mut literal_length.clone())? as usize; + // Read the offset directly from the input array. + // `input` is &[u8; 16] and `literal_length` is at most 14 (guaranteed by + // does_token_fit), so literal_length + 1 <= 15 is always in bounds. + let offset = + u16::from_le_bytes([input[literal_length], input[literal_length + 1]]) as usize; input_pos += 2; let mut match_length = MINMATCH + (token & 0xF) as usize;