mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-22 06:54:40 +00:00
Fix RAR5 async decompression corruption in UnpWriteBufAsync
Three bugs in the async version of UnpWriteBuf (used only in the async
decompression path) were causing data corruption when decompressing RAR5
archives containing executable filters (E8/E8E9/ARM) whose blocks spanned
the 4MB write boundary (UNPACK_MAX_WRITE):
1. WrittenFileSize was only incremented inside `if (OutMem != null)`, but
should always be incremented after ApplyFilter (matching sync behavior).
2. UnpSomeRead = true was missing from the filter processing path.
3. In the NotAllFiltersProcessed else branch (filter intersects write border):
- WrPtr was not updated to WrittenBorder, corrupting the window pointer
used to compute WriteBorder on the next flush cycle
- Remaining filters had NextWindow set to true (inverted logic), when
sync correctly sets them to false so they are processed next time
All three changes align the async path with the sync UnpWriteBuf logic.
This commit is contained in:
committed by
GitHub
parent
5445d2b77e
commit
9eb4abe49e
@@ -3,4 +3,4 @@
|
||||
"version": "10.0.301",
|
||||
"rollForward": "disable"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,28 +394,34 @@ internal partial class Unpack
|
||||
{
|
||||
await UnpIO_UnpWriteAsync(OutMem, 0, BlockLength, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
WrittenFileSize += BlockLength;
|
||||
}
|
||||
|
||||
UnpSomeRead = true;
|
||||
WrittenFileSize += BlockLength;
|
||||
WrittenBorder = BlockEnd;
|
||||
WriteSizeLeft = (UnpPtr - WrittenBorder) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NotAllFiltersProcessed = true;
|
||||
// Current filter intersects the window write border, so we adjust
|
||||
// the window border to process this filter next time, not now.
|
||||
WrPtr = WrittenBorder;
|
||||
|
||||
// Since Filter start position can only increase, we quit processing
|
||||
// all following filters for this data block and reset 'NextWindow'
|
||||
// flag for them.
|
||||
for (var J = I; J < Filters.Count; J++)
|
||||
{
|
||||
var fltj = Filters[J];
|
||||
if (
|
||||
fltj.Type != FILTER_NONE
|
||||
&& fltj.NextWindow == false
|
||||
&& ((fltj.BlockStart - WrPtr) & MaxWinMask) < FullWriteSize
|
||||
)
|
||||
if (fltj.Type != FILTER_NONE)
|
||||
{
|
||||
fltj.NextWindow = true;
|
||||
fltj.NextWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not write data left after current filter now.
|
||||
NotAllFiltersProcessed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user