From 978f41a4d9a282c53d5cbc176fecfe462acc75e3 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Wed, 20 Mar 2024 22:38:39 +0100 Subject: [PATCH] Make some stuff safer maybe. --- .../Buffers/MemoryMappedBuffer.cs | 60 +++++++++---------- Penumbra.CrashHandler/Program.cs | 19 ++++-- Penumbra/Services/ValidityChecker.cs | 44 +++++++------- 3 files changed, 67 insertions(+), 56 deletions(-) diff --git a/Penumbra.CrashHandler/Buffers/MemoryMappedBuffer.cs b/Penumbra.CrashHandler/Buffers/MemoryMappedBuffer.cs index 35055864..c4e2627e 100644 --- a/Penumbra.CrashHandler/Buffers/MemoryMappedBuffer.cs +++ b/Penumbra.CrashHandler/Buffers/MemoryMappedBuffer.cs @@ -9,15 +9,15 @@ public class MemoryMappedBuffer : IDisposable { private const int MinHeaderLength = 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; - private readonly MemoryMappedFile _file; - private readonly MemoryMappedViewAccessor _header; + private readonly MemoryMappedFile _file; + private readonly MemoryMappedViewAccessor _header; private readonly MemoryMappedViewAccessor[] _lines; - public readonly int Version; - public readonly uint LineCount; - public readonly uint LineCapacity; + public readonly int Version; + public readonly uint LineCount; + public readonly uint LineCapacity; private readonly uint _lineMask; - private bool _disposed; + private bool _disposed; protected uint CurrentLineCount { @@ -39,20 +39,20 @@ public class MemoryMappedBuffer : IDisposable public MemoryMappedBuffer(string mapName, int version, uint lineCount, uint lineCapacity) { - Version = version; - LineCount = BitOperations.RoundUpToPowerOf2(Math.Clamp(lineCount, 2, int.MaxValue >> 3)); + Version = version; + LineCount = BitOperations.RoundUpToPowerOf2(Math.Clamp(lineCount, 2, int.MaxValue >> 3)); LineCapacity = BitOperations.RoundUpToPowerOf2(Math.Clamp(lineCapacity, 2, int.MaxValue >> 3)); - _lineMask = LineCount - 1; - var fileName = Encoding.UTF8.GetBytes(mapName); + _lineMask = LineCount - 1; + var fileName = Encoding.UTF8.GetBytes(mapName); var headerLength = (uint)(4 + 4 + 4 + 4 + 4 + 4 + 4 + fileName.Length + 1); headerLength = (headerLength & 0b111) > 0 ? (headerLength & ~0b111u) + 0b1000 : headerLength; var capacity = LineCount * LineCapacity + headerLength; _file = MemoryMappedFile.CreateNew(mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, HandleInheritability.Inheritable); _header = _file.CreateViewAccessor(0, headerLength); - _header.Write(0, headerLength); - _header.Write(4, Version); - _header.Write(8, LineCount); + _header.Write(0, headerLength); + _header.Write(4, Version); + _header.Write(8, LineCount); _header.Write(12, LineCapacity); _header.WriteArray(28, fileName, 0, fileName.Length); _header.Write(fileName.Length + 28, (byte)0); @@ -65,16 +65,16 @@ public class MemoryMappedBuffer : IDisposable uint? expectedMinLineCapacity = null) { _file = MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable); - using var headerLine = _file.CreateViewAccessor(0, 4, MemoryMappedFileAccess.Read); - var headerLength = headerLine.ReadUInt32(0); + using var headerLine = _file.CreateViewAccessor(0, 4, MemoryMappedFileAccess.Read); + var headerLength = headerLine.ReadUInt32(0); if (headerLength < MinHeaderLength) Throw($"Map {mapName} did not contain a valid header."); - _header = _file.CreateViewAccessor(0, headerLength, MemoryMappedFileAccess.ReadWrite); - Version = _header.ReadInt32(4); - LineCount = _header.ReadUInt32(8); + _header = _file.CreateViewAccessor(0, headerLength, MemoryMappedFileAccess.ReadWrite); + Version = _header.ReadInt32(4); + LineCount = _header.ReadUInt32(8); LineCapacity = _header.ReadUInt32(12); - _lineMask = LineCount - 1; + _lineMask = LineCount - 1; if (expectedVersion.HasValue && expectedVersion.Value != Version) Throw($"Map {mapName} has version {Version} instead of {expectedVersion.Value}."); @@ -122,25 +122,25 @@ public class MemoryMappedBuffer : IDisposable protected static int WriteString(string text, Span span) { - var bytes = Encoding.UTF8.GetBytes(text); - var length = bytes.Length + 1; + var bytes = Encoding.UTF8.GetBytes(text); + var source = (Span)bytes; + var length = source.Length + 1; if (length > span.Length) - throw new Exception($"String {text} is too long to write into span."); - - bytes.CopyTo(span); + source = source[..(span.Length - 1)]; + source.CopyTo(span); span[bytes.Length] = 0; - return length; + return source.Length + 1; } protected static int WriteSpan(ReadOnlySpan input, Span span) { var length = input.Length + 1; if (length > span.Length) - throw new Exception("Byte array is too long to write into span."); + input = input[..(span.Length - 1)]; input.CopyTo(span); span[input.Length] = 0; - return length; + return input.Length + 1; } protected Span GetLine(int i) @@ -150,7 +150,7 @@ public class MemoryMappedBuffer : IDisposable lock (_header) { - var lineIdx = CurrentLinePosition + i & _lineMask; + var lineIdx = (CurrentLinePosition + i) & _lineMask; if (lineIdx > CurrentLineCount) return null; @@ -168,8 +168,8 @@ public class MemoryMappedBuffer : IDisposable if (currentLineCount == LineCount) { var currentLinePos = CurrentLinePosition; - view = _lines[currentLinePos]!; - CurrentLinePosition = currentLinePos + 1 & _lineMask; + view = _lines[currentLinePos]!; + CurrentLinePosition = (currentLinePos + 1) & _lineMask; } else { diff --git a/Penumbra.CrashHandler/Program.cs b/Penumbra.CrashHandler/Program.cs index 518e2d04..0ea76ac6 100644 --- a/Penumbra.CrashHandler/Program.cs +++ b/Penumbra.CrashHandler/Program.cs @@ -14,12 +14,21 @@ public class CrashHandler { using var reader = new GameEventLogReader(); var parent = Process.GetProcessById(pid); - + using var handle = parent.SafeHandle; parent.WaitForExit(); - var exitCode = parent.ExitCode; - var obj = reader.Dump("Crash", pid, exitCode, args[2], args[3]); - using var fs = File.Open(args[0], FileMode.Create); - using var w = new Utf8JsonWriter(fs, new JsonWriterOptions { Indented = true }); + int exitCode; + try + { + exitCode = parent.ExitCode; + } + catch (Exception ex) + { + exitCode = -1; + } + + var obj = reader.Dump("Crash", pid, exitCode, args[2], args[3]); + using var fs = File.Open(args[0], FileMode.Create); + using var w = new Utf8JsonWriter(fs, new JsonWriterOptions { Indented = true }); obj.WriteTo(w, new JsonSerializerOptions() { WriteIndented = true }); } catch (Exception ex) diff --git a/Penumbra/Services/ValidityChecker.cs b/Penumbra/Services/ValidityChecker.cs index d4b5005f..cc70306b 100644 --- a/Penumbra/Services/ValidityChecker.cs +++ b/Penumbra/Services/ValidityChecker.cs @@ -21,7 +21,15 @@ public class ValidityChecker : IService public readonly string Version; public readonly string CommitHash; - public readonly string GameVersion; + + public unsafe string GameVersion + { + get + { + var framework = Framework.Instance(); + return framework == null ? string.Empty : framework->GameVersion[0]; + } + } public ValidityChecker(DalamudPluginInterface pi) { @@ -30,14 +38,10 @@ public class ValidityChecker : IService IsValidSourceRepo = CheckSourceRepo(pi); var assembly = GetType().Assembly; - Version = assembly.GetName().Version?.ToString() ?? string.Empty; - CommitHash = assembly.GetCustomAttribute()?.InformationalVersion ?? "Unknown"; - GameVersion = GetGameVersion(); + Version = assembly.GetName().Version?.ToString() ?? string.Empty; + CommitHash = assembly.GetCustomAttribute()?.InformationalVersion ?? "Unknown"; } - private static unsafe string GetGameVersion() - => Framework.Instance()->GameVersion[0]; - public void LogExceptions() { if (ImcExceptions.Count > 0) @@ -49,16 +53,16 @@ public class ValidityChecker : IService private static bool CheckDevPluginPenumbra(DalamudPluginInterface pi) { #if !DEBUG - var path = Path.Combine( pi.DalamudAssetDirectory.Parent?.FullName ?? "INVALIDPATH", "devPlugins", "Penumbra" ); - var dir = new DirectoryInfo( path ); + var path = Path.Combine(pi.DalamudAssetDirectory.Parent?.FullName ?? "INVALIDPATH", "devPlugins", "Penumbra"); + var dir = new DirectoryInfo(path); try { - return dir.Exists && dir.EnumerateFiles( "*.dll", SearchOption.AllDirectories ).Any(); + return dir.Exists && dir.EnumerateFiles("*.dll", SearchOption.AllDirectories).Any(); } - catch( Exception e ) + catch (Exception e) { - Penumbra.Log.Error( $"Could not check for dev plugin Penumbra:\n{e}" ); + Penumbra.Log.Error($"Could not check for dev plugin Penumbra:\n{e}"); return true; } #else @@ -71,11 +75,9 @@ public class ValidityChecker : IService { #if !DEBUG var checkedDirectory = pi.AssemblyLocation.Directory?.Parent?.Parent?.Name; - var ret = checkedDirectory?.Equals( "installedPlugins", StringComparison.OrdinalIgnoreCase ) ?? false; - if( !ret ) - { - Penumbra.Log.Error( $"Penumbra is not correctly installed. Application loaded from \"{pi.AssemblyLocation.Directory!.FullName}\"." ); - } + var ret = checkedDirectory?.Equals("installedPlugins", StringComparison.OrdinalIgnoreCase) ?? false; + if (!ret) + Penumbra.Log.Error($"Penumbra is not correctly installed. Application loaded from \"{pi.AssemblyLocation.Directory!.FullName}\"."); return !ret; #else @@ -89,10 +91,10 @@ public class ValidityChecker : IService #if !DEBUG return pi.SourceRepository?.Trim().ToLowerInvariant() switch { - null => false, - RepositoryLower => true, - SeaOfStarsLower => true, - _ => false, + null => false, + RepositoryLower => true, + SeaOfStarsLower => true, + _ => false, }; #else return true;