-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C++: Support function calls throwing exceptions in the IR #15461
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
ea8f05a
to
508c918
Compare
…dFalseSuccessor'.
508c918
to
33e3753
Compare
# 21| v21_10(void) = ExitFunction : | ||
|
||
# 21| Block 5 | ||
# 21| v21_11(void) = Unreached : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this Unreached
because the exception would propagate?
It got eliminated because we have known constant values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Yes (after your edit 😂). There's an Unreached
instruction here because we generate trivial comparisons that the IR deduces is unreachable when we implement the semantics of Microsoft's structured exception handling:
codeql/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Line 41 in 41cca47
// t2 = cmp t1, condition |
1
)
# 26| Block 2 | ||
# 26| r26_1(int) = Constant[0] : | ||
# 26| r26_2(bool) = CompareEQ : r26_8, r26_1 | ||
# 26| v26_3(void) = ConditionalBranch : r26_2 | ||
#-----| False -> Block 3 | ||
#-----| True -> Block 4 | ||
|
||
# 26| Block 3 | ||
# 26| r26_4(int) = Constant[1] : | ||
# 26| r26_5(bool) = CompareEQ : r26_8, r26_4 | ||
# 26| v26_6(void) = ConditionalBranch : r26_5 | ||
#-----| True -> Block 6 | ||
|
||
# 26| Block 4 | ||
# 26| v26_7(void) = Unwind : | ||
# 29| r29_1(glval<int>) = VariableAddress[#return] : | ||
# 29| r29_2(int) = Constant[0] : | ||
# 29| mu29_3(int) = Store[#return] : &:r29_1, r29_2 | ||
#-----| Goto -> Block 1 | ||
|
||
# 26| Block 5 | ||
# 26| r26_8(int) = Constant[1] : | ||
# 26| r26_9(int) = Constant[-1] : | ||
# 26| r26_10(bool) = CompareEQ : r26_8, r26_9 | ||
# 26| v26_11(void) = ConditionalBranch : r26_10 | ||
#-----| False -> Block 2 | ||
#-----| True -> Block 4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No related to this PR (I think), but this looks somewhat odd. There's both unwinding in the case of -1 and 0, but reading https://learn.microsoft.com/en-us/cpp/cpp/try-except-statement, it seems there should be unwinding in the case of 0, while in the case of -1 the execution should continue at the place where the exception occurred. I don't we can model the latter properly at the moment though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that's what this TODO is about:
codeql/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Line 154 in e5ba8fe
// TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but you might want to wait for @rdmarsh2 to also have a look?
I don't really understand the semantics of the |
Sometimes We could choose to just pass in If you prefer not having the extra argument on |
No, that seems like a good reason to do it. |
This PR adds a new abstract class
ThrowingFunction
to model the exceptional behavior of a function. Specifically, to model that certain functions that may (or unconditionally) throw an exception one can implement the abstract classThrowingFunction
. For example, see the added models for the Windows structured exception handling functions (models/implementations/StructuredExceptionHandling.qll
in this commit).I wish the diff for this PR was just 1dfd32e, but unfortunately the current IR generation classes doesn't allow specifying an
EdgeKind
on thegetChildSuccessor
predicate 😭 (unlikegetInstructionSuccessor
, where we can specify this). So without adding this column we can't actually model that a call may have multiple successors (i.e., a "normal successor" and an "exceptional successor"). So there's a whole bunch of very boring commits that proceed this that actually propagate theseEdgeKind
columns around.