@@ -229,6 +229,22 @@ fn scan_for_next_magic<R: Read>(reader: &mut R) -> std::io::Result<Option<[u8; 8
229229 }
230230}
231231
232+ fn resync_to_next_magic < R : Read + Seek > ( reader : & mut R , rewind_bytes : i64 ) -> bool {
233+ if rewind_bytes != 0
234+ && reader
235+ . seek ( std:: io:: SeekFrom :: Current ( -rewind_bytes) )
236+ . is_err ( )
237+ {
238+ return false ;
239+ }
240+
241+ if scan_for_next_magic ( reader) . ok ( ) . flatten ( ) . is_none ( ) {
242+ return false ;
243+ }
244+
245+ reader. seek ( std:: io:: SeekFrom :: Current ( -8 ) ) . is_ok ( )
246+ }
247+
232248/// Parse packets with optional recovery slice inclusion
233249///
234250/// When `include_recovery_slices` is false, recovery slice packet headers are still
@@ -261,12 +277,9 @@ pub fn parse_packets_with_options<R: Read + Seek>(
261277 break ;
262278 }
263279 Err ( PacketParseError :: InvalidMagic ( _) ) => {
264- // Bad magic - try to find next valid packet by scanning forward
265- if scan_for_next_magic ( reader) . ok ( ) . flatten ( ) . is_some ( ) {
266- // Found magic, but we need to rewind 8 bytes so the next parse reads the header
267- if reader. seek ( std:: io:: SeekFrom :: Current ( -8 ) ) . is_err ( ) {
268- break ;
269- }
280+ // PacketHeader::parse consumed 64 bytes. Rewind 63 bytes so
281+ // resync still checks the byte immediately after the bad start.
282+ if resync_to_next_magic ( reader, 63 ) {
270283 continue ;
271284 } else {
272285 break ;
@@ -285,12 +298,7 @@ pub fn parse_packets_with_options<R: Read + Seek>(
285298 }
286299 Err ( _) => {
287300 // Validation failed - try to find next valid packet
288- if scan_for_next_magic ( reader) . ok ( ) . flatten ( ) . is_some ( ) {
289- // Found magic, rewind 8 bytes
290- if reader. seek ( std:: io:: SeekFrom :: Current ( -8 ) ) . is_err ( ) {
291- break ;
292- }
293- } else {
301+ if !resync_to_next_magic ( reader, 0 ) {
294302 break ;
295303 }
296304 }
@@ -303,10 +311,7 @@ pub fn parse_packets_with_options<R: Read + Seek>(
303311 Ok ( data) => data,
304312 Err ( _) => {
305313 // Failed to read packet body - try to find next valid packet
306- if scan_for_next_magic ( reader) . ok ( ) . flatten ( ) . is_some ( ) {
307- if reader. seek ( std:: io:: SeekFrom :: Current ( -8 ) ) . is_err ( ) {
308- break ;
309- }
314+ if resync_to_next_magic ( reader, 0 ) {
310315 continue ;
311316 } else {
312317 break ;
@@ -724,6 +729,20 @@ mod tests {
724729 assert_eq ! ( pos, 20 ) ; // 12 bytes before magic + 8 magic bytes
725730 }
726731
732+ #[ test]
733+ fn invalid_magic_resync_checks_next_byte ( ) {
734+ let mut data = vec ! [ 0xFF ; 64 ] ;
735+ data[ 1 ..9 ] . copy_from_slice ( MAGIC_BYTES ) ;
736+ let mut cursor = Cursor :: new ( & data) ;
737+
738+ let result = PacketHeader :: parse ( & mut cursor) ;
739+ assert ! ( matches!( result, Err ( PacketParseError :: InvalidMagic ( _) ) ) ) ;
740+ assert_eq ! ( cursor. position( ) , 64 ) ;
741+
742+ assert ! ( resync_to_next_magic( & mut cursor, 63 ) ) ;
743+ assert_eq ! ( cursor. position( ) , 1 ) ;
744+ }
745+
727746 #[ test]
728747 fn corrupt_packet_recovery ( ) {
729748 // Test that we can recover from a corrupt packet by finding the next valid magic
0 commit comments