Merge pull request #19775 from jketema/seh-2

C++: Generate SEH edges for pointer dereference loads/stores in `__try` blocks
This commit is contained in:
Jeroen Ketema
2025-06-16 18:00:39 +02:00
committed by GitHub
6 changed files with 297 additions and 3 deletions

View File

@@ -381,6 +381,14 @@ abstract class TranslatedValueCategoryAdjustment extends TranslatedExpr {
final TranslatedCoreExpr getOperand() { result.getExpr() = expr }
}
/**
* Holds if `expr` requires an `SehExceptionEdge` to be generated.
*/
private predicate hasSehExceptionEdge(Expr expr) {
expr instanceof PointerDereferenceExpr and
exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*())
}
/**
* IR translation of an implicit lvalue-to-rvalue conversion on the result of
* an expression.
@@ -400,7 +408,13 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = LoadTag() and
result = this.getParent().getChildSuccessor(this, kind)
(
result = this.getParent().getChildSuccessor(this, kind)
or
hasSehExceptionEdge(expr) and
kind instanceof SehExceptionEdge and
result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e))
)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -1945,7 +1959,13 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = AssignmentStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
(
result = this.getParent().getChildSuccessor(this, kind)
or
hasSehExceptionEdge(expr.getLValue()) and
kind instanceof SehExceptionEdge and
result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e))
)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {

View File

@@ -49689,6 +49689,74 @@ try_except.c:
# 52| Type = [IntType] int
# 52| ValueCategory = prvalue(load)
# 54| getStmt(2): [ReturnStmt] return ...
# 56| [TopLevelFunction] void k(int*, int*, int*)
# 56| <params>:
# 56| getParameter(0): [Parameter] b
# 56| Type = [IntPointerType] int *
# 56| getParameter(1): [Parameter] c
# 56| Type = [IntPointerType] int *
# 56| getParameter(2): [Parameter] d
# 56| Type = [IntPointerType] int *
# 56| getEntryPoint(): [BlockStmt] { ... }
# 57| getStmt(0): [DeclStmt] declaration
# 57| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 57| Type = [IntType] int
# 57| getVariable().getInitializer(): [Initializer] initializer for x
# 57| getExpr(): [Literal] 0
# 57| Type = [IntType] int
# 57| Value = [Literal] 0
# 57| ValueCategory = prvalue
# 58| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... }
# 58| getStmt(): [BlockStmt] { ... }
# 59| getStmt(0): [ExprStmt] ExprStmt
# 59| getExpr(): [AssignExpr] ... = ...
# 59| Type = [IntType] int
# 59| ValueCategory = prvalue
# 59| getLValue(): [VariableAccess] x
# 59| Type = [IntType] int
# 59| ValueCategory = lvalue
# 59| getRValue(): [PointerDereferenceExpr] * ...
# 59| Type = [IntType] int
# 59| ValueCategory = prvalue(load)
# 59| getOperand(): [VariableAccess] b
# 59| Type = [IntPointerType] int *
# 59| ValueCategory = prvalue(load)
# 60| getStmt(1): [ExprStmt] ExprStmt
# 60| getExpr(): [AssignExpr] ... = ...
# 60| Type = [IntType] int
# 60| ValueCategory = prvalue
# 60| getLValue(): [PointerDereferenceExpr] * ...
# 60| Type = [IntType] int
# 60| ValueCategory = lvalue
# 60| getOperand(): [VariableAccess] c
# 60| Type = [IntPointerType] int *
# 60| ValueCategory = prvalue(load)
# 60| getRValue(): [VariableAccess] x
# 60| Type = [IntType] int
# 60| ValueCategory = prvalue(load)
# 61| getStmt(2): [DeclStmt] declaration
# 61| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 61| Type = [IntType] int
# 61| getVariable().getInitializer(): [Initializer] initializer for y
# 61| getExpr(): [PointerDereferenceExpr] * ...
# 61| Type = [IntType] int
# 61| ValueCategory = prvalue(load)
# 61| getOperand(): [VariableAccess] d
# 61| Type = [IntPointerType] int *
# 61| ValueCategory = prvalue(load)
# 63| getCondition(): [Literal] 1
# 63| Type = [IntType] int
# 63| Value = [Literal] 1
# 63| ValueCategory = prvalue
# 63| getExcept(): [BlockStmt] { ... }
# 64| getStmt(0): [ExprStmt] ExprStmt
# 64| getExpr(): [FunctionCall] call to sink
# 64| Type = [VoidType] void
# 64| ValueCategory = prvalue
# 64| getArgument(0): [VariableAccess] x
# 64| Type = [IntType] int
# 64| ValueCategory = prvalue(load)
# 66| getStmt(2): [ReturnStmt] return ...
try_except.cpp:
# 3| [TopLevelFunction] void ProbeFunction()
# 3| <params>:

View File

@@ -39258,6 +39258,105 @@ try_except.c:
# 46| Block 7
# 46| v46_10(void) = Unreached :
# 56| void k(int*, int*, int*)
# 56| Block 0
# 56| v56_1(void) = EnterFunction :
# 56| m56_2(unknown) = AliasedDefinition :
# 56| m56_3(unknown) = InitializeNonLocal :
# 56| m56_4(unknown) = Chi : total:m56_2, partial:m56_3
# 56| r56_5(glval<int *>) = VariableAddress[b] :
# 56| m56_6(int *) = InitializeParameter[b] : &:r56_5
# 56| r56_7(int *) = Load[b] : &:r56_5, m56_6
# 56| m56_8(unknown) = InitializeIndirection[b] : &:r56_7
# 56| r56_9(glval<int *>) = VariableAddress[c] :
# 56| m56_10(int *) = InitializeParameter[c] : &:r56_9
# 56| r56_11(int *) = Load[c] : &:r56_9, m56_10
# 56| m56_12(unknown) = InitializeIndirection[c] : &:r56_11
# 56| r56_13(glval<int *>) = VariableAddress[d] :
# 56| m56_14(int *) = InitializeParameter[d] : &:r56_13
# 56| r56_15(int *) = Load[d] : &:r56_13, m56_14
# 56| m56_16(unknown) = InitializeIndirection[d] : &:r56_15
# 57| r57_1(glval<int>) = VariableAddress[x] :
# 57| r57_2(int) = Constant[0] :
# 57| m57_3(int) = Store[x] : &:r57_1, r57_2
# 59| r59_1(glval<int *>) = VariableAddress[b] :
# 59| r59_2(int *) = Load[b] : &:r59_1, m56_6
# 59| r59_3(int) = Load[?] : &:r59_2, ~m56_8
#-----| Goto -> Block 1
#-----| SEH Exception -> Block 6
# 59| Block 1
# 59| r59_4(glval<int>) = VariableAddress[x] :
# 59| m59_5(int) = Store[x] : &:r59_4, r59_3
# 60| r60_1(glval<int>) = VariableAddress[x] :
# 60| r60_2(int) = Load[x] : &:r60_1, m59_5
# 60| r60_3(glval<int *>) = VariableAddress[c] :
# 60| r60_4(int *) = Load[c] : &:r60_3, m56_10
# 60| r60_5(glval<int>) = CopyValue : r60_4
# 60| m60_6(int) = Store[?] : &:r60_5, r60_2
# 60| m60_7(unknown) = Chi : total:m56_12, partial:m60_6
#-----| Goto -> Block 2
#-----| SEH Exception -> Block 6
# 61| Block 2
# 61| r61_1(glval<int>) = VariableAddress[y] :
# 61| r61_2(glval<int *>) = VariableAddress[d] :
# 61| r61_3(int *) = Load[d] : &:r61_2, m56_14
# 61| r61_4(int) = Load[?] : &:r61_3, ~m56_16
#-----| Goto -> Block 3
#-----| SEH Exception -> Block 6
# 61| Block 3
# 61| m61_5(int) = Store[y] : &:r61_1, r61_4
#-----| Goto -> Block 8
# 63| Block 4
# 63| r63_1(int) = Constant[0] :
# 63| r63_2(bool) = CompareEQ : r63_9, r63_1
# 63| v63_3(void) = ConditionalBranch : r63_2
#-----| False -> Block 5
#-----| True -> Block 9
# 63| Block 5
# 63| r63_4(int) = Constant[1] :
# 63| r63_5(bool) = CompareEQ : r63_9, r63_4
# 63| v63_6(void) = ConditionalBranch : r63_5
#-----| False -> Block 9
#-----| True -> Block 7
# 63| Block 6
# 63| m63_7(unknown) = Phi : from 0:m56_12, from 1:m60_7, from 2:m60_7
# 63| m63_8(int) = Phi : from 0:m57_3, from 1:m59_5, from 2:m59_5
# 63| r63_9(int) = Constant[1] :
# 63| r63_10(int) = Constant[-1] :
# 63| r63_11(bool) = CompareEQ : r63_9, r63_10
# 63| v63_12(void) = ConditionalBranch : r63_11
#-----| False -> Block 4
#-----| True -> Block 9
# 64| Block 7
# 64| r64_1(glval<unknown>) = FunctionAddress[sink] :
# 64| r64_2(glval<int>) = VariableAddress[x] :
# 64| r64_3(int) = Load[x] : &:r64_2, m63_8
# 64| v64_4(void) = Call[sink] : func:r64_1, 0:r64_3
# 64| m64_5(unknown) = ^CallSideEffect : ~m56_4
# 64| m64_6(unknown) = Chi : total:m56_4, partial:m64_5
#-----| Goto -> Block 8
# 66| Block 8
# 66| m66_1(unknown) = Phi : from 3:m60_7, from 7:m63_7
# 66| m66_2(unknown) = Phi : from 3:~m56_4, from 7:~m64_6
# 66| v66_3(void) = NoOp :
# 56| v56_17(void) = ReturnIndirection[b] : &:r56_7, m56_8
# 56| v56_18(void) = ReturnIndirection[c] : &:r56_11, m66_1
# 56| v56_19(void) = ReturnIndirection[d] : &:r56_15, m56_16
# 56| v56_20(void) = ReturnVoid :
# 56| v56_21(void) = AliasedUse : ~m66_2
# 56| v56_22(void) = ExitFunction :
# 56| Block 9
# 56| v56_23(void) = Unreached :
try_except.cpp:
# 6| void f_cpp()
# 6| Block 0

View File

@@ -37533,6 +37533,101 @@ try_except.c:
# 46| v46_9(void) = ReturnVoid :
#-----| Goto -> Block 1
# 56| void k(int*, int*, int*)
# 56| Block 0
# 56| v56_1(void) = EnterFunction :
# 56| mu56_2(unknown) = AliasedDefinition :
# 56| mu56_3(unknown) = InitializeNonLocal :
# 56| r56_4(glval<int *>) = VariableAddress[b] :
# 56| mu56_5(int *) = InitializeParameter[b] : &:r56_4
# 56| r56_6(int *) = Load[b] : &:r56_4, ~m?
# 56| mu56_7(unknown) = InitializeIndirection[b] : &:r56_6
# 56| r56_8(glval<int *>) = VariableAddress[c] :
# 56| mu56_9(int *) = InitializeParameter[c] : &:r56_8
# 56| r56_10(int *) = Load[c] : &:r56_8, ~m?
# 56| mu56_11(unknown) = InitializeIndirection[c] : &:r56_10
# 56| r56_12(glval<int *>) = VariableAddress[d] :
# 56| mu56_13(int *) = InitializeParameter[d] : &:r56_12
# 56| r56_14(int *) = Load[d] : &:r56_12, ~m?
# 56| mu56_15(unknown) = InitializeIndirection[d] : &:r56_14
# 57| r57_1(glval<int>) = VariableAddress[x] :
# 57| r57_2(int) = Constant[0] :
# 57| mu57_3(int) = Store[x] : &:r57_1, r57_2
# 59| r59_1(glval<int *>) = VariableAddress[b] :
# 59| r59_2(int *) = Load[b] : &:r59_1, ~m?
# 59| r59_3(int) = Load[?] : &:r59_2, ~m?
#-----| Goto -> Block 3
#-----| SEH Exception -> Block 8
# 56| Block 1
# 56| v56_16(void) = AliasedUse : ~m?
# 56| v56_17(void) = ExitFunction :
# 56| Block 2
# 56| v56_18(void) = Unwind :
#-----| Goto -> Block 1
# 59| Block 3
# 59| r59_4(glval<int>) = VariableAddress[x] :
# 59| mu59_5(int) = Store[x] : &:r59_4, r59_3
# 60| r60_1(glval<int>) = VariableAddress[x] :
# 60| r60_2(int) = Load[x] : &:r60_1, ~m?
# 60| r60_3(glval<int *>) = VariableAddress[c] :
# 60| r60_4(int *) = Load[c] : &:r60_3, ~m?
# 60| r60_5(glval<int>) = CopyValue : r60_4
# 60| mu60_6(int) = Store[?] : &:r60_5, r60_2
#-----| Goto -> Block 4
#-----| SEH Exception -> Block 8
# 61| Block 4
# 61| r61_1(glval<int>) = VariableAddress[y] :
# 61| r61_2(glval<int *>) = VariableAddress[d] :
# 61| r61_3(int *) = Load[d] : &:r61_2, ~m?
# 61| r61_4(int) = Load[?] : &:r61_3, ~m?
#-----| Goto -> Block 5
#-----| SEH Exception -> Block 8
# 61| Block 5
# 61| mu61_5(int) = Store[y] : &:r61_1, r61_4
#-----| Goto -> Block 10
# 63| Block 6
# 63| r63_1(int) = Constant[0] :
# 63| r63_2(bool) = CompareEQ : r63_7, r63_1
# 63| v63_3(void) = ConditionalBranch : r63_2
#-----| False -> Block 7
#-----| True -> Block 2
# 63| Block 7
# 63| r63_4(int) = Constant[1] :
# 63| r63_5(bool) = CompareEQ : r63_7, r63_4
# 63| v63_6(void) = ConditionalBranch : r63_5
#-----| True -> Block 9
# 63| Block 8
# 63| r63_7(int) = Constant[1] :
# 63| r63_8(int) = Constant[-1] :
# 63| r63_9(bool) = CompareEQ : r63_7, r63_8
# 63| v63_10(void) = ConditionalBranch : r63_9
#-----| False -> Block 6
#-----| True -> Block 2
# 64| Block 9
# 64| r64_1(glval<unknown>) = FunctionAddress[sink] :
# 64| r64_2(glval<int>) = VariableAddress[x] :
# 64| r64_3(int) = Load[x] : &:r64_2, ~m?
# 64| v64_4(void) = Call[sink] : func:r64_1, 0:r64_3
# 64| mu64_5(unknown) = ^CallSideEffect : ~m?
#-----| Goto -> Block 10
# 66| Block 10
# 66| v66_1(void) = NoOp :
# 56| v56_19(void) = ReturnIndirection[b] : &:r56_6, ~m?
# 56| v56_20(void) = ReturnIndirection[c] : &:r56_10, ~m?
# 56| v56_21(void) = ReturnIndirection[d] : &:r56_14, ~m?
# 56| v56_22(void) = ReturnVoid :
#-----| Goto -> Block 1
try_except.cpp:
# 6| void f_cpp()
# 6| Block 0

View File

@@ -52,3 +52,15 @@ void j(int b) {
sink(x);
}
}
void k(int *b, int *c, int *d) {
int x = 0;
__try {
x = *b;
*c = x;
int y = *d;
}
__except (1) {
sink(x);
}
}

View File

@@ -49,6 +49,6 @@ void throw_cpp(int b) {
}
}
__except (1) {
sink(x);
sink(x);
}
}