From 8c0ae1d85dd3b11c8a2315a2873e336d090f73e3 Mon Sep 17 00:00:00 2001 From: Marek Aldorf Date: Mon, 20 Jan 2025 10:13:20 +0100 Subject: [PATCH] Enhance memory reading and COM object management with error handling and platform checks --- .../ElfBinary/Dwarf/DwarfMemoryReader.cs | 17 +++++-- src/BinaryParsers/PEBinary/PEBinary.cs | 2 +- .../ProgramDatabase/MSDiaComWrapper.cs | 3 ++ .../PEBinary/ProgramDatabase/Pdb.cs | 47 +++++++++++++------ .../PEBinary/ProgramDatabase/SourceFile.cs | 2 + .../PEBinary/ProgramDatabase/Symbol.cs | 6 ++- .../PEBinary/PEBinaryTests.cs | 2 + 7 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/BinaryParsers/ElfBinary/Dwarf/DwarfMemoryReader.cs b/src/BinaryParsers/ElfBinary/Dwarf/DwarfMemoryReader.cs index b6660b95f..48a65c481 100644 --- a/src/BinaryParsers/ElfBinary/Dwarf/DwarfMemoryReader.cs +++ b/src/BinaryParsers/ElfBinary/Dwarf/DwarfMemoryReader.cs @@ -121,13 +121,20 @@ public ulong ReadLength(out bool is64bit) /// /// Reads the string from the current position in the stream. /// - [HandleProcessCorruptedStateExceptions] public string ReadString() { - string result = Marshal.PtrToStringAnsi(pointer + Position); - - Position += result.Length + 1; - return result; + try + { + string result = Marshal.PtrToStringAnsi(pointer + Position); + Position += result.Length + 1; + return result; + } + catch (Exception ex) + { + // Handle the exception as needed, for example, log it or rethrow + // For now, we will just rethrow it + throw new InvalidOperationException("Failed to read string from memory.", ex); + } } /// diff --git a/src/BinaryParsers/PEBinary/PEBinary.cs b/src/BinaryParsers/PEBinary/PEBinary.cs index d762f8b2f..f5a37c2a8 100644 --- a/src/BinaryParsers/PEBinary/PEBinary.cs +++ b/src/BinaryParsers/PEBinary/PEBinary.cs @@ -80,7 +80,7 @@ public static void ClearLocalSymbolDirectoriesCache() public PE PE { get; private set; } - public Pdb Pdb => this.pdb?.Value; + public Pdb Pdb => this.pdb?.Value ?? null; public StringBuilder PdbLoadTrace { get; set; } diff --git a/src/BinaryParsers/PEBinary/ProgramDatabase/MSDiaComWrapper.cs b/src/BinaryParsers/PEBinary/ProgramDatabase/MSDiaComWrapper.cs index a8b3f83db..db3c35ec7 100644 --- a/src/BinaryParsers/PEBinary/ProgramDatabase/MSDiaComWrapper.cs +++ b/src/BinaryParsers/PEBinary/ProgramDatabase/MSDiaComWrapper.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using Dia2Lib; @@ -23,6 +24,7 @@ private static extern int DllGetClassObject( [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppvObject); + [SupportedOSPlatform("windows")] private static void CoCreateFromMsdia(Guid clsidOfServer, Guid riid, out IntPtr pvObject) { IntPtr pClassFactory = IntPtr.Zero; @@ -40,6 +42,7 @@ private static void CoCreateFromMsdia(Guid clsidOfServer, Guid riid, out IntPtr private const string IDiaDataSourceRiid = "79F1BB5F-B66E-48E5-B6A9-1545C323CA3D"; private const string DiaSourceClsid = "E6756135-1E65-4D17-8576-610761398C3C"; + [SupportedOSPlatform("windows")] public static IDiaDataSource GetDiaSource() { IntPtr diaSourcePtr = IntPtr.Zero; diff --git a/src/BinaryParsers/PEBinary/ProgramDatabase/Pdb.cs b/src/BinaryParsers/PEBinary/ProgramDatabase/Pdb.cs index 7bce18874..937ef56af 100644 --- a/src/BinaryParsers/PEBinary/ProgramDatabase/Pdb.cs +++ b/src/BinaryParsers/PEBinary/ProgramDatabase/Pdb.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Text; using System.Threading; @@ -72,10 +73,7 @@ public Pdb( public string LoadTrace { - get - { - return $"{this.loadTrace}"; - } + get => $"{this.loadTrace}"; set { // We make this settable to allow the tool to clear the trace. This @@ -203,7 +201,7 @@ private IEnumerable CreateSourceFileIteratorImpl(IDiaSymbol inObject { if (sourceFilesEnum != null) { - Marshal.ReleaseComObject(sourceFilesEnum); + ReleaseComObject(sourceFilesEnum); } } } @@ -239,9 +237,9 @@ private T CreateDiaTable() where T : class for (int i = 0; i < enumTables.Count; i++) { IDiaTable table = enumTables.Item(i); - if (!(table is T result)) + if (table is not T result) { - Marshal.ReleaseComObject(table); + ReleaseComObject(table); } else { @@ -253,7 +251,7 @@ private T CreateDiaTable() where T : class { if (enumTables != null) { - Marshal.ReleaseComObject(enumTables); + ReleaseComObject(enumTables); } } @@ -288,7 +286,7 @@ private HashSet GenerateWritableSegmentSet() } finally { - Marshal.ReleaseComObject(segment); + ReleaseComObject(segment); } } } @@ -296,7 +294,7 @@ private HashSet GenerateWritableSegmentSet() { if (enumSegments != null) { - Marshal.ReleaseComObject(enumSegments); + ReleaseComObject(enumSegments); } } @@ -341,7 +339,7 @@ private HashSet GenerateExecutableSectionContribIds() } finally { - Marshal.ReleaseComObject(sectionContrib); + ReleaseComObject(sectionContrib); } } } @@ -349,7 +347,7 @@ private HashSet GenerateExecutableSectionContribIds() { if (enumSectionContribs != null) { - Marshal.ReleaseComObject(enumSectionContribs); + ReleaseComObject(enumSectionContribs); } } return result; @@ -397,12 +395,12 @@ public void Dispose() if (this.session != null) { - Marshal.ReleaseComObject(this.session); + ReleaseComObject(this.session); } if (this.dataSource != null) { - Marshal.ReleaseComObject(this.dataSource); + ReleaseComObject(this.dataSource); } } @@ -416,7 +414,9 @@ private void Init(string pePath, string symbolPath, string localSymbolDirectorie try { PlatformSpecificHelpers.ThrowIfNotOnWindows(); +#if WINDOWS this.WindowsNativeLoadPdbFromPEUsingDia(pePath, symbolPath, localSymbolDirectories); +#endif } catch (PlatformNotSupportedException ex) { @@ -448,7 +448,9 @@ private void Init(string pdbPath) try { PlatformSpecificHelpers.ThrowIfNotOnWindows(); +#if WINDOWS this.WindowsNativeLoadPdbUsingDia(pdbPath); +#endif } catch (PlatformNotSupportedException ex) { @@ -457,13 +459,14 @@ private void Init(string pdbPath) } } + [SupportedOSPlatform("windows")] private void WindowsNativeLoadPdbFromPEUsingDia(string peOrPdbPath, string symbolPath, string localSymbolDirectories) { IDiaDataSource diaSource = null; Environment.SetEnvironmentVariable("_NT_SYMBOL_PATH", ""); Environment.SetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", ""); - object pCallback = this.loadTrace != null ? this : (object)IntPtr.Zero; + object pCallback = this.loadTrace != null ? this : nint.Zero; if (!string.IsNullOrEmpty(localSymbolDirectories)) { @@ -501,6 +504,7 @@ private void WindowsNativeLoadPdbFromPEUsingDia(string peOrPdbPath, string symbo this.dataSource = diaSource; } + [SupportedOSPlatform("windows")] private void WindowsNativeLoadPdbUsingDia(string pdbPath) { this.restrictReferenceAndOriginalPathAccess = false; @@ -647,5 +651,18 @@ public bool RestrictSystemRootAccess() { return true; } + /// + /// Releases the COM object if running on Windows. + /// + /// The COM object to release. + private void ReleaseComObject(object comObject) + { +#if WINDOWS + if (comObject != null) + { + Marshal.ReleaseComObject(comObject); + } +#endif + } } } diff --git a/src/BinaryParsers/PEBinary/ProgramDatabase/SourceFile.cs b/src/BinaryParsers/PEBinary/ProgramDatabase/SourceFile.cs index 73dda0a75..86889855f 100644 --- a/src/BinaryParsers/PEBinary/ProgramDatabase/SourceFile.cs +++ b/src/BinaryParsers/PEBinary/ProgramDatabase/SourceFile.cs @@ -86,7 +86,9 @@ public void Dispose() { if (!this.disposed) { +#if WINDOWS Marshal.ReleaseComObject(this.sourceFile); +#endif } this.disposed = true; diff --git a/src/BinaryParsers/PEBinary/ProgramDatabase/Symbol.cs b/src/BinaryParsers/PEBinary/ProgramDatabase/Symbol.cs index ae3382b59..7faeb297f 100644 --- a/src/BinaryParsers/PEBinary/ProgramDatabase/Symbol.cs +++ b/src/BinaryParsers/PEBinary/ProgramDatabase/Symbol.cs @@ -364,9 +364,11 @@ public void Dispose() { if (!this.disposed) { +#if WINDOWS Marshal.ReleaseComObject(this.sym); - } +#endif + } this.disposed = true; } @@ -505,7 +507,9 @@ private IEnumerable CreateChildrenImpl(SymTagEnum symbolTagType, string { if (enumSymbols != null) { +#if WINDOWS Marshal.ReleaseComObject(enumSymbols); +#endif } } } diff --git a/src/Test.UnitTests.BinaryParsers/PEBinary/PEBinaryTests.cs b/src/Test.UnitTests.BinaryParsers/PEBinary/PEBinaryTests.cs index 5b4757ae9..a3b5f8327 100644 --- a/src/Test.UnitTests.BinaryParsers/PEBinary/PEBinaryTests.cs +++ b/src/Test.UnitTests.BinaryParsers/PEBinary/PEBinaryTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.Versioning; using Dia2Lib; @@ -212,6 +213,7 @@ public void PEBinary_IsDotNetNativeBootstrapExe() } [Fact] + [SupportedOSPlatform("windows")] public void PEBinary_CanCreateIDiaSourceFromMsdia() { if (!PlatformSpecificHelpers.RunningOnWindows()) { return; }