-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix resx test name mangling logic #39569
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recall @ericstj was aware about such case but I don't remember why we didn't bother handling this case. Anyway, this change LGTM.
/azp run runtime |
Azure Pipelines successfully started running 1 pipeline(s). |
@dotnet/dnceng
|
This code was intentionally mangling the type name with generic parameters in order to test a problem that existed in the old resource writer (and thus in resources that needed to load on core). This is described in the commit 01aeaa5, as well as in the name of the type you modified: I believe this commit should be undone. How was this blocking you? |
@danmosemsft there was a brief network blip and DNS outage on Azure exactly around this time (same problem you may see in the partners mail about the auto scaler), so aside from us hardening the services we own around this not much we can do for MCR. |
I changed the implementation of runtime/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs Lines 301 to 303 in a366d63
Lines 27 to 31 in a366d63
Here's the modified code: In a nutshell, the code path above now actually serializes a using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace SampleFormatterApp
{
class Program
{
static void Main(string[] args)
{
var ms = new MemoryStream();
var bf = new BinaryFormatter();
bf.Binder = new MyBinder();
Console.WriteLine("Serializing Foo...");
bf.Serialize(ms, new Foo());
Console.WriteLine("Finished serializing Foo.");
Console.WriteLine();
Console.WriteLine("Serializing Bar...");
bf.Serialize(ms, new Bar());
Console.WriteLine("Finished serializing Bar.");
}
}
[Serializable]
class Foo : ISerializable
{
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(Bar));
}
}
[Serializable]
class Bar
{
}
class MyBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
throw new NotImplementedException();
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
Console.WriteLine($"BindToName({serializedType.FullName}) called.");
base.BindToName(serializedType, out assemblyName, out typeName);
}
}
} Outputs: Serializing Foo...
BindToName(SampleFormatterApp.Foo) called. <--- !!!!!
Finished serializing Foo.
Serializing Bar...
BindToName(SampleFormatterApp.Bar) called.
Finished serializing Bar. Now, to see why this matters, tweak the sample app a bit. Type nonRandomizedEqCmpType = typeof(object).Assembly.GetType("System.Collections.Generic.NonRandomizedStringEqualityComparer");
Type genericEqCmpType = EqualityComparer<string>.Default.GetType();
var ms = new MemoryStream();
var bf = new BinaryFormatter();
bf.Binder = new MyBinder();
Console.WriteLine("Serializing NonRandomizedComparer...");
bf.Serialize(ms, Activator.CreateInstance(nonRandomizedEqCmpType, nonPublic: true));
Console.WriteLine("Finished serializing NonRandomizedComparer.");
Console.WriteLine();
Console.WriteLine("Serializing GEC<string>...");
bf.Serialize(ms, Activator.CreateInstance(genericEqCmpType, nonPublic: true));
Console.WriteLine("Finished serializing GEC<string>."); Outputs: Serializing NonRandomizedComparer...
BindToName(System.Collections.Generic.NonRandomizedStringEqualityComparer) called.
Finished serializing NonRandomizedComparer.
Serializing GEC<string>...
BindToName(System.Collections.Generic.GenericEqualityComparer`1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]) called.
Finished serializing GEC<string>. The first case is the "before", and the second case is the "after". In the before case, the In the after case, the Hence why this very specific unit test is failing on my changes. |
I think this test was just failing because it observed that you changed the binary format of Dictionary. We need to keep the piece of code that breaks the type/assembly name as that's the specific behavior that this test is ensuring we continue to support. |
There's an edge case in the logic for System.Resources.Extensions.Tests that isn't being handled properly. This is blocking my progress on #36252.
Here's the existing logic:
runtime/src/libraries/System.Resources.Extensions/tests/TestData.cs
Lines 303 to 317 in 87d8f7d
I have a case where assemblyQualifiedTypeName is
"System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
. However, the IndexOf above is improperly detecting the','
as part of the generic term, which results in the corrupted output:assemblyName =
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
(note the]]
)newTypeName =
"System.Collections.Generic.GenericEqualityComparer`1[[System.String"
(note the[[
)This PR updates the type name mangling logic to ignore any
','
characters that are within a generic parameters list. This affects only test code, not runtime code.