dotnet/roslyn

Roslyn compiler does not round-trip attribute arguments that contain unmatched surrogates

开放

#41,764 创建于 2020年2月18日

 (0 条评论) (0 个反应) (0 位负责人)C# (4,257 个派生)batch import
Area-CompilersBughelp wanted

仓库指标

星标
 (20,414 个星标)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 256 个 PR)

描述

See also https://github.com/dotnet/roslyn/issues/41280

The following test passes on netcore 3.1, but the test demonstrates that

  1. an attribute in source with a string argument containing an unmatched surrogate is seen properly (unedited) through the symbol APIs from the source assembly
  2. results in a different attribute value when viewed through the compiler APIs on the emitted assembly
  3. results in a yet different value when viewed at runtime using reflection

The same value should be seen through all three mechanisms.

        [Fact]
        public void TEMP()
        {
            const string UnicodeHighSurrogate = "\uD800";
            const string UnicodeReplacementCharacter = "\uFFFD";

            var source =
@"using System;
 
[Obsolete(UnicodeHighSurrogate)]
class C
{
    public const string UnicodeHighSurrogate = ""\uD800"";
    public const string UnicodeReplacementCharacter = ""\uFFFD"";
 
    static void Main()
    {
        string message = ((ObsoleteAttribute)typeof(C).GetCustomAttributes(false)[0]).Message;
 
        Console.WriteLine(message == UnicodeReplacementCharacter + UnicodeReplacementCharacter);
    }
}";
            Func<bool, Action<ModuleSymbol>> validator = isFromSource => (ModuleSymbol module) =>
            {
                var C = module.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
                var obs = C.GetAttributes()[0];
                var tc = obs.ConstructorArguments.First();
                Assert.Equal(isFromSource ? UnicodeHighSurrogate : UnicodeReplacementCharacter + UnicodeReplacementCharacter + UnicodeReplacementCharacter, (string)tc.Value);
            };
            CompileAndVerify(source, sourceSymbolValidator: validator(true), symbolValidator: validator(false), expectedOutput: "True");
        }

贡献者指南