-
-
Notifications
You must be signed in to change notification settings - Fork 646
Protect against circular type forwarders #806
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
Conversation
If we have two assemblies with type forwarders that point to each other, we enter an infinite loop and a stack overflow. This breaks the cycle by detecting reentrancy. Fixes jbevain#706
655d831 to
5ad5672
Compare
|
@jbevain I even added a test! |
|
@jbevain What can community contributors do to get this PR merged and released? This resolves a bug that my team encountered. |
|
FYI @jbevain adding the boolean field is free because of alignment padding: |
|
Unfortunately it's not free for 32-bit (the size goes from 32 to 36 bytes. But there are not many exported types per assembly, so it's honestly negligible. |
|
We've been running into these same stack overflow issues quite a bit but intermittently and not related to circular type forwarders (from what I can tell). I have confirmed this fixes our issues as well, so it'd be nice to have it included in an official release. |
|
@KirillOsenkov just move the field with the other fields and this is good to go :) |
|
It's happening.gif |
It is not thread-safe. Cecil resolver can't be called concurrently from multiple threads because of jbevain/cecil#806. By sharing the assembly cache we get intermittent Circularity exceptions.
|
@jbevain @KirillOsenkov This change is breaking our multi-threaded immediate read logic. Is this change worth it? Cecil is generally a bit delicate when it comes to multi-thread but we've navigated successfully for years. I could be mistaken, but I believe this change introduces a new gotcha pattern that didn't exist previously. |
|
It is an unfortunate side effect that I've also discovered only recently, after the PR was merged. The tradeoff here is the following: people used to run into stack overflows all the time without this check, and there's nothing you can do as a consumer to defend against that. However you do have control over calling Resolve, so it's straightforward to just put a lock around that if you insist that you need parallelism. We could also put a lock directly into the resolver to formalize the expectation that the reader is thread-safe. However the consumer could do that in the rare chance they need to. This is my opinion only. |
I can live with doing nothing if this change is preferred. I was able to duplicate the Resolve logic into our code and avoid calling |
If we have two assemblies with type forwarders that point to each other, we enter an infinite loop and a stack overflow.
This breaks the cycle by detecting reentrancy.
Fixes #706