提交 6f339727 编写于 作者: A AlekseyTs

Strengthen emit against overflow of user string heap.

Fixes #8287.
上级 c61220bb
......@@ -8125,6 +8125,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals..
/// </summary>
internal static string ERR_TooManyUserStrings {
get {
return ResourceManager.GetString("ERR_TooManyUserStrings", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A format specifier may not contain trailing whitespace..
/// </summary>
......
......@@ -4672,4 +4672,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="SyntaxTreeIsNotASubmission" xml:space="preserve">
<value>Syntax tree should be created from a submission.</value>
</data>
<data name="ERR_TooManyUserStrings" xml:space="preserve">
<value>Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.</value>
</data>
</root>
\ No newline at end of file
......@@ -1319,5 +1319,6 @@ internal enum ErrorCode
ERR_BadAwaitInStaticVariableInitializer = 8100,
ERR_InvalidPathMap = 8101,
ERR_PublicSignButNoKey = 8102,
ERR_TooManyUserStrings = 8103,
}
}
......@@ -201,6 +201,7 @@ public override void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnost
// PE Writer:
public override int ERR_MetadataNameTooLong { get { return (int)ErrorCode.ERR_MetadataNameTooLong; } }
public override int ERR_EncReferenceToAddedMember { get { return (int)ErrorCode.ERR_EncReferenceToAddedMember; } }
public override int ERR_TooManyUserStrings { get { return (int)ErrorCode.ERR_TooManyUserStrings; } }
public override void ReportInvalidAttributeArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, AttributeData attribute)
{
......
......@@ -300,6 +300,37 @@ public static int Main ()
Diagnostic(ErrorCode.ERR_TooManyLocals, "Main"));
}
[Fact, WorkItem(8287, "https://github.com/dotnet/roslyn/issues/8287")]
public void ToManyUserStrings()
{
var builder = new System.Text.StringBuilder();
builder.Append(@"
public class A
{
public static void Main ()
{
");
for (int i = 0; i < 11; i++)
{
builder.Append("System.Console.WriteLine(\"");
builder.Append((char)('A' + i), 1000000);
builder.Append("\");");
builder.AppendLine();
}
builder.Append(@"
}
}
");
var compilation = CreateCompilationWithMscorlib(builder.ToString());
compilation.VerifyEmitDiagnostics(
// error CS8103: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.
Diagnostic(ErrorCode.ERR_TooManyUserStrings).WithLocation(1, 1)
);
}
#endregion
}
}
......@@ -202,6 +202,7 @@ public DiagnosticInfo FilterDiagnosticInfo(DiagnosticInfo diagnosticInfo, Compil
// PE writing:
public abstract int ERR_MetadataNameTooLong { get; }
public abstract int ERR_EncReferenceToAddedMember { get; }
public abstract int ERR_TooManyUserStrings { get; }
public abstract void ReportInvalidAttributeArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, AttributeData attribute);
public abstract void ReportInvalidNamedArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int namedArgumentIndex, ITypeSymbol attributeClass, string parameterName);
......
......@@ -261,7 +261,7 @@ public int ResolveBlobIndex(BlobIdx index)
return (index.HeapPosition == 0) ? 0 : _blobHeapStartOffset + index.HeapPosition;
}
public int GetUserStringToken(string str)
public bool TryGetUserStringToken(string str, out int token)
{
int index;
if (!_userStrings.TryGetValue(str, out index))
......@@ -269,6 +269,14 @@ public int GetUserStringToken(string str)
Debug.Assert(!_streamsAreComplete);
index = _userStringWriter.Position + _userStringHeapStartOffset;
// User strings are referenced by metadata tokens (8 bits of which are used for the token type) leaving only 24 bits for the offset.
if ((index & 0xFF000000) != 0)
{
token = 0;
return false;
}
_userStrings.Add(str, index);
_userStringWriter.WriteCompressedInteger((uint)str.Length * 2 + 1);
......@@ -327,7 +335,8 @@ public int GetUserStringToken(string str)
_userStringWriter.WriteByte(stringKind);
}
return 0x70000000 | index;
token = 0x70000000 | index;
return true;
}
public void Complete()
......
......@@ -422,6 +422,7 @@ private bool IsMinimalDelta
private int[] _pseudoSymbolTokenToTokenMap;
private IReference[] _pseudoSymbolTokenToReferenceMap;
private int[] _pseudoStringTokenToTokenMap;
private bool _userStringTokenOverflow;
private List<string> _pseudoStringTokenToStringMap;
private ReferenceIndexer _referenceVisitor;
......@@ -4479,7 +4480,23 @@ private int ResolveStringTokenFromPseudoStringToken(int pseudoStringToken)
var str = _pseudoStringTokenToStringMap[index];
if (str != null)
{
var token = heaps.GetUserStringToken(str);
const int overflowToken = 0x70000000; // 0x70 is a token type for a user string
int token;
if (!_userStringTokenOverflow)
{
if(!heaps.TryGetUserStringToken(str, out token))
{
this.Context.Diagnostics.Add(this.messageProvider.CreateDiagnostic(this.messageProvider.ERR_TooManyUserStrings,
NoLocation.Singleton));
_userStringTokenOverflow = true;
token = overflowToken;
}
}
else
{
token = overflowToken;
}
_pseudoStringTokenToTokenMap[index] = token;
_pseudoStringTokenToStringMap[index] = null; // Set to null to bypass next lookup
return token;
......
......@@ -1681,6 +1681,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ERR_DebugEntryPointNotSourceMethodDefinition = 37252
ERR_InvalidPathMap = 37253
ERR_PublicSignNoKey = 37254
ERR_TooManyUserStrings = 37255
ERR_LastPlusOne
......
......@@ -491,6 +491,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ERRID.ERR_EncReferenceToAddedMember
End Get
End Property
Public Overrides ReadOnly Property ERR_TooManyUserStrings As Integer
Get
Return ERRID.ERR_TooManyUserStrings
End Get
End Property
End Class
End Namespace
......@@ -10253,6 +10253,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals..
'''</summary>
Friend ReadOnly Property ERR_TooManyUserStrings() As String
Get
Return ResourceManager.GetString("ERR_TooManyUserStrings", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Method cannot contain both a &apos;Try&apos; statement and an &apos;On Error&apos; or &apos;Resume&apos; statement..
'''</summary>
......
......@@ -5344,4 +5344,7 @@
<data name="SyntaxTreeIsNotASubmission" xml:space="preserve">
<value>Syntax tree should be created from a submission.</value>
</data>
<data name="ERR_TooManyUserStrings" xml:space="preserve">
<value>Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals.</value>
</data>
</root>
\ No newline at end of file
......@@ -574,6 +574,35 @@ BC35000: Requested operation is not available because the runtime library functi
]]></expected>)
End Sub
<Fact, WorkItem(8287, "https://github.com/dotnet/roslyn/issues/8287")>
Public Sub ToManyUserStrings()
Dim source As New System.Text.StringBuilder()
source.Append("
Module C
Sub Main()
")
For i As Integer = 1 To 11
source.Append(
" System.Console.WriteLine(""")
source.Append(ChrW(AscW("A"c) + i), 1000000)
source.Append(""")
")
Next
source.Append("
End Sub
End Module")
Dim compilation = CreateCompilationWithReferences(VisualBasicSyntaxTree.ParseText(source.ToString()), {MscorlibRef, SystemRef, MsvbRef})
AssertTheseEmitDiagnostics(compilation,
<expected>
BC37255: Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string or XML literals.
</expected>)
End Sub
#End Region
End Class
......
......@@ -354,5 +354,13 @@ public override int ERR_BadCompilationOptionValue
throw new NotImplementedException();
}
}
public override int ERR_TooManyUserStrings
{
get
{
throw new NotImplementedException();
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册