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