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); }
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); }
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); }