From 490b67a7257d6fcf72b5d67f4dde0c67acd6a3f5 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 30 Sep 2024 16:17:09 +0200 Subject: [PATCH 1/4] Report error for native PDB limit --- .../CSharp/Test/Emit2/PDB/PDBTests.cs | 78 +++++++++++++++++++ .../Core/Portable/CodeAnalysisResources.resx | 3 + .../Portable/NativePdbWriter/PdbWriter.cs | 10 +++ .../Portable/xlf/CodeAnalysisResources.cs.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.de.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.es.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.fr.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.it.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.ja.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.ko.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.pl.xlf | 5 ++ .../xlf/CodeAnalysisResources.pt-BR.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.ru.xlf | 5 ++ .../Portable/xlf/CodeAnalysisResources.tr.xlf | 5 ++ .../xlf/CodeAnalysisResources.zh-Hans.xlf | 5 ++ .../xlf/CodeAnalysisResources.zh-Hant.xlf | 5 ++ .../VisualBasic/Test/Emit/PDB/PDBTests.vb | 25 ++++++ .../CustomMetadataSymUnmanagedWriter.cs | 17 ++++ .../Writer/DelegatingSymUnmanagedWriter.cs | 5 ++ .../Writer/SymWriterTestUtilities.cs | 5 ++ 20 files changed, 208 insertions(+) create mode 100644 src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs diff --git a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs index 78ef00e6a8aaa..2ff12f8b6fbbe 100644 --- a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs @@ -22,6 +22,7 @@ using Roslyn.Test.PdbUtilities; using Roslyn.Test.Utilities; using Roslyn.Test.Utilities.TestGenerators; +using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.PDB @@ -367,6 +368,83 @@ public void SymWriterErrors4() Assert.False(result.Success); } + [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] + [InlineData(0x9_999)] + [InlineData(0x9_000)] + public void NativeWriterLimit_Under(int length) + { + CompileWithMockedCustomMetadata(length).Diagnostics.Verify(); + } + + [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] + [InlineData(0x10_000)] + [InlineData(0x20_000)] + public void NativeWriterLimit_Over(int length) + { + CompileWithMockedCustomMetadata(length).Diagnostics.Verify( + // error CS0041: Unexpected error writing debug information -- 'Insufficient memory to continue the execution of the program.' + Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(new OutOfMemoryException().Message).WithLocation(1, 1)); + } + + private static EmitResult CompileWithMockedCustomMetadata(int length) + { + var comp = CreateCompilation(""" + class C + { + void M() { } + } + """); + return comp.Emit( + peStream: new MemoryStream(), + metadataPEStream: null, + pdbStream: new MemoryStream(), + xmlDocumentationStream: null, + cancellationToken: default, + win32Resources: null, + manifestResources: null, + options: null, + debugEntryPoint: null, + sourceLinkStream: null, + embeddedTexts: null, + rebuildData: null, + testData: new CompilationTestData + { + SymWriterFactory = metadataProvider => + { + var writer = SymWriterTestUtilities.CreateUnmanagedWriter(metadataProvider); + return new CustomMetadataSymUnmanagedWriter(writer, new byte[length]); + }, + }); + } + + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] + public void NativeWriterLimit_EndToEnd() + { + var locals = Enumerable.Range(0, 14_000) + .Select(i => $""" + var local{i} = {i}; + M2(local{i}); + """) + .Join(Environment.NewLine); + var source = $$""" + namespace N; + class C + { + void M1() + { + {{locals}} + } + void M2(int x) { } + } + """; + CreateCompilation(source, options: TestOptions.DebugDll).VerifyEmitDiagnostics( + // error CS0041: Unexpected error writing debug information -- 'Cannot emit native PDB for method 'N.C.M1()' because its debug metadata size 69096 is over the limit 65536.' + Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "N.C.M1()", 69096, 65536)).WithLocation(1, 1)); + } + [WorkItem(1067635, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067635")] [Fact] public void SuppressDynamicAndEncCDIForWinRT() diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.resx b/src/Compilers/Core/Portable/CodeAnalysisResources.resx index fc24b236c5a27..c013f246a5a59 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.resx +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.resx @@ -507,6 +507,9 @@ Windows PDB writer doesn't support SourceLink feature: '{0}' + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + The attribute {0} has an invalid value of {1}. diff --git a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs index 5b7acff12829c..3f13fd4ff794b 100644 --- a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs +++ b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs @@ -148,6 +148,16 @@ public void SerializeDebugInfo(IMethodBody methodBody, StandaloneSignatureHandle if (blob.Length > 0) { + const int limit = 0x10_000; + if (blob.Length > limit) + { + throw new SymUnmanagedWriterException(string.Format( + CodeAnalysisResources.SymWriterMetadataOverLimit, + methodBody.MethodDefinition, + blob.Length, + limit)); + } + _symWriter.DefineCustomMetadata(blob); } diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf index e27948360035c..2df3ee048a081 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor musí mít ID, které není null, prázdný řetězec ani řetězec obsahující jenom prázdné znaky. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Pokud jsou zadané anotace prvků řazené kolekce členů s možnou hodnotou null, musí se počet anotací shodovat s kardinalitou této řazené kolekce členů. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf index 2f1024bd36d3f..94bb96efb0917 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf @@ -268,6 +268,11 @@ Ein SuppressionDescriptor muss eine ID aufweisen, die weder NULL noch eine leere Zeichenfolge noch eine Zeichenfolge ist, die nur Leerzeichen enthält. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Wenn Nullable-Anmerkungen für Tupelelemente angegeben werden, muss die Anzahl von Anmerkungen der Kardinalität des Tupels entsprechen. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf index 184b373347e55..3c49dabe1c642 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf @@ -268,6 +268,11 @@ Un elemento SuppressionDescriptor debe tener un id. que no sea NULL, una cadena vacía ni una cadena que solo contenga un espacio en blanco. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Si se especifican las anotaciones que aceptan valores NULL de los elementos de tupla, el número de anotaciones debe coincidir con la cardinalidad de la tupla. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf index bc48129b024c3..8364a6e0d57d7 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor doit avoir un ID qui n'est ni une valeur null, ni une chaîne vide, ni une chaîne contenant uniquement des espaces blancs. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Si des annotations de type Nullable pour des éléments de tuples sont spécifiées, le nombre d'annotations doit correspondre à la cardinalité du tuple. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf index c55bd8e1bd77b..4e1ea7458a093 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf @@ -268,6 +268,11 @@ L'ID di un elemento SuppressionDescriptor non deve essere Null, né una stringa vuota o una stringa composta solo da spazi vuoti. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Se si specificano annotazioni nullable di elementi di tupla, il numero delle annotazioni deve corrispondere alla cardinalità della tupla. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf index 348b8333d5d9d..bbe59f873bdcb 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor では、null でも、空の文字列でも、空白のみの文字列でもない ID が必要です。 + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. タプル要素の Null 許容の注釈を指定する場合、注釈の数はタプルの基数と一致する必要があります。 diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf index 6bcf6900e8733..db8f19aed58d0 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor에 null, 빈 문자열 및 공백만 포함된 문자열이 아닌 ID가 있어야 합니다. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. 튜플 요소 nullable 주석이 지정된 경우, 주석 수는 튜플의 카디널리티와 일치해야 합니다. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf index 17cbdb97b7166..cc98075bccb34 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf @@ -268,6 +268,11 @@ Interfejs DiagnosticDescriptor musi mieć identyfikator, który nie ma wartości null, nie jest ciągiem pustym ani nie jest ciągiem zawierającym tylko białe znaki. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Jeśli określono adnotacje elementów krotki z możliwością ustawiania wartości null, liczba adnotacji musi zgadzać się z kardynalnością krotki. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf index 9952ed99f3eb2..52a2d40046885 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf @@ -268,6 +268,11 @@ A ID do SuppressionDescriptor não pode ser nula, não deve ser uma cadeia de caracteres vazia nem deve ser uma cadeia de caracteres que contenha apenas espaços em branco. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Se as anotações anuláveis de elementos de tupla forem especificadas, o número de anotações deverá corresponder à cardinalidade da tupla. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf index 75e0c337d706f..7137861c3cee9 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor должен иметь идентификатор, который не является значением NULL, пустой строкой или строкой, состоящей из одного пробела. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Если указаны аннотации элементов кортежа, допускающих значения null, то число аннотаций должно соответствовать кратности кортежа. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf index 6b008f54f5c42..c18509b928aee 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor türünün kimliği, null veya boş bir dize ya da yalnızca boşluk içeren bir dize olmamalıdır. + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. Demet öğelerine yönelik boş değer atanabilir ek açıklamalar belirtildiyse, ek açıklamaların sayısı demetin kardinalitesiyle eşleşmelidir. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf index f5e63e3d44c6d..195a98abb1b34 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf @@ -268,6 +268,11 @@ A SuppressionDescriptor 必须具有一个 ID,且该 ID 不为 null、不是空字符串且不是仅包含空格的字符串。 + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. 如果已指定元组元素可以为 null 的注释,则注释的数量必须与元组基数相匹配。 diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf index 57ee62adf5847..d0daf896b2cdd 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf @@ -268,6 +268,11 @@ SuppressionDescriptor 的識別碼不得為 null、空白字串或只包含空白字元的字串。 + + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + Cannot emit native PDB for method '{0}' because its debug metadata size {1} is over the limit {2}. + + If tuple element nullable annotations are specified, the number of annotations must match the cardinality of the tuple. 如果指定元組元素可為 Null 的註釋,註釋數目就必須符合元組的基數。 diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb index 057a7f2316d38..0057d5ef01e7f 100644 --- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb @@ -208,6 +208,31 @@ End Class result.Diagnostics.Verify(Diagnostic(ERRID.ERR_DebugEntryPointNotSourceMethodDefinition)) End Sub + + + Public Sub NativeWriterLimit() + Dim locals = Enumerable.Range(0, 14_000). + Select(Function(i) $" +Dim local{i} As Integer = {i} +M2(local{i}) +"). + Join(Environment.NewLine) + Dim source = $" +Namespace N +Class C + Shared Sub M1() + {locals} + End Sub + Shared Sub M2(x As Integer) + End Sub +End Class +End Namespace +" + ' Cannot emit native PDB for method 'Public Shared Sub M1()' because its debug metadata size 69328 is over the limit 65536. + CreateCompilation(source, options:=TestOptions.DebugDll).VerifyEmitDiagnostics( + Diagnostic(ERRID.ERR_PDBWritingFailed).WithArguments(String.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "Public Shared Sub M1()", 69328, 65536)).WithLocation(1, 1)) + End Sub + #End Region diff --git a/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs b/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs new file mode 100644 index 0000000000000..f2bf8b3032dda --- /dev/null +++ b/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.DiaSymReader; + +namespace Roslyn.Test.PdbUtilities; + +internal sealed class CustomMetadataSymUnmanagedWriter(SymUnmanagedWriter target, byte[] customMetadata) : DelegatingSymUnmanagedWriter(target) +{ + private readonly byte[] _customMetadata = customMetadata; + + public override void DefineCustomMetadata(byte[] metadata) + { + base.DefineCustomMetadata(_customMetadata); + } +} diff --git a/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs b/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs index da765c30c53cd..32ee70b2dc908 100644 --- a/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs +++ b/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs @@ -26,6 +26,11 @@ public override int DocumentTableCapacity set => _target.DocumentTableCapacity = value; } + public override void AddCompilerInfo(ushort major, ushort minor, ushort build, ushort revision, string name) + { + _target.AddCompilerInfo(major, minor, build, revision, name); + } + public override void Dispose() => _target.Dispose(); public override void CloseMethod() => _target.CloseMethod(); public override void CloseScope(int endOffset) => _target.CloseScope(endOffset); diff --git a/src/Test/PdbUtilities/Writer/SymWriterTestUtilities.cs b/src/Test/PdbUtilities/Writer/SymWriterTestUtilities.cs index 3d154fe733097..e35ac26c31719 100644 --- a/src/Test/PdbUtilities/Writer/SymWriterTestUtilities.cs +++ b/src/Test/PdbUtilities/Writer/SymWriterTestUtilities.cs @@ -13,5 +13,10 @@ internal static class SymWriterTestUtilities { public static readonly Func ThrowingFactory = _ => throw new SymUnmanagedWriterException("xxx", new NotSupportedException(), ""); + + public static SymUnmanagedWriter CreateUnmanagedWriter(ISymWriterMetadataProvider metadataProvider) + { + return SymUnmanagedWriterFactory.CreateWriter(metadataProvider); + } } } From 0d8e32150d2b835ee58944b076208df63a687307 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Tue, 1 Oct 2024 11:20:41 +0200 Subject: [PATCH 2/4] Fix the limit --- src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs | 15 +++++++-------- .../Core/Portable/NativePdbWriter/PdbWriter.cs | 6 +++--- .../VisualBasic/Test/Emit/PDB/PDBTests.vb | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs index 2ff12f8b6fbbe..988a167e01edf 100644 --- a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs @@ -13,6 +13,7 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Text; +using Microsoft.Cci; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; @@ -370,18 +371,16 @@ public void SymWriterErrors4() [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] - [InlineData(0x9_999)] - [InlineData(0x9_000)] - public void NativeWriterLimit_Under(int length) + [CombinatorialData] + public void NativeWriterLimit_Under([CombinatorialRange(PdbWriter.CustomMetadataByteLimit - 9, 10)] int length) { CompileWithMockedCustomMetadata(length).Diagnostics.Verify(); } [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] - [InlineData(0x10_000)] - [InlineData(0x20_000)] - public void NativeWriterLimit_Over(int length) + [CombinatorialData] + public void NativeWriterLimit_Over([CombinatorialRange(PdbWriter.CustomMetadataByteLimit + 1, 10)] int length) { CompileWithMockedCustomMetadata(length).Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'Insufficient memory to continue the execution of the program.' @@ -441,8 +440,8 @@ void M2(int x) { } } """; CreateCompilation(source, options: TestOptions.DebugDll).VerifyEmitDiagnostics( - // error CS0041: Unexpected error writing debug information -- 'Cannot emit native PDB for method 'N.C.M1()' because its debug metadata size 69096 is over the limit 65536.' - Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "N.C.M1()", 69096, 65536)).WithLocation(1, 1)); + // error CS0041: Unexpected error writing debug information -- 'Cannot emit native PDB for method 'N.C.M1()' because its debug metadata size 69096 is over the limit 65504.' + Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "N.C.M1()", 69096, 65504)).WithLocation(1, 1)); } [WorkItem(1067635, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067635")] diff --git a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs index 3f13fd4ff794b..ee11f14135491 100644 --- a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs +++ b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs @@ -26,6 +26,7 @@ namespace Microsoft.Cci internal sealed class PdbWriter : IDisposable { internal const uint Age = 1; + internal const int CustomMetadataByteLimit = 65_504; private readonly HashAlgorithmName _hashAlgorithmNameOpt; private readonly string _fileName; @@ -148,14 +149,13 @@ public void SerializeDebugInfo(IMethodBody methodBody, StandaloneSignatureHandle if (blob.Length > 0) { - const int limit = 0x10_000; - if (blob.Length > limit) + if (blob.Length > CustomMetadataByteLimit) { throw new SymUnmanagedWriterException(string.Format( CodeAnalysisResources.SymWriterMetadataOverLimit, methodBody.MethodDefinition, blob.Length, - limit)); + CustomMetadataByteLimit)); } _symWriter.DefineCustomMetadata(blob); diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb index 0057d5ef01e7f..fca4413f84999 100644 --- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb @@ -228,9 +228,9 @@ Class C End Class End Namespace " - ' Cannot emit native PDB for method 'Public Shared Sub M1()' because its debug metadata size 69328 is over the limit 65536. + ' Cannot emit native PDB for method 'Public Shared Sub M1()' because its debug metadata size 69328 is over the limit 65504. CreateCompilation(source, options:=TestOptions.DebugDll).VerifyEmitDiagnostics( - Diagnostic(ERRID.ERR_PDBWritingFailed).WithArguments(String.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "Public Shared Sub M1()", 69328, 65536)).WithLocation(1, 1)) + Diagnostic(ERRID.ERR_PDBWritingFailed).WithArguments(String.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "Public Shared Sub M1()", 69328, 65504)).WithLocation(1, 1)) End Sub #End Region From dc46ad50a6570e521aacc8f4e7397c0de656f05b Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 2 Oct 2024 10:35:02 +0200 Subject: [PATCH 3/4] Add comments --- src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs | 6 ++++++ src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs index 988a167e01edf..abb3cc2fff41b 100644 --- a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs @@ -369,6 +369,9 @@ public void SymWriterErrors4() Assert.False(result.Success); } + /// + /// Verifies the constant against the external sym writer library we depend on. + /// [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] [CombinatorialData] @@ -377,6 +380,9 @@ public void NativeWriterLimit_Under([CombinatorialRange(PdbWriter.CustomMetadata CompileWithMockedCustomMetadata(length).Diagnostics.Verify(); } + /// + /// Verifies the constant against the external sym writer library we depend on. + /// [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] [CombinatorialData] diff --git a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs index ee11f14135491..c716ba4aba03e 100644 --- a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs +++ b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs @@ -26,6 +26,8 @@ namespace Microsoft.Cci internal sealed class PdbWriter : IDisposable { internal const uint Age = 1; + + // This constant is verified in PDBTests.NativeWriterLimit_Under and NativeWriterLimit_Over. internal const int CustomMetadataByteLimit = 65_504; private readonly HashAlgorithmName _hashAlgorithmNameOpt; From 5c1985e710ab149bec33d7f2514c66d18130c4fc Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 2 Oct 2024 18:51:59 +0200 Subject: [PATCH 4/4] Move check into SymUnmanagedWriterImpl --- src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs | 15 +++++++-------- .../DiaSymReader/Writer/SymUnmanagedWriter.cs | 3 ++- .../Writer/SymUnmanagedWriterImpl.cs | 16 +++++++++++++++- .../Core/Portable/NativePdbWriter/PdbWriter.cs | 14 +------------- .../Writer/CustomMetadataSymUnmanagedWriter.cs | 5 +++-- .../Writer/DelegatingSymUnmanagedWriter.cs | 3 ++- .../Writer/MockSymUnmanagedWriter.cs | 3 ++- 7 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs index abb3cc2fff41b..08b320c17d4be 100644 --- a/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/PDB/PDBTests.cs @@ -5,7 +5,6 @@ #nullable disable using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; @@ -13,13 +12,13 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Text; -using Microsoft.Cci; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; +using Microsoft.DiaSymReader; using Roslyn.Test.PdbUtilities; using Roslyn.Test.Utilities; using Roslyn.Test.Utilities.TestGenerators; @@ -370,27 +369,27 @@ public void SymWriterErrors4() } /// - /// Verifies the constant against the external sym writer library we depend on. + /// Verifies the constant SymUnmanagedWriterImpl.CustomMetadataByteLimit against the external sym writer library we depend on. /// [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] [CombinatorialData] - public void NativeWriterLimit_Under([CombinatorialRange(PdbWriter.CustomMetadataByteLimit - 9, 10)] int length) + public void NativeWriterLimit_Under([CombinatorialRange(SymUnmanagedWriterImpl.CustomMetadataByteLimit - 9, 10)] int length) { CompileWithMockedCustomMetadata(length).Diagnostics.Verify(); } /// - /// Verifies the constant against the external sym writer library we depend on. + /// Verifies the constant SymUnmanagedWriterImpl.CustomMetadataByteLimit against the external sym writer library we depend on. /// [ConditionalTheory(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem("https://github.com/dotnet/roslyn/issues/75237")] [CombinatorialData] - public void NativeWriterLimit_Over([CombinatorialRange(PdbWriter.CustomMetadataByteLimit + 1, 10)] int length) + public void NativeWriterLimit_Over([CombinatorialRange(SymUnmanagedWriterImpl.CustomMetadataByteLimit + 1, 10)] int length) { CompileWithMockedCustomMetadata(length).Diagnostics.Verify( - // error CS0041: Unexpected error writing debug information -- 'Insufficient memory to continue the execution of the program.' - Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(new OutOfMemoryException().Message).WithLocation(1, 1)); + // error CS0041: Unexpected error writing debug information -- 'Cannot emit native PDB for method 'C.M()' because its debug metadata size 65505 is over the limit 65504.' + Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterMetadataOverLimit, "C.M()", length, 65504)).WithLocation(1, 1)); } private static EmitResult CompileWithMockedCustomMetadata(int length) diff --git a/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriter.cs b/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriter.cs index 0dd0206e6d541..45a03c88f3611 100644 --- a/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriter.cs +++ b/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriter.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.IO; +using Microsoft.Cci; namespace Microsoft.DiaSymReader { @@ -141,7 +142,7 @@ public abstract void SetAsyncInfo( /// Writes are not allowed to the underlying stream. /// Error occurred while writing PDB data. /// is null - public abstract void DefineCustomMetadata(byte[] metadata); + public abstract void DefineCustomMetadata(byte[] metadata, IMethodDefinition methodDefinition); /// /// Designates specified method as an entry point. diff --git a/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriterImpl.cs b/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriterImpl.cs index 19c65e61879c7..5bc729249d958 100644 --- a/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriterImpl.cs +++ b/src/Compilers/Core/Portable/DiaSymReader/Writer/SymUnmanagedWriterImpl.cs @@ -4,6 +4,8 @@ #nullable disable +using Microsoft.Cci; +using Microsoft.CodeAnalysis; using System; using System.Collections.Generic; using System.Diagnostics; @@ -16,6 +18,9 @@ namespace Microsoft.DiaSymReader { internal sealed class SymUnmanagedWriterImpl : SymUnmanagedWriter { + // This constant is verified in PDBTests.NativeWriterLimit_Under and NativeWriterLimit_Over. + internal const int CustomMetadataByteLimit = 65_504; + private static readonly object s_zeroInt32 = 0; private ISymUnmanagedWriter5 _symWriter; @@ -532,7 +537,7 @@ public override void SetAsyncInfo( } } - public override unsafe void DefineCustomMetadata(byte[] metadata) + public override unsafe void DefineCustomMetadata(byte[] metadata, IMethodDefinition methodDefinition) { if (metadata == null) { @@ -544,6 +549,15 @@ public override unsafe void DefineCustomMetadata(byte[] metadata) return; } + if (metadata.Length > CustomMetadataByteLimit) + { + throw new SymUnmanagedWriterException(string.Format( + CodeAnalysisResources.SymWriterMetadataOverLimit, + methodDefinition, + metadata.Length, + CustomMetadataByteLimit)); + } + var symWriter = GetSymWriter(); try diff --git a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs index c716ba4aba03e..84073d32f22b1 100644 --- a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs +++ b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs @@ -27,9 +27,6 @@ internal sealed class PdbWriter : IDisposable { internal const uint Age = 1; - // This constant is verified in PDBTests.NativeWriterLimit_Under and NativeWriterLimit_Over. - internal const int CustomMetadataByteLimit = 65_504; - private readonly HashAlgorithmName _hashAlgorithmNameOpt; private readonly string _fileName; private readonly Func _symWriterFactory; @@ -151,16 +148,7 @@ public void SerializeDebugInfo(IMethodBody methodBody, StandaloneSignatureHandle if (blob.Length > 0) { - if (blob.Length > CustomMetadataByteLimit) - { - throw new SymUnmanagedWriterException(string.Format( - CodeAnalysisResources.SymWriterMetadataOverLimit, - methodBody.MethodDefinition, - blob.Length, - CustomMetadataByteLimit)); - } - - _symWriter.DefineCustomMetadata(blob); + _symWriter.DefineCustomMetadata(blob, methodBody.MethodDefinition); } CloseMethod(methodBody.IL.Length); diff --git a/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs b/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs index f2bf8b3032dda..5a2510ac24ed7 100644 --- a/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs +++ b/src/Test/PdbUtilities/Writer/CustomMetadataSymUnmanagedWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.Cci; using Microsoft.DiaSymReader; namespace Roslyn.Test.PdbUtilities; @@ -10,8 +11,8 @@ internal sealed class CustomMetadataSymUnmanagedWriter(SymUnmanagedWriter target { private readonly byte[] _customMetadata = customMetadata; - public override void DefineCustomMetadata(byte[] metadata) + public override void DefineCustomMetadata(byte[] metadata, IMethodDefinition methodDefinition) { - base.DefineCustomMetadata(_customMetadata); + base.DefineCustomMetadata(_customMetadata, methodDefinition); } } diff --git a/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs b/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs index 32ee70b2dc908..4e23168ec5af1 100644 --- a/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs +++ b/src/Test/PdbUtilities/Writer/DelegatingSymUnmanagedWriter.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.IO; +using Microsoft.Cci; using Microsoft.DiaSymReader; namespace Roslyn.Test.PdbUtilities @@ -35,7 +36,7 @@ public override void AddCompilerInfo(ushort major, ushort minor, ushort build, u public override void CloseMethod() => _target.CloseMethod(); public override void CloseScope(int endOffset) => _target.CloseScope(endOffset); public override void CloseTokensToSourceSpansMap() => _target.CloseTokensToSourceSpansMap(); - public override void DefineCustomMetadata(byte[] metadata) => _target.DefineCustomMetadata(metadata); + public override void DefineCustomMetadata(byte[] metadata, IMethodDefinition methodDefinition) => _target.DefineCustomMetadata(metadata, methodDefinition); public override int DefineDocument(string name, Guid language, Guid vendor, Guid type, Guid algorithmId, ReadOnlySpan checksum, ReadOnlySpan source) => _target.DefineDocument(name, language, vendor, type, algorithmId, checksum, source); diff --git a/src/Test/PdbUtilities/Writer/MockSymUnmanagedWriter.cs b/src/Test/PdbUtilities/Writer/MockSymUnmanagedWriter.cs index ea9eaa9577fb6..33ee5de6744c2 100644 --- a/src/Test/PdbUtilities/Writer/MockSymUnmanagedWriter.cs +++ b/src/Test/PdbUtilities/Writer/MockSymUnmanagedWriter.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.IO; +using Microsoft.Cci; using Microsoft.DiaSymReader; namespace Roslyn.Test.Utilities @@ -37,7 +38,7 @@ public override void CloseTokensToSourceSpansMap() throw MakeException(); } - public override void DefineCustomMetadata(byte[] metadata) + public override void DefineCustomMetadata(byte[] metadata, IMethodDefinition methodDefinition) { throw MakeException(); }