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

Fixes for Partial Trust #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Fixes for Partial Trust #14

wants to merge 1 commit into from

Conversation

AlphaGremlin
Copy link
Contributor

Added partially trusted caller support
Added more SecuritySafeCritical attributes so an AsyncBridge-compiled program running with 4.5 installed will not fail.
Fixed exception propagation in partial trust

Added partially trusted caller support
Added more SecuritySafeCritical attributes so an AsyncBridge-compiled program running with 4.5 installed will not fail.
Fixed exception propagation in partial trust
Copy link
Collaborator

@jnm2 jnm2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to write these tests! This is pretty awesome stuff and it's temping to merge it right away!
If any change is important enough to add to the codebase, I'd like to have it protected by a test. This serves two critical purposes for us: documentation, and protection from future regressions.

#if !NET35
[assembly: AllowPartiallyTrustedCallers]
#if !PORTABLE
[assembly: SecurityRules(SecurityRuleSet.Level2)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this line is removed, no tests fail. Is it possible to test this in some way? If not, can you add a comment above it explaining why it is needed?

Also, no biggie but would you mind renaming the file to AssemblyInfo.cs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SecurityRules is recommended to be added. On my phone so I can't reference the exact reason. Will check later.

Will rename. That's what the file was called in the older project before the cleanup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.microsoft.com/en-us/dotnet/framework/misc/security-transparent-code-level-2#usage-examples-and-behaviors

"If you do not annotate an assembly, the .NET Framework 4 rules are used by default. However, the recommended best practice is to use the SecurityRulesAttribute attribute instead of depending on the default."

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it's locking it rather than following the CLR default. That's fine so long as we can be sure that this doesn't cause any issues on CLR v2, which we don't run tests against. How would we verify that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the project even build against a vanilla 2.0? The attribute only exists in 4.0+, so maybe we just need to change the #if to specifically check for 4.0+

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I missed that this is still nested in #if !NET35! Might read more clearly, but it's up to you.

@@ -79,6 +79,7 @@ private AsyncVoidMethodBuilder(SynchronizationContext synchronizationContext)
/// <summary>
/// Registers with UnobservedTaskException to suppress exception crashing.
/// </summary>
[SecuritySafeCritical]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a test that fails when this line is removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see what I can do. As I recall, without it, secannotate reports a transparency violation. Theoretically it will throw TypeLoadException if you try to use it in partial trust.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is only relevant in a .Net 4.5 environment where you're loading a library built with AsyncBridge. In 4.5, TaskScheduler.UnobservedTaskException is marked SecurityCritical, causing it to throw TypeLoadException. AsyncBridge currently has a blind catch that swallows the exception. It won't automatically observe exceptions any more, but I think that's fine, since on 4.5 it won't bring down the AppDomain unless the application sets ThrowOnUnobservedTaskExceptions. If it does, that's what you'd expect anyway.

We obviously want to fix this, since it's an exception that can be avoided. But it makes me wonder about the opposite scenario -- full trust on 4.5. With AsyncBridge as it is, even if the application sets ThrowOnUnobservedTaskExceptions, it will never throw because we automatically observe everything. It also introduces heisenbugs, whereby depending on whether you've run a 4.0 async method determines whether the application fails or silently swallows them.

The only solution would be to somehow detect if we're running on 4.5 and not add the event handler. I'm not sure how we can do that, or if we event want to.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's enlightening, thanks! I don't like the blind catch. Is there a way we could get rid of it on all platforms?

{
CodeAccessPermission.RevertAssert();
}
#endif
Copy link
Collaborator

@jnm2 jnm2 Apr 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a test that fails when the Assert() is removed?
Also, I noticed that s_prepForRemoting.Invoke became prefixed with return (Exception). Is that fixing a separate bug? Can we have a test that fails without the return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the return, the PrepareRemoting method returns the exception. It just happens to return 'this' so ignoring it doesn't cause a problem. Personal preference to follow the obvious desire of the original code and use the return value.

The tests don't fail, but in partial trust they will lose their full stack trace. I wasn't sure how to write a reliable test for that without some crazy string checking that would also make the test localisation specific.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, sounds good.

The stack trace is a good example of the type of thing I'd like to put under test. How crazy, exactly? What if we check for the presence of a stack frame with a certain method name which we set up to get lost in one scenario and not the other?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could work! I'll give it a shot.


public Sandbox()
{
var CurrentSetup = AppDomain.CurrentDomain.SetupInformation;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding #19 asap. Sorry one more time! 😟
Can you use camel-case for both fields and locals, optionally with underscore for fields?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants