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
Lines changed: 4 additions & 0 deletions
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.

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

Lines changed: 8 additions & 2 deletions
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

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

Lines changed: 4 additions & 4 deletions
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
)

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

Lines changed: 72 additions & 32 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy