Skip to content

C++/C#: Make escape analysis unsound by default #2667

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

Merged
merged 8 commits into from
Jan 28, 2020

Conversation

dbartol
Copy link
Contributor

@dbartol dbartol commented Jan 22, 2020

When building SSA, we'll be assuming that stack variables do not escape, at least until we improve our alias analysis. I've added a new IREscapeAnalysisConfiguration class to allow the query to control this, and a new UseSoundEscapeAnalysis.qll module that can be imported to switch to the sound escape analysis. I've cloned the existing IR and SSA tests to have both sound and unsound versions. There were relatively few diffs in the IR dump tests, and the sanity tests still give the same results after one change described below.

Assuming that stack variables do not escape exposed an existing bug where we do not emit an Uninitialized instruction for the temporary variables used by return statements and throw expressions, even if the initializer is a constructor call or array initializer. I've refactored the code for handling elements that initialize a variable to share a common base class. I added a test case for returning an object initialized by constructor call, and ensured that the IR diffs for the existing throw test cases are correct.

When building SSA, we'll be assuming that stack variables do not escape, at least until we improve our alias analysis. I've added a new `IREscapeAnalysisConfiguration` class to allow the query to control this, and a new `UseSoundEscapeAnalysis.qll` module that can be imported to switch to the sound escape analysis. I've cloned the existing IR and SSA tests to have both sound and unsound versions. There were relatively few diffs in the IR dump tests, and the sanity tests still give the same results after one change described below.

Assuming that stack variables do not escape exposed an existing bug where we do not emit an `Uninitialized` instruction for the temporary variables used by `return` statements and `throw` expressions, even if the initializer is a constructor call or array initializer. I've refactored the code for handling elements that initialize a variable to share a common base class. I added a test case for returning an object initialized by constructor call, and ensured that the IR diffs for the existing `throw` test cases are correct.
@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.ql
Copy link
Contributor

Choose a reason for hiding this comment

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

Why re-introduce the *aliased_ssa_ir.{qlref,expected} files? I thought you had a good reason to delete those in #919.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, I re-added those by mistake. They're useful for seeing diffs caused by changes, but they're still not worth keeping up to date with every PR. Fixed.

Copy link
Contributor

@rdmarsh2 rdmarsh2 left a comment

Choose a reason for hiding this comment

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

LGTM overall, there's a couple points I wanted to check, plus @jbj's comment on the added ssa dump tests in the ir/ir test directory

exists(IREscapeAnalysisConfiguration config |
config.useSoundEscapeAnalysis() and
(
automaticVariableAddressEscapes(var.(IRAutomaticVariable))
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the sound escape analysis get evaluated when config.useSoundEscapAnalysis doesn't hold?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. I checked the DIL, and the optimizer eliminates that half of the disjunction because it can prove that it never holds.

@@ -43,93 +43,34 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
* Represents the IR translation of the declaration of a local variable,
* including its initialization, if any.
*/
abstract class TranslatedVariableDeclaration extends TranslatedElement, InitializationContext {
abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInitialization {
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like a rename without an associated change to what the values of the class are. Is that just a clarification?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.

tag = InitializerVariableAddressTag() and
result = getInitialization().getFirstInstruction() and
kind instanceof GotoEdge
result = TranslatedVariableInitialization.super.getInstructionSuccessor(tag, kind)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I understand what's going on here (the successor relations within each piece are exactly the ones in the respective superclass, and the connection between them is injected into TranslatedVariableInitialization by getInitializationSuccessor) but it seems a bit spooky to me.

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 think a cleaner way of doing this would have been to make the actual (un)initialization part a separate element that is a child of the original element, i.e., composition instead of inheritance. That seemed like an even bigger refactoring in a change where I hadn't expected to do any refactoring to begin with. I can go back and improve this, but I'd prefer to do it in a follow-up post-January.

@dbartol
Copy link
Contributor Author

dbartol commented Jan 26, 2020

I've looked at the test expectation diffs, and they all seem to be expected. In most cases they are also better as well.

@dbartol
Copy link
Contributor Author

dbartol commented Jan 26, 2020

I believe I've addressed all feedback and resolved all the merge conflicts. Ready for final sign-off.

@jbj
Copy link
Contributor

jbj commented Jan 27, 2020

@dbartol Two tests are failing.

@dbartol
Copy link
Contributor Author

dbartol commented Jan 27, 2020

Hmm. Not sure how I missed those. The diffs look like improvements thanks to the non-escaping of a local, so I've just accepted them.

@rdmarsh2
Copy link
Contributor

Tests are broken. Looks like a taint model change on master that affects the new tests in ir/ssa

@dbartol
Copy link
Contributor Author

dbartol commented Jan 27, 2020

Fixed.

@rdmarsh2 rdmarsh2 merged commit a9bcc1d into github:master Jan 28, 2020
@MathiasVP MathiasVP mentioned this pull request Apr 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants