// We use it instead of direct PPM.DecodeChar call to be sure that // we reset PPM structures in case of corrupt data. It is important, // because these structures can be invalid after PPM.DecodeChar returned -1. int SafePPMDecodeChar() { int Ch = PPM.DecodeChar(); if (Ch == -1) // Corrupt PPM data found. { PPM.CleanUp(); // Reset possibly corrupt PPM data structures. UnpBlockType = BLOCK_LZ; // Set faster and more fail proof LZ mode. } return(Ch); }
void Unpack29(bool Solid) { uint Bits; if (DDecode[1] == 0) { int Dist = 0, BitLength = 0, Slot = 0; for (int I = 0; I < DBitLengthCounts.Length; I++, BitLength++) { for (int J = 0; J < DBitLengthCounts[I]; J++, Slot++, Dist += (1 << BitLength)) { DDecode[Slot] = Dist; DBits[Slot] = (byte)BitLength; } } } FileExtracted = true; if (!Suspended) { UnpInitData(Solid); if (!UnpReadBuf30()) { return; } if ((!Solid || !TablesRead3) && !ReadTables30()) { return; } } while (true) { UnpPtr &= MaxWinMask; if (Inp.InAddr > ReadBorder) { if (!UnpReadBuf30()) { break; } } if (((WrPtr - UnpPtr) & MaxWinMask) < 260 && WrPtr != UnpPtr) { UnpWriteBuf30(); if (WrittenFileSize > DestUnpSize) { return; } if (Suspended) { FileExtracted = false; return; } } if (UnpBlockType == BLOCK_PPM) { // Here speed is critical, so we do not use SafePPMDecodeChar, // because sometimes even the inline function can introduce // some additional penalty. int Ch = PPM.DecodeChar(); if (Ch == -1) // Corrupt PPM data found. { PPM.CleanUp(); // Reset possibly corrupt PPM data structures. UnpBlockType = BLOCK_LZ; // Set faster and more fail proof LZ mode. break; } if (Ch == PPMEscChar) { int NextCh = SafePPMDecodeChar(); if (NextCh == 0) // End of PPM encoding. { if (!ReadTables30()) { break; } continue; } if (NextCh == -1) // Corrupt PPM data found. { break; } if (NextCh == 2) // End of file in PPM mode. { break; } if (NextCh == 3) // Read VM code. { if (!ReadVMCodePPM()) { break; } continue; } if (NextCh == 4) // LZ inside of PPM. { uint Distance = 0, Length; bool Failed = false; for (int I = 0; I < 4 && !Failed; I++) { int _Ch = SafePPMDecodeChar(); if (_Ch == -1) { Failed = true; } else if (I == 3) { Length = (byte)_Ch; } else { Distance = (Distance << 8) + (byte)_Ch; } } if (Failed) { break; } CopyString(Length + 32, Distance + 2); continue; } if (NextCh == 5) // One byte distance match (RLE) inside of PPM. { int Length = SafePPMDecodeChar(); if (Length == -1) { break; } CopyString((uint)(Length + 4), 1); continue; } // If we are here, NextCh must be 1, what means that current byte // is equal to our 'escape' byte, so we just store it to Window. } Window[UnpPtr++] = (byte)Ch; continue; } uint Number = DecodeNumber(Inp, BlockTables.LD); if (Number < 256) { Window[UnpPtr++] = (byte)Number; continue; } if (Number >= 271) { uint Length = (uint)(LDecode[Number -= 271] + 3); if ((Bits = LBits[Number]) > 0) { Length += Inp.getbits() >> (int)(16 - Bits); Inp.addbits(Bits); } uint DistNumber = DecodeNumber(Inp, BlockTables.DD); uint Distance = (uint)(DDecode[DistNumber] + 1); if ((Bits = DBits[DistNumber]) > 0) { if (DistNumber > 9) { if (Bits > 4) { Distance += ((Inp.getbits() >> (int)(20 - Bits)) << 4); Inp.addbits(Bits - 4); } if (LowDistRepCount > 0) { LowDistRepCount--; Distance += (uint)PrevLowDist; } else { uint LowDist = DecodeNumber(Inp, BlockTables.LDD); if (LowDist == 16) { LowDistRepCount = (int)(LOW_DIST_REP_COUNT - 1); Distance += (uint)PrevLowDist; } else { Distance += LowDist; PrevLowDist = (int)LowDist; } } } else { Distance += Inp.getbits() >> (int)(16 - Bits); Inp.addbits(Bits); } } if (Distance >= 0x2000) { Length++; if (Distance >= 0x40000) { Length++; } } InsertOldDist(Distance); LastLength = Length; CopyString(Length, Distance); continue; } if (Number == 256) { if (!ReadEndOfBlock()) { break; } continue; } if (Number == 257) { if (!ReadVMCode()) { break; } continue; } if (Number == 258) { if (LastLength != 0) { CopyString(LastLength, OldDist[0]); } continue; } if (Number < 263) { uint DistNum = Number - 259; uint Distance = OldDist[DistNum]; for (uint I = DistNum; I > 0; I--) { OldDist[I] = OldDist[I - 1]; } OldDist[0] = Distance; uint LengthNumber = DecodeNumber(Inp, BlockTables.RD); int Length = LDecode[LengthNumber] + 2; if ((Bits = LBits[LengthNumber]) > 0) { Length += (int)(Inp.getbits() >> (int)(16 - Bits)); Inp.addbits(Bits); } LastLength = (uint)Length; CopyString((uint)Length, Distance); continue; } if (Number < 272) { uint Distance = (uint)(SDDecode[Number -= 263] + 1); if ((Bits = SDBits[Number]) > 0) { Distance += Inp.getbits() >> (int)(16 - Bits); Inp.addbits(Bits); } InsertOldDist(Distance); LastLength = 2; CopyString(2, Distance); continue; } } UnpWriteBuf30(); }