Fix race conditions in CultureInfo.GetCultureInfoHelper (#26567)
commite15efa37b78653bb6529a93d5df086b4e4566c99
authorStephen Toub <stoub@microsoft.com>
Sat, 7 Sep 2019 14:47:49 +0000 (7 10:47 -0400)
committerMarek Safar <marek.safar@gmail.com>
Sun, 8 Sep 2019 09:22:09 +0000 (8 11:22 +0200)
tree4a22d9fffa42c7928d24465fd5df7fa5359f54ee
parent8c77bcdfaf841fea6214f8027afbc54c8db6de80
Fix race conditions in CultureInfo.GetCultureInfoHelper (#26567)

The implementation reads the current value of the static cache field and then later overwrites that field with the originally read value.  If ClearCachedData was called in the interim to clear the cached data, this will end up effectively undoing part of that clearing, as it'll end up restoring the previous cache. The fix is to write back the new reference only when we need to, which we could do when we detect it's null.

There's a secondary race condition this fixes as well.  When a name and an altname are used with CultureInfo.GetCurrentCulture(string, string), the implementation was publishig the newly created instance into the dictionary under the lock, but then after the lock was released, it was setting that TextInfo to be read-only.  That provides a window where another thread could see it as non-read-only and mutate it.  The fix is to ensure it's marked as read-only fully before it's published.

As I was doing this, it struck me that the implementation was overly complicated, trying to merge three different code paths for three different callers, presumably to share code, but most of the code ended up not being shared anyway, which just made the code harder to follow for little gain.  So, I split it back out into the three calling functions and removed the helper.

I also changed the locking mechanism.  It had been using a single shared lock to protect all state, but the purpose of the lock is really just to synchronize access to an individual dictionary, so we can just lock on the relevant dictionary.

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs