diff options
author | Jb Evain <jb@evain.net> | 2021-06-24 04:55:44 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-24 04:55:44 +0300 |
commit | 0dd5556af12ab8fd053f9072a1f8e80d7a9608a7 (patch) | |
tree | 216bb4af5e9791393dc393c96d189f3aefd90a49 /symbols | |
parent | a72c1b1e11762d940f95ffb662dbdf7f0de92a28 (diff) |
Fix NRE when writing native pdb with type name exceeding PDB_MAX_PATH (#769)
* Add test with long type name
* Fix definition and usage of IMetadataImport methods to handle long names
Diffstat (limited to 'symbols')
-rw-r--r-- | symbols/pdb/Mono.Cecil.Pdb.csproj | 1 | ||||
-rw-r--r-- | symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs | 109 | ||||
-rw-r--r-- | symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs | 11 | ||||
-rw-r--r-- | symbols/pdb/Test/Resources/assemblies/longtypename.dll | bin | 0 -> 4096 bytes | |||
-rw-r--r-- | symbols/pdb/Test/Resources/assemblies/longtypename.pdb | bin | 0 -> 11776 bytes |
5 files changed, 72 insertions, 49 deletions
diff --git a/symbols/pdb/Mono.Cecil.Pdb.csproj b/symbols/pdb/Mono.Cecil.Pdb.csproj index 265159d..8e7d08c 100644 --- a/symbols/pdb/Mono.Cecil.Pdb.csproj +++ b/symbols/pdb/Mono.Cecil.Pdb.csproj @@ -2,6 +2,7 @@ <PropertyGroup> <TargetFrameworks>netstandard2.0;net40</TargetFrameworks> <NoWarn>0649</NoWarn> + <AllowUnsafeBlocks>True</AllowUnsafeBlocks> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\..\Mono.Cecil.csproj"> diff --git a/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs b/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs index 297df0c..0bc32dc 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs @@ -5,8 +5,10 @@ using System.Text; namespace Mono.Cecil.Pdb { + // WARNING: most methods should be reworked into PreserveSig methods + [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("BA3FEE4C-ECB9-4e41-83B7-183FA41CD859")] - interface IMetaDataEmit { + unsafe interface IMetaDataEmit { void SetModuleProps (string szName); void Save (string szFile, uint dwSaveFlags); void SaveToStream (IntPtr pIStream, uint dwSaveFlags); @@ -63,7 +65,7 @@ namespace Mono.Cecil.Pdb { } [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("7DAC8207-D3AE-4c75-9B67-92801A497D44")] - interface IMetaDataImport { + unsafe interface IMetaDataImport { [PreserveSig] void CloseEnum (uint hEnum); uint CountEnum (uint hEnum); @@ -74,7 +76,9 @@ namespace Mono.Cecil.Pdb { uint FindTypeDefByName (string szTypeDef, uint tkEnclosingClass); Guid GetScopeProps (StringBuilder szName, uint cchName, out uint pchName); uint GetModuleFromScope (); - uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags); + + [PreserveSig] + uint GetTypeDefProps (uint td, char* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends); uint GetInterfaceImplProps (uint iiImpl, out uint pClass); uint GetTypeRefProps (uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName); uint ResolveTypeRef (uint tr, [In] ref Guid riid, [MarshalAs (UnmanagedType.Interface)] out object ppIScope); @@ -94,7 +98,9 @@ namespace Mono.Cecil.Pdb { uint FindMethod (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); uint FindField (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); uint FindMemberRef (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); - uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA); + + [PreserveSig] + uint GetMethodProps (uint mb, uint* pClass, char* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags); uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr /* byte* */ ppvSigBlob); uint EnumProperties (ref uint phEnum, uint td, IntPtr /* uint* */ rProperties, uint cMax); uint EnumEvents (ref uint phEnum, uint td, IntPtr /* uint* */ rEvents, uint cMax); @@ -136,18 +142,22 @@ namespace Mono.Cecil.Pdb { [PreserveSig] [return: MarshalAs (UnmanagedType.Bool)] bool IsValidToken (uint tk); - uint GetNestedClassProps (uint tdNestedClass); + [PreserveSig] + uint GetNestedClassProps (uint tdNestedClass, uint* ptdEnclosingClass); uint GetNativeCallConvFromSig (IntPtr /* void* */ pvSig, uint cbSig); int IsGlobal (uint pd); } - class ModuleMetadata : IMetaDataEmit, IMetaDataImport { + unsafe class ModuleMetadata : IMetaDataEmit, IMetaDataImport { readonly ModuleDefinition module; Dictionary<uint, TypeDefinition> types; Dictionary<uint, MethodDefinition> methods; + const uint S_OK = 0x00000000; + const uint E_FAIL = 0x80004005; + public ModuleMetadata (ModuleDefinition module) { this.module = module; @@ -476,40 +486,22 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags) + public uint GetTypeDefProps (uint td, char* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends) { TypeDefinition type; - if (!TryGetType (td, out type)) { - Marshal.WriteInt16 (szTypeDef, 0); - pchTypeDef = 1; - return 0; - } - - WriteString (type.IsNested ? type.Name : type.FullName, szTypeDef, cchTypeDef, out pchTypeDef); - WriteIntPtr (pdwTypeDefFlags, (uint) type.Attributes); - return type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; - } - - static void WriteIntPtr (IntPtr ptr, uint value) - { - if (ptr == IntPtr.Zero) - return; + if (!TryGetType (td, out type)) + return E_FAIL; - Marshal.WriteInt32 (ptr, (int) value); - } + var name = type.IsNested ? type.Name : type.FullName; - static void WriteString (string str, IntPtr buffer, uint bufferSize, out uint chars) - { - var length = str.Length + 1 >= bufferSize ? bufferSize - 1 : (uint) str.Length; - chars = length + 1; - var offset = 0; + WriteNameBuffer (name, szTypeDef, cchTypeDef, pchTypeDef); - for (int i = 0; i < length; i++) { - Marshal.WriteInt16 (buffer, offset, str [i]); - offset += 2; - } + if (pdwTypeDefFlags != null) + *pdwTypeDefFlags = (uint) type.Attributes; + if (ptkExtends != null) + *ptkExtends = type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; - Marshal.WriteInt16 (buffer, offset, 0); + return S_OK; } public uint GetInterfaceImplProps (uint iiImpl, out uint pClass) @@ -597,22 +589,38 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA) + public uint GetMethodProps (uint mb, uint* pClass, char* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags) { MethodDefinition method; - if (!TryGetMethod (mb, out method)) { - Marshal.WriteInt16 (szMethod, 0); - pchMethod = 1; - pClass = 0; - return 0; - } + if (!TryGetMethod (mb, out method)) + return E_FAIL; + + if (pClass != null) + *pClass = method.DeclaringType.MetadataToken.ToUInt32 (); + + WriteNameBuffer (method.Name, szMethod, cchMethod, pchMethod); - pClass = method.DeclaringType.MetadataToken.ToUInt32 (); - WriteString (method.Name, szMethod, cchMethod, out pchMethod); - WriteIntPtr (pdwAttr, (uint) method.Attributes); - WriteIntPtr (pulCodeRVA, (uint) method.RVA); + if (pdwAttr != null) + *pdwAttr = (uint) method.Attributes; + if (pulCodeRVA != null) + *pulCodeRVA = (uint) method.RVA; + if (pdwImplFlags != null) + *pdwImplFlags = (uint) method.ImplAttributes; - return (uint) method.ImplAttributes; + return S_OK; + } + + static void WriteNameBuffer(string name, char* buffer, uint bufferLength, uint* actualLength) + { + var length = Math.Min (name.Length, bufferLength - 1); + if (actualLength != null) + *actualLength = (uint) length; + + if (buffer != null && bufferLength > 0) { + for (int i = 0; i < length; i++) + buffer [i] = name [i]; + buffer [length + 1] = '\0'; + } } public uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob) @@ -770,13 +778,16 @@ namespace Mono.Cecil.Pdb { throw new NotImplementedException (); } - public uint GetNestedClassProps (uint tdNestedClass) + public uint GetNestedClassProps (uint tdNestedClass, uint* ptdEnclosingClass) { TypeDefinition type; if (!TryGetType (tdNestedClass, out type)) - return 0; + return E_FAIL; + + if (ptdEnclosingClass != null) + *ptdEnclosingClass = type.IsNested ? type.DeclaringType.MetadataToken.ToUInt32 () : 0; - return type.IsNested ? type.DeclaringType.MetadataToken.ToUInt32 () : 0; + return S_OK; } public uint GetNativeCallConvFromSig (IntPtr pvSig, uint cbSig) diff --git a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs index 797f680..6f2d2fa 100644 --- a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs +++ b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs @@ -465,5 +465,16 @@ namespace Mono.Cecil.Tests { Assert.AreEqual ("temp", method.DebugInformation.Scope.Variables [0].Name); } + + [Test] + public void TypeNameExceedingMaxPdbPath () + { + if (!Platform.HasNativePdbSupport) + Assert.Ignore (); + + TestModule ("longtypename.dll", module => { + Assert.IsTrue (module.HasSymbols); + }, symbolReaderProvider: typeof (NativePdbReaderProvider), symbolWriterProvider: typeof (NativePdbWriterProvider)); + } } } diff --git a/symbols/pdb/Test/Resources/assemblies/longtypename.dll b/symbols/pdb/Test/Resources/assemblies/longtypename.dll Binary files differnew file mode 100644 index 0000000..803757f --- /dev/null +++ b/symbols/pdb/Test/Resources/assemblies/longtypename.dll diff --git a/symbols/pdb/Test/Resources/assemblies/longtypename.pdb b/symbols/pdb/Test/Resources/assemblies/longtypename.pdb Binary files differnew file mode 100644 index 0000000..0c5ca89 --- /dev/null +++ b/symbols/pdb/Test/Resources/assemblies/longtypename.pdb |