@@ -66,6 +66,7 @@ fn longest_match_help<const SLOW: bool>(
66
66
// The code is optimized for STD_MAX_MATCH-2 multiple of 16.
67
67
assert_eq ! ( STD_MAX_MATCH , 258 , "Code too clever" ) ;
68
68
69
+ // length of the previous match (if any), hence <= STD_MAX_MATCH
69
70
best_len = if state. prev_length > 0 {
70
71
state. prev_length
71
72
} else {
@@ -81,9 +82,6 @@ fn longest_match_help<const SLOW: bool>(
81
82
}
82
83
}
83
84
84
- let scan_start = window[ strstart..] . as_ptr ( ) ;
85
- let mut scan_end = window[ strstart + offset..] . as_ptr ( ) ;
86
-
87
85
let mut mbase_start = window. as_ptr ( ) ;
88
86
let mut mbase_end = window[ offset..] . as_ptr ( ) ;
89
87
@@ -145,6 +143,9 @@ fn longest_match_help<const SLOW: bool>(
145
143
early_exit = state. level < EARLY_EXIT_TRIGGER_LEVEL ;
146
144
}
147
145
146
+ let scan_start = window[ strstart..] . as_ptr ( ) ;
147
+ let mut scan_end = window[ strstart + offset..] . as_ptr ( ) ;
148
+
148
149
assert ! (
149
150
strstart <= state. window_size. saturating_sub( MIN_LOOKAHEAD ) ,
150
151
"need lookahead"
@@ -193,9 +194,18 @@ fn longest_match_help<const SLOW: bool>(
193
194
194
195
// first, do a quick check on the start and end bytes. Go to the next item in the chain if
195
196
// these bytes don't match.
196
- // SAFETY: we read up to 8 bytes in this block. scan_start and start_end are 8 byte arrays.
197
- // this loop also breaks before cur_match gets past strstart, which is bounded by
198
- // window_size - MIN_LOOKAHEAD, so 8 byte reads of mbase_end/start are in-bounds.
197
+ // SAFETY: we read up to 8 bytes in this block.
198
+ // Note that scan_start >= mbase_start and scan_end >= mbase_end.
199
+ // the surrounding loop breaks before cur_match gets past strstart, which is bounded by
200
+ // `window_size - 258 + 3 + 1` (`window_size - MIN_LOOKAHEAD`).
201
+ //
202
+ // With 262 bytes of space at the end, and 8 byte reads of scan_start is always in-bounds.
203
+ //
204
+ // scan_end is a bit trickier: it reads at a bounded offset from scan_start:
205
+ //
206
+ // - UNALIGNED64_OK: scan_end is bounded by `258 - (4 + 2 + 1)`, so an 8-byte read is in-bounds
207
+ // - UNALIGNED_OK: scan_end is bounded by `258 - (2 + 1)`, so a 4-byte read is in-bounds
208
+ // - otherwise: scan_end is bounded by `258 - 1`, so a 2-byte read is in-bounds
199
209
unsafe {
200
210
if UNALIGNED_OK {
201
211
if best_len < core:: mem:: size_of :: < u32 > ( ) {
@@ -242,7 +252,7 @@ fn longest_match_help<const SLOW: bool>(
242
252
// we know that there is at least some match. Now count how many bytes really match
243
253
let len = {
244
254
// SAFETY: cur_match is bounded by window_size - MIN_LOOKAHEAD, where MIN_LOOKAHEAD
245
- // is 256 + 2 , so 258-byte reads of mbase_start are in-bounds.
255
+ // is 258 + 3 + 1 , so 258-byte reads of mbase_start are in-bounds.
246
256
let src1 = unsafe {
247
257
core:: slice:: from_raw_parts ( mbase_start. wrapping_add ( cur_match as usize + 2 ) , 256 )
248
258
} ;
0 commit comments