Skip to content

Commit 9da590e

Browse files
authored
Merge branch 'main' into declare-permissions
2 parents c5a047d + 06334ee commit 9da590e

File tree

142 files changed

+24724
-5662
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+24724
-5662
lines changed

Diff for: cpp/ql/lib/change-notes/2024-01-30-throwing-model.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.

Diff for: cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

+8-2
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,10 @@ private class InstructionExprNode extends ExprNodeBase, InstructionNode {
14081408
InstructionExprNode() {
14091409
exists(Expr e, int n |
14101410
exprNodeShouldBeInstruction(this, e, n) and
1411-
not exprNodeShouldBe(e, n + 1)
1411+
not exists(Expr conv |
1412+
exprNodeShouldBe(conv, n + 1) and
1413+
conv.getUnconverted() = e.getUnconverted()
1414+
)
14121415
)
14131416
}
14141417

@@ -1419,7 +1422,10 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
14191422
OperandExprNode() {
14201423
exists(Expr e, int n |
14211424
exprNodeShouldBeOperand(this, e, n) and
1422-
not exprNodeShouldBe(e, n + 1)
1425+
not exists(Expr conv |
1426+
exprNodeShouldBe(conv, n + 1) and
1427+
conv.getUnconverted() = e.getUnconverted()
1428+
)
14231429
)
14241430
}
14251431

Diff for: cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll

+4-4
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ private predicate backEdgeCandidate(
285285
// is a back edge. This includes edges from `continue` and the fall-through
286286
// edge(s) after the last instruction(s) in the body.
287287
exists(TranslatedWhileStmt s |
288-
targetInstruction = s.getFirstConditionInstruction() and
288+
targetInstruction = s.getFirstConditionInstruction(_) and
289289
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
290290
requiredAncestor = s.getBody()
291291
)
@@ -296,7 +296,7 @@ private predicate backEdgeCandidate(
296296
// { ... } while (0)` statement. Note that all `continue` statements in a
297297
// do-while loop produce forward edges.
298298
exists(TranslatedDoStmt s |
299-
targetInstruction = s.getBody().getFirstInstruction() and
299+
targetInstruction = s.getBody().getFirstInstruction(_) and
300300
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
301301
requiredAncestor = s.getCondition()
302302
)
@@ -308,7 +308,7 @@ private predicate backEdgeCandidate(
308308
// last instruction(s) in the body. A for loop may not have a condition, in
309309
// which case `getFirstConditionInstruction` returns the body instead.
310310
exists(TranslatedForStmt s |
311-
targetInstruction = s.getFirstConditionInstruction() and
311+
targetInstruction = s.getFirstConditionInstruction(_) and
312312
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
313313
(
314314
requiredAncestor = s.getUpdate()
@@ -322,7 +322,7 @@ private predicate backEdgeCandidate(
322322
// Any edge from within the update of the loop to the condition of
323323
// the loop is a back edge.
324324
exists(TranslatedRangeBasedForStmt s |
325-
targetInstruction = s.getCondition().getFirstInstruction() and
325+
targetInstruction = s.getCondition().getFirstInstruction(_) and
326326
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
327327
requiredAncestor = s.getUpdate()
328328
)

Diff for: cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll

+72-32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ private import semmle.code.cpp.ir.implementation.Opcode
33
private import semmle.code.cpp.ir.implementation.internal.OperandTag
44
private import semmle.code.cpp.ir.internal.CppType
55
private import semmle.code.cpp.models.interfaces.SideEffect
6+
private import semmle.code.cpp.models.interfaces.Throwing
67
private import InstructionTag
78
private import SideEffects
89
private import TranslatedElement
@@ -40,10 +41,10 @@ abstract class TranslatedCall extends TranslatedExpr {
4041
id = this.getNumberOfArguments() and result = this.getSideEffects()
4142
}
4243

43-
final override Instruction getFirstInstruction() {
44+
final override Instruction getFirstInstruction(EdgeKind kind) {
4445
if exists(this.getQualifier())
45-
then result = this.getQualifier().getFirstInstruction()
46-
else result = this.getFirstCallTargetInstruction()
46+
then result = this.getQualifier().getFirstInstruction(kind)
47+
else result = this.getFirstCallTargetInstruction(kind)
4748
}
4849

4950
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -52,34 +53,43 @@ abstract class TranslatedCall extends TranslatedExpr {
5253
resultType = getTypeForPRValue(this.getCallResultType())
5354
}
5455

55-
override Instruction getChildSuccessor(TranslatedElement child) {
56+
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
5657
child = this.getQualifier() and
57-
result = this.getFirstCallTargetInstruction()
58+
result = this.getFirstCallTargetInstruction(kind)
5859
or
5960
child = this.getCallTarget() and
60-
result = this.getFirstArgumentOrCallInstruction()
61+
result = this.getFirstArgumentOrCallInstruction(kind)
6162
or
6263
exists(int argIndex |
6364
child = this.getArgument(argIndex) and
6465
if exists(this.getArgument(argIndex + 1))
65-
then result = this.getArgument(argIndex + 1).getFirstInstruction()
66-
else result = this.getInstruction(CallTag())
66+
then result = this.getArgument(argIndex + 1).getFirstInstruction(kind)
67+
else (
68+
result = this.getInstruction(CallTag()) and kind instanceof GotoEdge
69+
)
6770
)
6871
or
6972
child = this.getSideEffects() and
7073
if this.isNoReturn()
7174
then
75+
kind instanceof GotoEdge and
7276
result =
7377
any(UnreachedInstruction instr |
7478
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
7579
)
76-
else result = this.getParent().getChildSuccessor(this)
80+
else (
81+
not this.mustThrowException() and
82+
result = this.getParent().getChildSuccessor(this, kind)
83+
or
84+
this.mayThrowException() and
85+
kind instanceof ExceptionEdge and
86+
result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge))
87+
)
7788
}
7889

7990
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
80-
kind instanceof GotoEdge and
8191
tag = CallTag() and
82-
result = this.getSideEffects().getFirstInstruction()
92+
result = this.getSideEffects().getFirstInstruction(kind)
8393
}
8494

8595
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -100,6 +110,16 @@ abstract class TranslatedCall extends TranslatedExpr {
100110

101111
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
102112

113+
/**
114+
* Holds if the evaluation of this call may throw an exception.
115+
*/
116+
abstract predicate mayThrowException();
117+
118+
/**
119+
* Holds if the evaluation of this call always throws an exception.
120+
*/
121+
abstract predicate mustThrowException();
122+
103123
/**
104124
* Gets the result type of the call.
105125
*/
@@ -121,8 +141,8 @@ abstract class TranslatedCall extends TranslatedExpr {
121141
* it can be overridden by a subclass for cases where there is a call target
122142
* that is not computed from an expression (e.g. a direct call).
123143
*/
124-
Instruction getFirstCallTargetInstruction() {
125-
result = this.getCallTarget().getFirstInstruction()
144+
Instruction getFirstCallTargetInstruction(EdgeKind kind) {
145+
result = this.getCallTarget().getFirstInstruction(kind)
126146
}
127147

128148
/**
@@ -159,10 +179,12 @@ abstract class TranslatedCall extends TranslatedExpr {
159179
* If there are any arguments, gets the first instruction of the first
160180
* argument. Otherwise, returns the call instruction.
161181
*/
162-
final Instruction getFirstArgumentOrCallInstruction() {
182+
final Instruction getFirstArgumentOrCallInstruction(EdgeKind kind) {
163183
if this.hasArguments()
164-
then result = this.getArgument(0).getFirstInstruction()
165-
else result = this.getInstruction(CallTag())
184+
then result = this.getArgument(0).getFirstInstruction(kind)
185+
else (
186+
kind instanceof GotoEdge and result = this.getInstruction(CallTag())
187+
)
166188
}
167189

168190
/**
@@ -203,24 +225,25 @@ abstract class TranslatedSideEffects extends TranslatedElement {
203225
)
204226
}
205227

206-
final override Instruction getChildSuccessor(TranslatedElement te) {
228+
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
207229
exists(int i |
208230
this.getChild(i) = te and
209231
if exists(this.getChild(i + 1))
210-
then result = this.getChild(i + 1).getFirstInstruction()
211-
else result = this.getParent().getChildSuccessor(this)
232+
then result = this.getChild(i + 1).getFirstInstruction(kind)
233+
else result = this.getParent().getChildSuccessor(this, kind)
212234
)
213235
}
214236

215237
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
216238
none()
217239
}
218240

219-
final override Instruction getFirstInstruction() {
220-
result = this.getChild(0).getFirstInstruction()
241+
final override Instruction getFirstInstruction(EdgeKind kind) {
242+
result = this.getChild(0).getFirstInstruction(kind)
221243
or
222244
// Some functions, like `std::move()`, have no side effects whatsoever.
223-
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
245+
not exists(this.getChild(0)) and
246+
result = this.getParent().getChildSuccessor(this, kind)
224247
}
225248

226249
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
@@ -235,8 +258,9 @@ abstract class TranslatedSideEffects extends TranslatedElement {
235258
* (`TranslatedAllocatorCall`).
236259
*/
237260
abstract class TranslatedDirectCall extends TranslatedCall {
238-
final override Instruction getFirstCallTargetInstruction() {
239-
result = this.getInstruction(CallTargetTag())
261+
final override Instruction getFirstCallTargetInstruction(EdgeKind kind) {
262+
result = this.getInstruction(CallTargetTag()) and
263+
kind instanceof GotoEdge
240264
}
241265

242266
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
@@ -253,8 +277,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
253277
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
254278
or
255279
tag = CallTargetTag() and
256-
kind instanceof GotoEdge and
257-
result = this.getFirstArgumentOrCallInstruction()
280+
result = this.getFirstArgumentOrCallInstruction(kind)
258281
}
259282
}
260283

@@ -290,6 +313,15 @@ class TranslatedExprCall extends TranslatedCallExpr {
290313
override TranslatedExpr getCallTarget() {
291314
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
292315
}
316+
317+
final override predicate mayThrowException() {
318+
// We assume that a call to a function pointer will not throw an exception.
319+
// This is not sound in general, but this will greatly reduce the number of
320+
// exceptional edges.
321+
none()
322+
}
323+
324+
final override predicate mustThrowException() { none() }
293325
}
294326

295327
/**
@@ -311,6 +343,14 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
311343
exists(this.getQualifier()) and
312344
not exists(MemberFunction func | expr.getTarget() = func and func.isStatic())
313345
}
346+
347+
final override predicate mayThrowException() {
348+
expr.getTarget().(ThrowingFunction).mayThrowException(_)
349+
}
350+
351+
final override predicate mustThrowException() {
352+
expr.getTarget().(ThrowingFunction).mayThrowException(true)
353+
}
314354
}
315355

316356
/**
@@ -376,10 +416,11 @@ private int initializeAllocationGroup() { result = 3 }
376416
abstract class TranslatedSideEffect extends TranslatedElement {
377417
final override TranslatedElement getChild(int n) { none() }
378418

379-
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
419+
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
380420

381-
final override Instruction getFirstInstruction() {
382-
result = this.getInstruction(OnlyInstructionTag())
421+
final override Instruction getFirstInstruction(EdgeKind kind) {
422+
result = this.getInstruction(OnlyInstructionTag()) and
423+
kind instanceof GotoEdge
383424
}
384425

385426
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
@@ -388,9 +429,8 @@ abstract class TranslatedSideEffect extends TranslatedElement {
388429
}
389430

390431
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
391-
result = this.getParent().getChildSuccessor(this) and
392-
tag = OnlyInstructionTag() and
393-
kind instanceof GotoEdge
432+
result = this.getParent().getChildSuccessor(this, kind) and
433+
tag = OnlyInstructionTag()
394434
}
395435

396436
final override Declaration getFunction() { result = this.getParent().getFunction() }

0 commit comments

Comments
 (0)