-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
dotnet/coreclr
#26721Milestone
Description
Courtesy of excellent sleuthing by @lpatalas:
Accessing a CultureInfo
instance's .DateTimeFormat
property before it is cloned with .Clone()
unexpectedly causes the clone's .Calendar
and .DateTimeFormat.Calendar
properties to reference different objects; from PowerShell/PowerShell#10438 (comment):
If I would have to guess it's caused by this line: https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs#L1015. The
_calendar
field isnull
so it's not cloned until it's accessed for the first time. After that it's set and each subsequentClone()
call will create new Calendar instance.
Code to reproduce:
using System;
using System.Globalization;
public static class Program
{
public static void Main()
{
var orig = CultureInfo.InvariantCulture;
for (var i=0; i<2; ++i) {
var clone = (CultureInfo)orig.Clone();
clone.Calendar.TwoDigitYearMax = 2020;
Console.WriteLine($"Clone {i}: Do .Calendar and .DateTimeFormat.Calendar referrence the same object? {object.ReferenceEquals(clone.Calendar, clone.DateTimeFormat.Calendar)}");
Console.WriteLine($"Clone {i}: .Calendar.TwoDigitYearMax vs. .DateTimeFormat.Calendar.TwoDigitYearMax: {clone.Calendar.TwoDigitYearMax} vs. {clone.DateTimeFormat.Calendar.TwoDigitYearMax}");
// Trigger the bug: after this property access,
// cloning `orig` again makes the clones' .Calendar and .
// DateTimeFormat.Calendar references *differ*.
var dummy = orig.DateTimeFormat;
}
}
}
Expected:
Clone 0: Do .Calendar and .DateTimeFormat.Calendar referrence the same object? True
Clone 0: .Calendar.TwoDigitYearMax vs. .DateTimeFormat.Calendar.TwoDigitYearMax: 2020 vs. 2020
Clone 1: Do .Calendar and .DateTimeFormat.Calendar referrence the same object? True
Clone 1: .Calendar.TwoDigitYearMax vs. .DateTimeFormat.Calendar.TwoDigitYearMax: 2020 vs. 2020
Actual (the 2nd iteration exhibits the bug):
Clone 0: Do .Calendar and .DateTimeFormat.Calendar referrence the same object? True
Clone 0: .Calendar.TwoDigitYearMax vs. .DateTimeFormat.Calendar.TwoDigitYearMax: 2020 vs. 2020
Clone 1: Do .Calendar and .DateTimeFormat.Calendar referrence the same object? False
Clone 1: .Calendar.TwoDigitYearMax vs. .DateTimeFormat.Calendar.TwoDigitYearMax: 2020 vs. 2029
scalablecory