Example #1
0
        private static bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new FileStream(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress, true))
                    using (MemoryStream stream = new MemoryStream())
                        using (MD5 md5 = MD5.Create())
                        {
                            int hashSize = md5.HashSize / 8;

                            try
                            {
                                deflateStream.CopyTo(stream);
                            }
                            catch
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            stream.Seek(0L, SeekOrigin.Begin);

                            byte[] currentHash = new byte[hashSize];
                            stream.Read(currentHash, 0, hashSize);

                            byte[] expectedHash = md5.ComputeHash(stream);

                            if (!CompareHash(currentHash, expectedHash))
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            stream.Seek((long)hashSize, SeekOrigin.Begin);

                            Header header = ReadHeader(stream);

                            if (header.Magic != HeaderMagic)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.CacheFileVersion != InternalVersion)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.FeatureInfo != GetFeatureInfo())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.OSPlatform != GetOSPlatform())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.InfosLen % InfoEntry.Stride != 0)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            byte[] infosBuf       = new byte[header.InfosLen];
                            byte[] codesBuf       = new byte[header.CodesLen];
                            byte[] relocsBuf      = new byte[header.RelocsLen];
                            byte[] unwindInfosBuf = new byte[header.UnwindInfosLen];

                            stream.Read(infosBuf, 0, header.InfosLen);
                            stream.Read(codesBuf, 0, header.CodesLen);
                            stream.Read(relocsBuf, 0, header.RelocsLen);
                            stream.Read(unwindInfosBuf, 0, header.UnwindInfosLen);

                            try
                            {
                                PtcJumpTable = PtcJumpTable.Deserialize(stream);
                            }
                            catch
                            {
                                PtcJumpTable = new PtcJumpTable();

                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            _infosStream.Write(infosBuf, 0, header.InfosLen);
                            _codesStream.Write(codesBuf, 0, header.CodesLen);
                            _relocsStream.Write(relocsBuf, 0, header.RelocsLen);
                            _unwindInfosStream.Write(unwindInfosBuf, 0, header.UnwindInfosLen);
                        }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetInfosEntriesCount()}).");

            return(true);
        }
Example #2
0
        private static unsafe bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
                {
                    OuterHeader outerHeader = DeserializeStructure <OuterHeader>(compressedStream);

                    if (!outerHeader.IsHeaderValid())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.Magic != _outerHeaderMagic)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.CacheFileVersion != InternalVersion)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.Endianness != GetEndianness())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.FeatureInfo != GetFeatureInfo())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.MemoryManagerMode != GetMemoryManagerMode())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    if (outerHeader.OSPlatform != GetOSPlatform())
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    IntPtr intPtr = IntPtr.Zero;

                    try
                    {
                        intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));

                        using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite))
                        {
                            try
                            {
                                deflateStream.CopyTo(stream);
                            }
                            catch
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            Debug.Assert(stream.Position == stream.Length);

                            stream.Seek(0L, SeekOrigin.Begin);

                            InnerHeader innerHeader = DeserializeStructure <InnerHeader>(stream);

                            if (!innerHeader.IsHeaderValid())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (innerHeader.Magic != _innerHeaderMagic)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
                            stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);

                            Hash128 infosHash = XXHash128.ComputeHash(infosBytes);

                            if (innerHeader.InfosHash != infosHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan <byte> .Empty;
                            stream.Seek(innerHeader.CodesLength, SeekOrigin.Current);

                            Hash128 codesHash = XXHash128.ComputeHash(codesBytes);

                            if (innerHeader.CodesHash != codesHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
                            stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);

                            Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes);

                            if (innerHeader.RelocsHash != relocsHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
                            stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);

                            Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);

                            if (innerHeader.UnwindInfosHash != unwindInfosHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, innerHeader.PtcJumpTableLength);
                            stream.Seek(innerHeader.PtcJumpTableLength, SeekOrigin.Current);

                            Debug.Assert(stream.Position == stream.Length);

                            Hash128 ptcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes);

                            if (innerHeader.PtcJumpTableHash != ptcJumpTableHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            stream.Seek((long)Unsafe.SizeOf <InnerHeader>(), SeekOrigin.Begin);

                            _infosStream.Write(infosBytes);
                            stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);

                            _codesList.ReadFrom(stream);

                            _relocsStream.Write(relocsBytes);
                            stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);

                            _unwindInfosStream.Write(unwindInfosBytes);
                            stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);

                            PtcJumpTable = PtcJumpTable.Deserialize(stream);

                            Debug.Assert(stream.Position == stream.Length);
                        }
                    }
                    finally
                    {
                        if (intPtr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(intPtr);
                        }
                    }
                }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()}).");

            return(true);
        }
Example #3
0
        private static unsafe bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
                {
                    Hash128 currentSizeHash = DeserializeStructure <Hash128>(compressedStream);

                    Span <byte> sizeBytes = new byte[sizeof(int)];
                    compressedStream.Read(sizeBytes);
                    Hash128 expectedSizeHash = XXHash128.ComputeHash(sizeBytes);

                    if (currentSizeHash != expectedSizeHash)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    int size = BinaryPrimitives.ReadInt32LittleEndian(sizeBytes);

                    IntPtr intPtr = IntPtr.Zero;

                    try
                    {
                        intPtr = Marshal.AllocHGlobal(size);

                        using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite))
                        {
                            try
                            {
                                deflateStream.CopyTo(stream);
                            }
                            catch
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            int hashSize = Unsafe.SizeOf <Hash128>();

                            stream.Seek(0L, SeekOrigin.Begin);
                            Hash128 currentHash = DeserializeStructure <Hash128>(stream);

                            ReadOnlySpan <byte> streamBytes  = new(stream.PositionPointer, (int)(stream.Length - stream.Position));
                            Hash128             expectedHash = XXHash128.ComputeHash(streamBytes);

                            if (currentHash != expectedHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            stream.Seek((long)hashSize, SeekOrigin.Begin);

                            Header header = ReadHeader(stream);

                            if (header.Magic != _headerMagic)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.CacheFileVersion != InternalVersion)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.Endianness != GetEndianness())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.FeatureInfo != GetFeatureInfo())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.OSPlatform != GetOSPlatform())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.InfosLen % InfoEntry.Stride != 0)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> infosBuf = new(stream.PositionPointer, header.InfosLen);
                            stream.Seek(header.InfosLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> codesBuf = new(stream.PositionPointer, header.CodesLen);
                            stream.Seek(header.CodesLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> relocsBuf = new(stream.PositionPointer, header.RelocsLen);
                            stream.Seek(header.RelocsLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> unwindInfosBuf = new(stream.PositionPointer, header.UnwindInfosLen);
                            stream.Seek(header.UnwindInfosLen, SeekOrigin.Current);

                            try
                            {
                                PtcJumpTable = PtcJumpTable.Deserialize(stream);
                            }
                            catch
                            {
                                PtcJumpTable = new PtcJumpTable();

                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            _infosStream.Write(infosBuf);
                            _codesStream.Write(codesBuf);
                            _relocsStream.Write(relocsBuf);
                            _unwindInfosStream.Write(unwindInfosBuf);
                        }
                    }
                    finally
                    {
                        if (intPtr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(intPtr);
                        }
                    }
                }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetInfosEntriesCount()}).");

            return(true);
        }