public void Decode(Window window) { // Clear cache codeTable.Cache.Initialize(); // Set the target window offset window.TargetWindowOffset = (uint)output.Position; // For each instruction Instruction firstInstruction, secondInstruction; while (!window.Instructions.Eof) { byte codeIndex = window.Instructions.ReadByte(); codeTable.GetInstructions(codeIndex, out firstInstruction, out secondInstruction); firstInstruction.Decode(window, input, output); secondInstruction.Decode(window, input, output); } // Check all data has been decoded if (output.Position - window.TargetWindowOffset != window.TargetWindowLength) throw new Exception("Target window not fully decoded"); // Check checksum if (window.Source.Contains(WindowFields.Adler32)) { output.Position = window.TargetWindowOffset; uint newAdler = Adler32.Run(1, output, window.TargetWindowLength); if (newAdler != window.Checksum) throw new Exception("Invalid checksum"); } }
public void Decode(Window window, Stream input, Stream output) { if (Type != InstructionType.Noop && SizeInTable == 0) Size = window.Instructions.ReadInteger(); DecodeInstruction(window, input, output); }
public void Run() { WindowReader windowReader = new WindowReader(Patch, Header); WindowDecoder windowDecoder = new WindowDecoder(Input, Output); // Decode windows until there are no more bytes to process while (Patch.Position < Patch.Length) { DisposeLastWindow(); Window window = windowReader.Read(); LastWindow = window; windowDecoder.Decode(window); OnProgressChanged(1.0 * Patch.Position / Patch.Length); } OnFinished(); }
private Window ReadWindow() { Window window = new Window(); // Get window indicator window.Source = (WindowFields)vcdReader.ReadByte(); if (window.Source.Contains(WindowFields.NotSupported)) throw new FormatException("unrecognized window indicator bits set"); if (window.Source.Contains(WindowFields.Source | WindowFields.Target)) { window.SourceSegmentLength = vcdReader.ReadInteger(); window.SourceSegmentOffset = vcdReader.ReadInteger(); } // Copy offset and copy length may not overflow if (window.SourceSegmentOffset.CheckOverflow(window.SourceSegmentLength)) throw new FormatException("decoder copy window overflows a file offset"); // Check copy window bounds if (window.Source.Contains(WindowFields.Target) && window.SourceSegmentOffset + window.SourceSegmentLength > lastWindowOffset) throw new FormatException("VCD_TARGET window out of bounds"); // Start of Delta Encoding Data vcdReader.ReadInteger(); // Length of the delta encoding (following data) // Get the length of target window window.TargetWindowLength = vcdReader.ReadInteger(); lastWindowLength = window.TargetWindowLength; // Set the maximum decoder position, beyond which we should not // decode any data. This may not exceed the size of a UInt32. if (window.SourceSegmentLength.CheckOverflow(window.TargetWindowLength)) throw new FormatException("decoder target window overflows a UInt32"); // Check for malicious files if (window.TargetWindowLength > HardMaxWindowSize) throw new FormatException("Hard window size exceeded"); // Get compressed / delta fields window.CompressedFields = (WindowCompressedFields)vcdReader.ReadByte(); if (window.CompressedFields.Contains(WindowCompressedFields.Invalid)) throw new FormatException("unrecognized delta indicator bits set"); // Compressed fields is only used with secondary compression if (window.CompressedFields != WindowCompressedFields.None && header.SecondaryCompressor == SecondaryCompressor.None) throw new FormatException("invalid delta indicator bits set"); // Read section lengths uint dataLength = vcdReader.ReadInteger(); uint instructionsLength = vcdReader.ReadInteger(); uint addressesLength = vcdReader.ReadInteger(); // Read checksum if so (it's in big-endian-non-integer) if (window.Source.Contains(WindowFields.Adler32)) { byte[] checksum = vcdReader.ReadBytes(4); window.Checksum = (uint)((checksum[0] << 24) | (checksum[1] << 16) | (checksum[2] << 8) | checksum[3]); } // Read sections MemoryStream data = new MemoryStream(vcdReader.ReadBytes(dataLength)); MemoryStream instructions = new MemoryStream(vcdReader.ReadBytes(instructionsLength)); MemoryStream addresses = new MemoryStream(vcdReader.ReadBytes(addressesLength)); window.Data = new VcdReader(data); window.Instructions = new VcdReader(instructions); window.Addresses = new VcdReader(addresses); return window; }
private void DisposeLastWindow() { if (LastWindow != null) { LastWindow.Data.BaseStream.Dispose(); LastWindow.Data = null; LastWindow.Instructions.BaseStream.Dispose(); LastWindow.Instructions = null; LastWindow.Addresses.BaseStream.Dispose(); LastWindow.Addresses = null; LastWindow = null; } }
public abstract void DecodeInstruction(Window window, Stream input, Stream output);