-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
.NET version
8.0.201 (the affected code is still there in .NET 9)
Did it work in .NET Framework?
Yes
Did it work in any of the earlier releases of .NET Core or .NET 5+?
No response
Issue description
The code in ResourceCodeDomSerializer.SerializationResourceManager.SetValue() (around code lines 714) is failing when assigning sequential number suffixes to resource names:
While I cannot provide an quick-and-easy project to reproduce this, I'd like to suggest reading the code instead:
....
// Now find an unused name
string resourceName = nameBase;
// Only append the number when appendCount is set or if there is already a count.
int count = 0;
if (appendCount || _nameTable.TryGetValue(nameBase, out count))
{
count++;
resourceName = $"{nameBase}{count}";
}
// Now that we have a name, write out the resource.
SetValue(manager, resourceName, value, forceInvariant, shouldSerializeInvariant, ensureInvariant, applyingCachedResources);
_nameTable[resourceName] = count; // <<--- bug here, _nameTable[nameBase] should be assigned instead
....
The code in .NET 4.8 assigned numbers starting from 1..N (even if only one value was in the _nameTable, so from the comment in the code I assume it has been changed to avoid assigning a number to the very first occurrence.
The bug occurs when generating number suffixes for the same nameBase
value more than twice - it will end up using the same number 1 over and over. You'll end up with a _nameTable looking like this:
- "name" => 0
- "name1" => 1
"name1" will be overwritten every time after the second.
Steps to reproduce
The bug is recurring in our software when copy/pasting WinForms controls in design mode. We are maintaining a Window Editor application which allows to copy/paste controls. When serializing the controls, the CodeDomSerializer will end up generating code like this (note the resource names, which are always using the number 1 as suffix.
CustomTextField.CustomProperty.AddRange(new CustomAssembly.Controls.Collections.CollectionItem[] {
((CustomAssembly.Controls.Collections.CollectionItem)(resources.GetObject("CustomTextField.CustomProperty"))),
((CustomAssembly.Controls.Collections.CollectionItem)(resources.GetObject("CustomTextField.CustomProperty1"))),
((CustomAssembly.Controls.Collections.CollectionItem)(resources.GetObject("CustomTextField.CustomProperty1"))),
((CustomAssembly.Controls.Collections.CollectionItem)(resources.GetObject("CustomTextField.CustomProperty1")))});