Skip to content

Commit 8bf3c42

Browse files
author
Paolo Tranquilli
committed
Merge branch 'main' into rust-experiment
2 parents d8db0e4 + d374935 commit 8bf3c42

File tree

21 files changed

+383
-359
lines changed

21 files changed

+383
-359
lines changed

cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private int isSource(Expr bufferExpr, Element why) {
5757
exists(Type bufferType |
5858
// buffer is the address of a variable
5959
why = bufferExpr.(AddressOfExpr).getAddressable() and
60-
bufferType = why.(Variable).getType() and
60+
bufferType = why.(Variable).getUnspecifiedType() and
6161
result = bufferType.getSize() and
6262
not bufferType instanceof ReferenceType and
6363
not any(Union u).getAMemberVariable() = why

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
209209
(
210210
// Only generate the `Unwind` instruction if there is any exception
211211
// handling present in the function.
212-
exists(TryStmt try | try.getEnclosingFunction() = func) or
212+
exists(TryOrMicrosoftTryStmt try | try.getEnclosingFunction() = func)
213+
or
213214
exists(ThrowExpr throw | throw.getEnclosingFunction() = func)
215+
or
216+
exists(FunctionCall call | call.getEnclosingFunction() = func |
217+
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException()
218+
)
214219
)
215220
or
216221
tag = AliasedUseTag() and

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
7979
tag = TryExceptCompareOneBranch() and
8080
opcode instanceof Opcode::ConditionalBranch and
8181
resultType = getVoidType()
82-
or
83-
// unwind stack
84-
tag = UnwindTag() and
85-
opcode instanceof Opcode::Unwind and
86-
resultType = getVoidType()
8782
}
8883

8984
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -156,7 +151,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
156151
// TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
157152
// we should continue execution at the point where the exception occurred. But we don't have
158153
// any instruction to model this behavior.
159-
result = this.getInstruction(UnwindTag())
154+
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
160155
or
161156
kind instanceof FalseEdge and
162157
result = this.getInstruction(TryExceptGenerateZero())
@@ -176,7 +171,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
176171
tag = TryExceptCompareZeroBranch() and
177172
(
178173
kind instanceof TrueEdge and
179-
result = this.getInstruction(UnwindTag())
174+
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
180175
or
181176
kind instanceof FalseEdge and
182177
result = this.getInstruction(TryExceptGenerateOne())
@@ -196,10 +191,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
196191
tag = TryExceptCompareOneBranch() and
197192
kind instanceof TrueEdge and
198193
result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge))
199-
or
200-
// Unwind -> Parent
201-
tag = UnwindTag() and
202-
result = this.getParent().getChildSuccessor(this, kind)
203194
}
204195

205196
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -215,8 +206,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
215206

216207
override Instruction getALastInstructionInternal() {
217208
result = this.getTranslatedHandler().getALastInstruction()
218-
or
219-
result = this.getInstruction(UnwindTag())
220209
}
221210

222211
private TranslatedExpr getTranslatedCondition() {
@@ -236,6 +225,12 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
236225
}
237226

238227
final override Function getFunction() { result = tryExcept.getEnclosingFunction() }
228+
229+
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
230+
// A throw from within a `__except` block flows to the handler for the parent of
231+
// the `__try`.
232+
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
233+
}
239234
}
240235

