Skip to content

Commit 2d6546b

Browse files
authored
Fix comparer in StringTokenMap (#81341)
Fixes https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2641964. StringTokenMap (added in #78033) used reference equality comparer; I believe by mistake; which made it possible for it to contain the same string multiple times; leading to overflowing the user string heap limit sooner than before.
1 parent 848a5d3 commit 2d6546b

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using Microsoft.CodeAnalysis.CodeGen;
7+
using Roslyn.Test.Utilities;
8+
using Xunit;
9+
10+
namespace Microsoft.CodeAnalysis.UnitTests.Emit;
11+
12+
public sealed class StringTokenMapTests
13+
{
14+
[Fact, WorkItem("https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2641964")]
15+
public void UniqueStrings()
16+
{
17+
var map = new StringTokenMap(initialHeapSize: 0);
18+
var a1 = new string('a', 5);
19+
var a2 = new string('a', 5);
20+
Assert.Equal(a1, a2);
21+
Assert.NotSame(a1, a2);
22+
Assert.True(map.TryGetOrAddToken(a1, out var token1));
23+
Assert.True(map.TryGetOrAddToken(a2, out var token2));
24+
var b = "b";
25+
Assert.True(map.TryGetOrAddToken(b, out var token3));
26+
Assert.True(map.TryGetOrAddToken(b, out var token4));
27+
Assert.Equal((0u, 0u, 1u, 1u), (token1, token2, token3, token4));
28+
Assert.Equal(["aaaaa", "b"], map.CopyValues());
29+
Assert.Equal("aaaaa", map.GetValue(0));
30+
Assert.Equal("b", map.GetValue(1));
31+
Assert.Throws<IndexOutOfRangeException>(() => map.GetValue(2));
32+
}
33+
}

src/Compilers/Core/Portable/CodeGen/StringTokenMap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Collections.Concurrent;
6-
using System.Collections.Generic;
77
using Microsoft.CodeAnalysis.PooledObjects;
88
using Roslyn.Utilities;
99

@@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CodeGen;
1717
/// </summary>
1818
internal sealed class StringTokenMap(int initialHeapSize)
1919
{
20-
private readonly ConcurrentDictionary<string, uint> _valueToToken = new ConcurrentDictionary<string, uint>(ReferenceEqualityComparer.Instance);
20+
private readonly ConcurrentDictionary<string, uint> _valueToToken = new ConcurrentDictionary<string, uint>(StringComparer.Ordinal);
2121
private readonly ArrayBuilder<string> _uniqueValues = [];
2222
private int _heapSize = initialHeapSize;
2323

0 commit comments

Comments
 (0)