From cd5da3da5dde514a8bf2483343476f028eddd511 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 11 Feb 2026 16:35:41 +0000 Subject: [PATCH] moved and validated more async code --- .../Rar/UnpackV2017/Unpack.unpack15_async.cs | 100 ++++++ .../Rar/UnpackV2017/Unpack.unpack15_cpp.cs | 96 ------ .../Rar/UnpackV2017/Unpack.unpack20_async.cs | 319 ++++++++++++++++++ .../Rar/UnpackV2017/Unpack.unpack20_cpp.cs | 318 ----------------- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 11 +- 5 files changed, 421 insertions(+), 423 deletions(-) create mode 100644 src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_async.cs create mode 100644 src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_async.cs diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_async.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_async.cs new file mode 100644 index 00000000..e615527e --- /dev/null +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_async.cs @@ -0,0 +1,100 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace SharpCompress.Compressors.Rar.UnpackV2017; + +internal partial class Unpack +{ + private async Task Unpack15Async(bool Solid, CancellationToken cancellationToken = default) + { + UnpInitData(Solid); + UnpInitData15(Solid); + await UnpReadBufAsync(cancellationToken).ConfigureAwait(false); + if (!Solid) + { + InitHuff(); + UnpPtr = 0; + } + else + { + UnpPtr = WrPtr; + } + + --DestUnpSize; + if (DestUnpSize >= 0) + { + GetFlagsBuf(); + FlagsCnt = 8; + } + + while (DestUnpSize >= 0) + { + UnpPtr &= MaxWinMask; + + if ( + Inp.InAddr > ReadTop - 30 + && !await UnpReadBufAsync(cancellationToken).ConfigureAwait(false) + ) + { + break; + } + + if (((WrPtr - UnpPtr) & MaxWinMask) < 270 && WrPtr != UnpPtr) + { + UnpWriteBuf20(); + } + + if (StMode != 0) + { + HuffDecode(); + continue; + } + + if (--FlagsCnt < 0) + { + GetFlagsBuf(); + FlagsCnt = 7; + } + + if ((FlagBuf & 0x80) != 0) + { + FlagBuf <<= 1; + if (Nlzb > Nhfb) + { + LongLZ(); + } + else + { + HuffDecode(); + } + } + else + { + FlagBuf <<= 1; + if (--FlagsCnt < 0) + { + GetFlagsBuf(); + FlagsCnt = 7; + } + if ((FlagBuf & 0x80) != 0) + { + FlagBuf <<= 1; + if (Nlzb > Nhfb) + { + HuffDecode(); + } + else + { + LongLZ(); + } + } + else + { + FlagBuf <<= 1; + ShortLZ(); + } + } + } + UnpWriteBuf20(); + } +} diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_cpp.cs index 9a2882b7..c1886df8 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_cpp.cs @@ -200,102 +200,6 @@ internal partial class Unpack UnpWriteBuf20(); } - private async System.Threading.Tasks.Task Unpack15Async( - bool Solid, - System.Threading.CancellationToken cancellationToken = default - ) - { - UnpInitData(Solid); - UnpInitData15(Solid); - await UnpReadBufAsync(cancellationToken).ConfigureAwait(false); - if (!Solid) - { - InitHuff(); - UnpPtr = 0; - } - else - { - UnpPtr = WrPtr; - } - - --DestUnpSize; - if (DestUnpSize >= 0) - { - GetFlagsBuf(); - FlagsCnt = 8; - } - - while (DestUnpSize >= 0) - { - UnpPtr &= MaxWinMask; - - if ( - Inp.InAddr > ReadTop - 30 - && !await UnpReadBufAsync(cancellationToken).ConfigureAwait(false) - ) - { - break; - } - - if (((WrPtr - UnpPtr) & MaxWinMask) < 270 && WrPtr != UnpPtr) - { - await UnpWriteBuf20Async(cancellationToken).ConfigureAwait(false); - } - - if (StMode != 0) - { - HuffDecode(); - continue; - } - - if (--FlagsCnt < 0) - { - GetFlagsBuf(); - FlagsCnt = 7; - } - - if ((FlagBuf & 0x80) != 0) - { - FlagBuf <<= 1; - if (Nlzb > Nhfb) - { - LongLZ(); - } - else - { - HuffDecode(); - } - } - else - { - FlagBuf <<= 1; - if (--FlagsCnt < 0) - { - GetFlagsBuf(); - FlagsCnt = 7; - } - if ((FlagBuf & 0x80) != 0) - { - FlagBuf <<= 1; - if (Nlzb > Nhfb) - { - HuffDecode(); - } - else - { - LongLZ(); - } - } - else - { - FlagBuf <<= 1; - ShortLZ(); - } - } - } - await UnpWriteBuf20Async(cancellationToken).ConfigureAwait(false); - } - //#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos]) private uint GetShortLen1(uint pos) => ((pos) == 1 ? (uint)(Buf60 + 3) : ShortLen1[pos]); diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_async.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_async.cs new file mode 100644 index 00000000..0619189a --- /dev/null +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_async.cs @@ -0,0 +1,319 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; + +namespace SharpCompress.Compressors.Rar.UnpackV2017; + +internal partial class Unpack +{ + private async Task Unpack20Async(bool Solid, CancellationToken cancellationToken = default) + { + uint Bits; + + if (Suspended) + { + UnpPtr = WrPtr; + } + else + { + UnpInitData(Solid); + if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) + { + return; + } + + if ( + (!Solid || !TablesRead2) + && !await ReadTables20Async(cancellationToken).ConfigureAwait(false) + ) + { + return; + } + + --DestUnpSize; + } + + while (DestUnpSize >= 0) + { + UnpPtr &= MaxWinMask; + + if (Inp.InAddr > ReadTop - 30) + { + if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) + { + break; + } + } + + if (((WrPtr - UnpPtr) & MaxWinMask) < 270 && WrPtr != UnpPtr) + { + UnpWriteBuf20(); + if (Suspended) + { + return; + } + } + if (UnpAudioBlock) + { + var AudioNumber = DecodeNumber(Inp, MD[UnpCurChannel]); + + if (AudioNumber == 256) + { + if (!await ReadTables20Async(cancellationToken).ConfigureAwait(false)) + { + break; + } + + continue; + } + Window[UnpPtr++] = DecodeAudio((int)AudioNumber); + if (++UnpCurChannel == UnpChannels) + { + UnpCurChannel = 0; + } + + --DestUnpSize; + continue; + } + + var Number = DecodeNumber(Inp, BlockTables.LD); + if (Number < 256) + { + Window[UnpPtr++] = (byte)Number; + --DestUnpSize; + continue; + } + if (Number > 269) + { + var Length = (uint)(LDecode[Number -= 270] + 3); + if ((Bits = LBits[Number]) > 0) + { + Length += Inp.getbits() >> (int)(16 - Bits); + Inp.addbits(Bits); + } + + var DistNumber = DecodeNumber(Inp, BlockTables.DD); + var Distance = DDecode[DistNumber] + 1; + if ((Bits = DBits[DistNumber]) > 0) + { + Distance += Inp.getbits() >> (int)(16 - Bits); + Inp.addbits(Bits); + } + + if (Distance >= 0x2000) + { + Length++; + if (Distance >= 0x40000L) + { + Length++; + } + } + + CopyString20(Length, Distance); + continue; + } + if (Number == 269) + { + if (!await ReadTables20Async(cancellationToken).ConfigureAwait(false)) + { + break; + } + + continue; + } + if (Number == 256) + { + CopyString20(LastLength, LastDist); + continue; + } + if (Number < 261) + { + var Distance = OldDist[(OldDistPtr - (Number - 256)) & 3]; + var LengthNumber = DecodeNumber(Inp, BlockTables.RD); + var Length = (uint)(LDecode[LengthNumber] + 2); + if ((Bits = LBits[LengthNumber]) > 0) + { + Length += Inp.getbits() >> (int)(16 - Bits); + Inp.addbits(Bits); + } + if (Distance >= 0x101) + { + Length++; + if (Distance >= 0x2000) + { + Length++; + if (Distance >= 0x40000) + { + Length++; + } + } + } + CopyString20(Length, Distance); + continue; + } + if (Number < 270) + { + var Distance = (uint)(SDDecode[Number -= 261] + 1); + if ((Bits = SDBits[Number]) > 0) + { + Distance += Inp.getbits() >> (int)(16 - Bits); + Inp.addbits(Bits); + } + CopyString20(2, Distance); + continue; + } + } + ReadLastTables(); + UnpWriteBuf20(); + } + + private async Task UnpWriteBuf20Async(CancellationToken cancellationToken = default) + { + if (UnpPtr != WrPtr) + { + UnpSomeRead = true; + } + + if (UnpPtr < WrPtr) + { + await UnpIO_UnpWriteAsync( + Window, + WrPtr, + (uint)(-(int)WrPtr & MaxWinMask), + cancellationToken + ) + .ConfigureAwait(false); + await UnpIO_UnpWriteAsync(Window, 0, UnpPtr, cancellationToken).ConfigureAwait(false); + UnpAllBuf = true; + } + else + { + await UnpIO_UnpWriteAsync(Window, WrPtr, UnpPtr - WrPtr, cancellationToken) + .ConfigureAwait(false); + } + + WrPtr = UnpPtr; + } + + private async Task ReadTables20Async(CancellationToken cancellationToken = default) + { + byte[] BitLength = new byte[checked((int)BC20)]; + byte[] Table = new byte[checked((int)MC20 * 4)]; + if (Inp.InAddr > ReadTop - 25) + { + if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) + { + return false; + } + } + + var BitField = Inp.getbits(); + UnpAudioBlock = (BitField & 0x8000) != 0; + + if ((BitField & 0x4000) != 0) + { + Array.Clear(UnpOldTable20, 0, UnpOldTable20.Length); + } + + Inp.addbits(2); + + uint TableSize; + if (UnpAudioBlock) + { + UnpChannels = ((BitField >> 12) & 3) + 1; + if (UnpCurChannel >= UnpChannels) + { + UnpCurChannel = 0; + } + + Inp.addbits(2); + TableSize = MC20 * UnpChannels; + } + else + { + TableSize = NC20 + DC20 + RC20; + } + + for (int I = 0; I < checked((int)BC20); I++) + { + BitLength[I] = (byte)(Inp.getbits() >> 12); + Inp.addbits(4); + } + MakeDecodeTables(BitLength, 0, BlockTables.BD, BC20); + for (int I = 0; I < checked((int)TableSize); ) + { + if (Inp.InAddr > ReadTop - 5) + { + if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) + { + return false; + } + } + + var Number = DecodeNumber(Inp, BlockTables.BD); + if (Number < 16) + { + Table[I] = (byte)((Number + UnpOldTable20[I]) & 0xf); + I++; + } + else if (Number == 16) + { + var N = (Inp.getbits() >> 14) + 3; + Inp.addbits(2); + if (I == 0) + { + return false; // We cannot have "repeat previous" code at the first position. + } + else + { + while (N-- > 0 && I < TableSize) + { + Table[I] = Table[I - 1]; + I++; + } + } + } + else + { + uint N; + if (Number == 17) + { + N = (Inp.getbits() >> 13) + 3; + Inp.addbits(3); + } + else + { + N = (Inp.getbits() >> 9) + 11; + Inp.addbits(7); + } + while (N-- > 0 && I < TableSize) + { + Table[I++] = 0; + } + } + } + TablesRead2 = true; + if (Inp.InAddr > ReadTop) + { + return true; + } + + if (UnpAudioBlock) + { + for (int I = 0; I < UnpChannels; I++) + { + MakeDecodeTables(Table, (int)(I * MC20), MD[I], MC20); + } + } + else + { + MakeDecodeTables(Table, 0, BlockTables.LD, NC20); + MakeDecodeTables(Table, (int)NC20, BlockTables.DD, DC20); + MakeDecodeTables(Table, (int)(NC20 + DC20), BlockTables.RD, RC20); + } + Array.Copy(Table, 0, this.UnpOldTable20, 0, UnpOldTable20.Length); + return true; + } +} diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs index 725d70ce..55b4174c 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs @@ -342,170 +342,6 @@ internal partial class Unpack UnpWriteBuf20(); } - private async System.Threading.Tasks.Task Unpack20Async( - bool Solid, - System.Threading.CancellationToken cancellationToken = default - ) - { - uint Bits; - - if (Suspended) - { - UnpPtr = WrPtr; - } - else - { - UnpInitData(Solid); - if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) - { - return; - } - - if ( - (!Solid || !TablesRead2) - && !await ReadTables20Async(cancellationToken).ConfigureAwait(false) - ) - { - return; - } - - --DestUnpSize; - } - - while (DestUnpSize >= 0) - { - UnpPtr &= MaxWinMask; - - if (Inp.InAddr > ReadTop - 30) - { - if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) - { - break; - } - } - - if (((WrPtr - UnpPtr) & MaxWinMask) < 270 && WrPtr != UnpPtr) - { - await UnpWriteBuf20Async(cancellationToken).ConfigureAwait(false); - if (Suspended) - { - return; - } - } - if (UnpAudioBlock) - { - var AudioNumber = DecodeNumber(Inp, MD[UnpCurChannel]); - - if (AudioNumber == 256) - { - if (!await ReadTables20Async(cancellationToken).ConfigureAwait(false)) - { - break; - } - - continue; - } - Window[UnpPtr++] = DecodeAudio((int)AudioNumber); - if (++UnpCurChannel == UnpChannels) - { - UnpCurChannel = 0; - } - - --DestUnpSize; - continue; - } - - var Number = DecodeNumber(Inp, BlockTables.LD); - if (Number < 256) - { - Window[UnpPtr++] = (byte)Number; - --DestUnpSize; - continue; - } - if (Number > 269) - { - var Length = (uint)(LDecode[Number -= 270] + 3); - if ((Bits = LBits[Number]) > 0) - { - Length += Inp.getbits() >> (int)(16 - Bits); - Inp.addbits(Bits); - } - - var DistNumber = DecodeNumber(Inp, BlockTables.DD); - var Distance = DDecode[DistNumber] + 1; - if ((Bits = DBits[DistNumber]) > 0) - { - Distance += Inp.getbits() >> (int)(16 - Bits); - Inp.addbits(Bits); - } - - if (Distance >= 0x2000) - { - Length++; - if (Distance >= 0x40000L) - { - Length++; - } - } - - CopyString20(Length, Distance); - continue; - } - if (Number == 269) - { - if (!await ReadTables20Async(cancellationToken).ConfigureAwait(false)) - { - break; - } - - continue; - } - if (Number == 256) - { - CopyString20(LastLength, LastDist); - continue; - } - if (Number < 261) - { - var Distance = OldDist[(OldDistPtr - (Number - 256)) & 3]; - var LengthNumber = DecodeNumber(Inp, BlockTables.RD); - var Length = (uint)(LDecode[LengthNumber] + 2); - if ((Bits = LBits[LengthNumber]) > 0) - { - Length += Inp.getbits() >> (int)(16 - Bits); - Inp.addbits(Bits); - } - if (Distance >= 0x101) - { - Length++; - if (Distance >= 0x2000) - { - Length++; - if (Distance >= 0x40000) - { - Length++; - } - } - } - CopyString20(Length, Distance); - continue; - } - if (Number < 270) - { - var Distance = (uint)(SDDecode[Number -= 261] + 1); - if ((Bits = SDBits[Number]) > 0) - { - Distance += Inp.getbits() >> (int)(16 - Bits); - Inp.addbits(Bits); - } - CopyString20(2, Distance); - continue; - } - } - ReadLastTables(); - await UnpWriteBuf20Async(cancellationToken).ConfigureAwait(false); - } - private void UnpWriteBuf20() { if (UnpPtr != WrPtr) @@ -527,36 +363,6 @@ internal partial class Unpack WrPtr = UnpPtr; } - private async System.Threading.Tasks.Task UnpWriteBuf20Async( - System.Threading.CancellationToken cancellationToken = default - ) - { - if (UnpPtr != WrPtr) - { - UnpSomeRead = true; - } - - if (UnpPtr < WrPtr) - { - await UnpIO_UnpWriteAsync( - Window, - WrPtr, - (uint)(-(int)WrPtr & MaxWinMask), - cancellationToken - ) - .ConfigureAwait(false); - await UnpIO_UnpWriteAsync(Window, 0, UnpPtr, cancellationToken).ConfigureAwait(false); - UnpAllBuf = true; - } - else - { - await UnpIO_UnpWriteAsync(Window, WrPtr, UnpPtr - WrPtr, cancellationToken) - .ConfigureAwait(false); - } - - WrPtr = UnpPtr; - } - private bool ReadTables20() { Span BitLength = stackalloc byte[checked((int)BC20)]; @@ -677,130 +483,6 @@ internal partial class Unpack return true; } - private async System.Threading.Tasks.Task ReadTables20Async( - System.Threading.CancellationToken cancellationToken = default - ) - { - byte[] BitLength = new byte[checked((int)BC20)]; - byte[] Table = new byte[checked((int)MC20 * 4)]; - if (Inp.InAddr > ReadTop - 25) - { - if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) - { - return false; - } - } - - var BitField = Inp.getbits(); - UnpAudioBlock = (BitField & 0x8000) != 0; - - if ((BitField & 0x4000) != 0) - { - Array.Clear(UnpOldTable20, 0, UnpOldTable20.Length); - } - - Inp.addbits(2); - - uint TableSize; - if (UnpAudioBlock) - { - UnpChannels = ((BitField >> 12) & 3) + 1; - if (UnpCurChannel >= UnpChannels) - { - UnpCurChannel = 0; - } - - Inp.addbits(2); - TableSize = MC20 * UnpChannels; - } - else - { - TableSize = NC20 + DC20 + RC20; - } - - for (int I = 0; I < checked((int)BC20); I++) - { - BitLength[I] = (byte)(Inp.getbits() >> 12); - Inp.addbits(4); - } - MakeDecodeTables(BitLength, 0, BlockTables.BD, BC20); - for (int I = 0; I < checked((int)TableSize); ) - { - if (Inp.InAddr > ReadTop - 5) - { - if (!await UnpReadBufAsync(cancellationToken).ConfigureAwait(false)) - { - return false; - } - } - - var Number = DecodeNumber(Inp, BlockTables.BD); - if (Number < 16) - { - Table[I] = (byte)((Number + UnpOldTable20[I]) & 0xF); - I++; - } - else if (Number < 18) - { - uint N; - if (Number == 16) - { - N = (Inp.getbits() >> 14) + 3; - Inp.addbits(2); - } - else - { - N = (Inp.getbits() >> 13) + 11; - Inp.addbits(3); - } - if (I == 0) - { - return false; - } - - while (N-- > 0 && I < checked((int)TableSize)) - { - Table[I] = Table[I - 1]; - I++; - } - } - else - { - uint N; - if (Number == 18) - { - N = (Inp.getbits() >> 13) + 3; - Inp.addbits(3); - } - else - { - N = (Inp.getbits() >> 9) + 11; - Inp.addbits(7); - } - - while (N-- > 0 && I < checked((int)TableSize)) - { - Table[I++] = 0; - } - } - } - if (UnpAudioBlock) - { - for (int I = 0; I < UnpChannels; I++) - { - MakeDecodeTables(Table, (int)(I * MC20), MD[I], MC20); - } - } - else - { - MakeDecodeTables(Table, 0, BlockTables.LD, NC20); - MakeDecodeTables(Table, (int)NC20, BlockTables.DD, DC20); - MakeDecodeTables(Table, (int)(NC20 + DC20), BlockTables.RD, RC20); - } - Array.Copy(Table, 0, this.UnpOldTable20, 0, UnpOldTable20.Length); - return true; - } - private void ReadLastTables() { if (ReadTop >= Inp.InAddr + 5) diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index c614e591..2959021b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -24,11 +24,7 @@ internal partial class Unpack // Check TablesRead5 to be sure that we read tables at least once // regardless of current block header TablePresent flag. // So we can safefly use these tables below. - if ( - !ReadBlockHeader(Inp) - || !ReadTables(Inp, ref BlockHeader, ref BlockTables) - || !TablesRead5 - ) + if (!ReadBlockHeader(Inp) || !ReadTables(Inp) || !TablesRead5) { return; } @@ -55,10 +51,7 @@ internal partial class Unpack FileDone = true; break; } - if ( - !ReadBlockHeader(Inp, ref BlockHeader) - || !ReadTables(Inp, ref BlockHeader, ref BlockTables) - ) + if (!ReadBlockHeader(Inp) || !ReadTables(Inp)) { return; }