Skip to content
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

Race condition in DependencyProperty registration mechanism #10324

Open
h3xds1nz opened this issue Jan 22, 2025 · 0 comments
Open

Race condition in DependencyProperty registration mechanism #10324

h3xds1nz opened this issue Jan 22, 2025 · 0 comments
Labels
Investigate Requires further investigation by the WPF team.

Comments

@h3xds1nz
Copy link
Contributor

Description

There is a race condition in DependencyProperty registration mechanism which can cause a successful DependencyProperty registration for the same type, with the same name. What makes it worse is that this property will exist everywhere but in the property name map.

While there are in total 3 attempts to synchronize the access around the collections, it may happen that this will simply not be enough.

Here we check under a lock whether property exists:

lock (Synchronized)
{
if (PropertyFromName.ContainsKey(key))
{
throw new ArgumentException(SR.Format(SR.PropertyAlreadyRegistered, name, ownerType.Name));
}

Afterwards, under the same lock, DependencyProperty gets an unique index and is added into the list of registered properties. Before this lock is taken, it was already possible for another thread to pass the check for property name map registration successfully.

lock (Synchronized)
{
packedData = (Flags) GetUniqueGlobalIndex(ownerType, name);
RegisteredPropertyList.Add(this);
}

Finally, under the same lock, a property is written without checking whether it exists in the map. That means the previous one that was added into the map, the newer one can replace it (because it has managed to get past the ContainsKey check meanwhile.)

lock (Synchronized)
{
PropertyFromName[key] = dp;
}

Reproduction Steps

As with all race conditions, hit registration overloads for DependencyProperty with the right timing on multiple threads. It is sometimes replicable by running the current tests in a lucky order even. It is not easy but it ain't impossible.

Expected behavior

A dependency property for a single ownerType with an identical name is not created and partially registered, exception is thrown instead.

Actual behavior

A property is created, returned, the newer one replaces the older one in PropertyFromName and the older one ceases to exist in this map without any notice.

Regression?

No.

Known Workarounds

No response

Impact

In the real application world/usage, given that developers follow guidelines of declaring dependency properties as static readonly, there's almost no impact as it requires a grave human error combined with great amount of luck to hit this one since most of the time this will actually properly fail with ArgumentException so you'd find out rather quickly you've made the mistake of declaring two dependency properties for the same type with the same name; then again, you may not always control all of your dependencies.

Configuration

No response

Other information

This also applies to AddOwner instance method where it may cause a metadata override but that's way harder to trigger.

To be honest, I'm not sure this is worth fixing on its own as it might negatively impact perf but I think it's worth to have this issue existing.

@himgoyalmicro himgoyalmicro added the Investigate Requires further investigation by the WPF team. label Jan 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Investigate Requires further investigation by the WPF team.
Projects
None yet
Development

No branches or pull requests

2 participants