void UnpWriteBuf30() { uint WrittenBorder = (uint)WrPtr; uint WriteSize = (uint)((UnpPtr - WrittenBorder) & MaxWinMask); for (int I = 0; I < PrgStack.Count; I++) { // Here we apply filters to data which we need to write. // We always copy data to virtual machine memory before processing. // We cannot process them just in place in Window buffer, because // these data can be used for future string matches, so we must // preserve them in original form. UnpackFilter30 flt = PrgStack[I]; if (flt == null) { continue; } if (flt.NextWindow) { flt.NextWindow = false; continue; } uint BlockStart = flt.BlockStart; uint BlockLength = flt.BlockLength; if (((BlockStart - WrittenBorder) & MaxWinMask) < WriteSize) { if (WrittenBorder != BlockStart) { UnpWriteArea(WrittenBorder, BlockStart); WrittenBorder = BlockStart; WriteSize = (uint)((UnpPtr - WrittenBorder) & MaxWinMask); } if (BlockLength <= WriteSize) { uint BlockEnd = (BlockStart + BlockLength) & MaxWinMask; if (BlockStart < BlockEnd || BlockEnd == 0) { VM.SetMemory(0, Window + BlockStart, BlockLength); } else { uint FirstPartLength = uint(MaxWinSize - BlockStart); VM.SetMemory(0, Window + BlockStart, FirstPartLength); VM.SetMemory(FirstPartLength, Window, BlockEnd); } VM_PreparedProgram *ParentPrg = &Filters30[flt->ParentFilter]->Prg; VM_PreparedProgram *Prg = &flt->Prg; ExecuteCode(Prg); byte[] FilteredData = Prg.FilteredData; uint FilteredDataSize = Prg.FilteredDataSize; delete PrgStack[I];
bool AddVMCode(uint FirstByte, byte[] Code, int CodeSize) { VMCodeInp.InitBitInput(); //x memcpy(VMCodeInp.InBuf,Code,Min(BitInput.MAX_SIZE,CodeSize)); Array.Copy(Code, 0, VMCodeInp.InBuf, 0, Math.Min(BitInput.MAX_SIZE, CodeSize)); VM.Init(); uint FiltPos; if ((FirstByte & 0x80) != 0) { FiltPos = RarVM.ReadData(VMCodeInp); if (FiltPos == 0) { InitFilters30(false); } else { FiltPos--; } } else { FiltPos = (uint)this.LastFilter; // Use the same filter as last time. } if (FiltPos > Filters30.Count || FiltPos > OldFilterLengths.Count) { return(false); } LastFilter = (int)FiltPos; bool NewFilter = (FiltPos == Filters30.Count); UnpackFilter30 StackFilter = new UnpackFilter30(); // New filter for PrgStack. UnpackFilter30 Filter; if (NewFilter) // New filter code, never used before since VM reset. { if (FiltPos > MAX3_UNPACK_FILTERS) { // Too many different filters, corrupt archive. //delete StackFilter; return(false); } Filters30.Add(1); Filters30[Filters30.Count - 1] = Filter = new UnpackFilter30(); StackFilter.ParentFilter = (uint)(Filters30.Count - 1); // Reserve one item to store the data block length of our new filter // entry. We'll set it to real block length below, after reading it. // But we need to initialize it now, because when processing corrupt // data, we can access this item even before we set it to real value. OldFilterLengths.Add(0); } else // Filter was used in the past. { Filter = Filters30[(int)FiltPos]; StackFilter.ParentFilter = FiltPos; } int EmptyCount = 0; for (int I = 0; I < PrgStack.Count; I++) { PrgStack[I - EmptyCount] = PrgStack[I]; if (PrgStack[I] == null) { EmptyCount++; } if (EmptyCount > 0) { PrgStack[I] = null; } } if (EmptyCount == 0) { if (PrgStack.Count > MAX3_UNPACK_FILTERS) { //delete StackFilter; return(false); } PrgStack.Add(1); EmptyCount = 1; } size_t StackPos = (uint)(this.PrgStack.Count - EmptyCount); PrgStack[(int)StackPos] = StackFilter; uint BlockStart = RarVM.ReadData(VMCodeInp); if ((FirstByte & 0x40) != 0) { BlockStart += 258; } StackFilter.BlockStart = (uint)((BlockStart + UnpPtr) & MaxWinMask); if ((FirstByte & 0x20) != 0) { StackFilter.BlockLength = RarVM.ReadData(VMCodeInp); // Store the last data block length for current filter. OldFilterLengths[(int)FiltPos] = (int)StackFilter.BlockLength; } else { // Set the data block size to same value as the previous block size // for same filter. It is possible for corrupt data to access a new // and not filled yet item of OldFilterLengths array here. This is why // we set new OldFilterLengths items to zero above. StackFilter.BlockLength = FiltPos < OldFilterLengths.Count ? OldFilterLengths[(int)FiltPos]:0; } StackFilter.NextWindow = WrPtr != UnpPtr && ((WrPtr - UnpPtr) & MaxWinMask) <= BlockStart; // DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart); memset(StackFilter.Prg.InitR, 0, sizeof(StackFilter.Prg.InitR)); StackFilter.Prg.InitR[4] = StackFilter.BlockLength; if ((FirstByte & 0x10) != 0) // Set registers to optional parameters if any. { uint InitMask = VMCodeInp.fgetbits() >> 9; VMCodeInp.faddbits(7); for (int I = 0; I < 7; I++) { if ((InitMask & (1 << I)) != 0) { StackFilter.Prg.InitR[I] = RarVM.ReadData(VMCodeInp); } } } if (NewFilter) { uint VMCodeSize = RarVM.ReadData(VMCodeInp); if (VMCodeSize >= 0x10000 || VMCodeSize == 0) { return(false); } Array <byte> VMCode(VMCodeSize); for (uint I = 0; I < VMCodeSize; I++) { if (VMCodeInp.Overflow(3)) { return(false); } VMCode[I] = VMCodeInp.fgetbits() >> 8; VMCodeInp.faddbits(8); } VM.Prepare(&VMCode[0], VMCodeSize, &Filter->Prg); } StackFilter.Prg.Type = Filter.Prg.Type; return(true); }