241236
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
@@ -583,7 +578,7 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
583578
/**
584579
* A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
585580
*/
586-
private class TryOrMicrosoftTryStmt extends Stmt {
581+
class TryOrMicrosoftTryStmt extends Stmt {
587582
TryOrMicrosoftTryStmt() {
588583
this instanceof TryStmt or
589584
this instanceof MicrosoftTryStmt

cpp/ql/lib/semmle/code/cpp/security/BufferAccess.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ int getPointedSize(Type t) {
1414
* BufferWrite differ.
1515
*/
1616
abstract class BufferAccess extends Expr {
17-
BufferAccess() { not this.isUnevaluated() }
17+
BufferAccess() {
18+
not this.isUnevaluated() and
19+
//A buffer access must be reachable (not in dead code)
20+
reachable(this)
21+
}
1822

1923
abstract string getName();
2024

@@ -26,6 +30,8 @@ abstract class BufferAccess extends Expr {
2630
* - 1 = buffer range [0, getSize) is accessed entirely.
2731
* - 2 = buffer range [0, getSize) may be accessed partially or entirely.
2832
* - 3 = buffer is accessed at offset getSize - 1.
33+
* - 4 = buffer is accessed with null terminator read protections
34+
* (does not read past null terminator, regardless of access size)
2935
*/
3036
abstract Expr getBuffer(string bufferDesc, int accessType);
3137

@@ -128,7 +134,7 @@ class StrncpyBA extends BufferAccess {
128134
or
129135
result = this.(FunctionCall).getArgument(1) and
130136
bufferDesc = "source buffer" and
131-
accessType = 2
137+
accessType = 4
132138
}
133139

134140
override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) }

cpp/ql/src/Critical/OverflowStatic.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class BufferAccess extends ArrayExpr {
4242
not exists(Macro m |
4343
m.getName() = "strcmp" and
4444
m.getAnInvocation().getAnExpandedElement() = this
45-
)
45+
) and
46+
//A buffer access must be reachable (not in dead code)
47+
reachable(this)
4648
}
4749

4850
int bufferSize() { staticBuffer(this.getArrayBase(), _, result) }

cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ from
2626
BufferAccess ba, string bufferDesc, int accessSize, int accessType, Element bufferAlloc,
2727
int bufferSize, string message
2828
where
29+
accessType != 4 and
2930
accessSize = ba.getSize() and
3031
bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), bufferAlloc) and
3132
(
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Removed false positives caused by buffer accesses in unreachable code
5+
* Removed false positives caused by inconsistent type checking

cpp/ql/test/library-tests/ir/ir/aliased_ir.expected

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,41 +3167,45 @@ ir.c:
31673167
# 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2
31683168
# 36| m36_4(unknown) = ^CallSideEffect : ~m32_4
31693169
# 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4
3170-
#-----| Exception -> Block 3
3170+
#-----| Exception -> Block 4
31713171

3172-
# 39| Block 1
3172+
# 32| Block 1
3173+
# 32| v32_5(void) = Unwind :
3174+
# 32| v32_6(void) = AliasedUse : ~m40_5
3175+
# 32| v32_7(void) = ExitFunction :
3176+
3177+
# 39| Block 2
31733178
# 39| r39_1(int) = Constant[0] :
3174-
# 39| r39_2(bool) = CompareEQ : r38_2, r39_1
3179+
# 39| r39_2(bool) = CompareEQ : r38_1, r39_1
31753180
# 39| v39_3(void) = ConditionalBranch : r39_2
3176-
#-----| False (back edge) -> Block 2
3177-
#-----| True -> Block 5
3181+
#-----| False -> Block 3
3182+
#-----| True -> Block 6
31783183

3179-
# 39| Block 2
3184+
# 39| Block 3
31803185
# 39| r39_4(int) = Constant[1] :
3181-
# 39| r39_5(bool) = CompareEQ : r38_2, r39_4
3186+
# 39| r39_5(bool) = CompareEQ : r38_1, r39_4
31823187
# 39| v39_6(void) = ConditionalBranch : r39_5
3183-
#-----| False -> Block 5
3184-
#-----| True (back edge) -> Block 4
3185-
3186-
# 38| Block 3
3187-
# 38| m38_1(unknown) = Phi : from 0:~m36_5, from 4:~m40_5
3188-
# 38| r38_2(int) = Constant[1] :
3189-
# 39| r39_7(int) = Constant[-1] :
3190-
# 39| r39_8(bool) = CompareEQ : r38_2, r39_7
3191-
# 39| v39_9(void) = ConditionalBranch : r39_8
3192-
#-----| False (back edge) -> Block 1
3188+
#-----| False -> Block 6
31933189
#-----| True -> Block 5
31943190

3195-
# 40| Block 4
3191+
# 38| Block 4
3192+
# 38| r38_1(int) = Constant[1] :
3193+
# 39| r39_7(int) = Constant[-1] :
3194+
# 39| r39_8(bool) = CompareEQ : r38_1, r39_7
3195+
# 39| v39_9(void) = ConditionalBranch : r39_8
3196+
#-----| False -> Block 2
3197+
#-----| True -> Block 6
3198+
3199+
# 40| Block 5
31963200
# 40| r40_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
31973201
# 40| r40_2(int) = Constant[1] :
31983202
# 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2
3199-
# 40| m40_4(unknown) = ^CallSideEffect : ~m38_1
3200-
# 40| m40_5(unknown) = Chi : total:m38_1, partial:m40_4
3201-
#-----| Exception (back edge) -> Block 3
3203+
# 40| m40_4(unknown) = ^CallSideEffect : ~m36_5
3204+
# 40| m40_5(unknown) = Chi : total:m36_5, partial:m40_4
3205+
#-----| Exception -> Block 1
32023206

3203-
# 32| Block 5
3204-
# 32| v32_5(void) = Unreached :
3207+
# 32| Block 6
3208+
# 32| v32_8(void) = Unreached :
32053209

32063210
# 44| void try_with_finally()
32073211
# 44| Block 0
@@ -3261,6 +3265,12 @@ ir.c:
32613265
# 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2
32623266
# 81| m81_4(unknown) = ^CallSideEffect : ~m80_4
32633267
# 81| m81_5(unknown) = Chi : total:m80_4, partial:m81_4
3268+
#-----| Exception -> Block 1
3269+
3270+
# 80| Block 1
3271+
# 80| v80_5(void) = Unwind :
3272+
# 80| v80_6(void) = AliasedUse : ~m81_5
3273+
# 80| v80_7(void) = ExitFunction :
32643274

32653275
ir.cpp:
32663276
# 1| void Constants()

cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,8 @@ sideEffectWithoutPrimary
88
instructionWithoutSuccessor
99
| ir.c:62:5:62:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
1010
| ir.c:73:5:73:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
11-
| ir.c:81:3:81:24 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:80:6:80:27 | void raise_access_violation() | void raise_access_violation() |
1211
ambiguousSuccessors
1312
unexplainedLoop
14-
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
15-
| ir.c:38:13:38:37 | Phi: 1 | Instruction 'Phi: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
16-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
17-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
18-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
19-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
20-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
21-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
22-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
23-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
24-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
25-
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
26-
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
27-
| ir.c:40:5:40:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
28-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
29-
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
3013
unnecessaryPhiInstruction
3114
memoryOperandDefinitionIsUnmodeled
3215
operandAcrossFunctions
@@ -37,9 +20,6 @@ containsLoopOfForwardEdges
3720
missingIRType
3821
multipleIRTypes
3922
lostReachability
40-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
41-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
42-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
4323
backEdgeCountMismatch
4424
useNotDominatedByDefinition
4525
switchInstructionWithoutDefaultEdge

0 commit comments

Comments
 (0)