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);
        }
Exemple #3
0
        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;
        }
Exemple #5
0
        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);