@@ -321,7 +321,7 @@ ErrorOr<void> LzmaDecompressor::decode_literal_to_output_buffer()
321
321
// Testing `(State > 7)` with actual test files yields errors, so the reference implementation appears to be the correct one.
322
322
if (m_state >= 7 ) {
323
323
u8 matched_byte = 0 ;
324
- auto read_bytes = TRY (m_dictionary->read_with_seekback ({ &matched_byte, sizeof (matched_byte) }, m_rep0 + 1 ));
324
+ auto read_bytes = TRY (m_dictionary->read_with_seekback ({ &matched_byte, sizeof (matched_byte) }, current_repetition_offset () ));
325
325
VERIFY (read_bytes.size () == sizeof (matched_byte));
326
326
327
327
do {
@@ -455,6 +455,16 @@ ErrorOr<u32> LzmaDecompressor::decode_normalized_match_distance(u16 normalized_m
455
455
return (distance_prefix << number_of_alignment_bits) | TRY (decode_symbol_using_reverse_bit_tree (number_of_alignment_bits, m_alignment_bit_probabilities));
456
456
}
457
457
458
+ u32 LzmaDecompressor::current_repetition_offset () const
459
+ {
460
+ // LZMA never needs to read at offset 0 (i.e. the actual read head of the buffer).
461
+ // Instead, the values are remapped so that the rep-value n starts reading n + 1 bytes back.
462
+ // The special rep-value 0xFFFFFFFF is reserved for marking the end of the stream,
463
+ // so this should never overflow.
464
+ VERIFY (m_rep0 < NumericLimits<u32 >::max ());
465
+ return m_rep0 + 1 ;
466
+ }
467
+
458
468
ErrorOr<Bytes> LzmaDecompressor::read_some (Bytes bytes)
459
469
{
460
470
while (m_dictionary->used_space () < bytes.size () && m_dictionary->empty_space () != 0 ) {
@@ -517,7 +527,7 @@ ErrorOr<Bytes> LzmaDecompressor::read_some(Bytes bytes)
517
527
}
518
528
519
529
u8 byte;
520
- auto read_bytes = TRY (m_dictionary->read_with_seekback ({ &byte, sizeof (byte) }, m_rep0 + 1 ));
530
+ auto read_bytes = TRY (m_dictionary->read_with_seekback ({ &byte, sizeof (byte) }, current_repetition_offset () ));
521
531
VERIFY (read_bytes.size () == sizeof (byte));
522
532
523
533
auto written_bytes = m_dictionary->write ({ &byte, sizeof (byte) });
@@ -600,7 +610,7 @@ ErrorOr<Bytes> LzmaDecompressor::read_some(Bytes bytes)
600
610
601
611
// "Also the decoder must check that "rep0" value is not larger than dictionary size
602
612
// and is not larger than the number of already decoded bytes."
603
- if (m_rep0 > m_dictionary->seekback_limit ())
613
+ if (current_repetition_offset () > m_dictionary->seekback_limit ())
604
614
return Error::from_string_literal (" rep0 value is larger than the possible lookback size" );
605
615
606
616
// "Then the decoder must copy match bytes as described in
0 commit comments