Skip to content

Commit 028e61b

Browse files
authored
Merge pull request #1101 from robertbrignull/merge/rc/1.20
Merge rc/1.20 => master
2 parents 08d852f + 5380e1d commit 028e61b

File tree

68 files changed

+16345
-600
lines changed

Some content is hidden

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

68 files changed

+16345
-600
lines changed

change-notes/1.20/analysis-cpp.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,39 @@
88

99
| **Query** | **Tags** | **Purpose** |
1010
|-----------------------------|-----------|--------------------------------------------------------------------|
11-
| Use of string copy function in a condition (`cpp/string-copy-return-value-as-boolean`) | correctness | This query identifies calls to string copy functions used in conditions, where it's likely that a different function was intended to be called. |
12-
| Lossy function result cast (`cpp/lossy-function-result-cast`) | correctness | Finds function calls whose result type is a floating point type, which are implicitly cast to an integral type. Newly available but not displayed by default on LGTM. |
1311
| Array argument size mismatch (`cpp/array-arg-size-mismatch`) | reliability | Finds function calls where the size of an array being passed is smaller than the array size of the declared parameter. Newly displayed on LGTM. |
14-
| Returning stack-allocated memory (`cpp/return-stack-allocated-memory`) | reliability, external/cwe/cwe-825 | Finds functions that may return a pointer or reference to stack-allocated memory. This query existed already but has been rewritten from scratch to make the error rate low enough for use on LGTM. Displayed by default. |
12+
| Lossy function result cast (`cpp/lossy-function-result-cast`) | correctness | Finds function calls whose result type is a floating point type, which are implicitly cast to an integral type. Newly available on LGTM but results not displayed by default. |
13+
| Returning stack-allocated memory (`cpp/return-stack-allocated-memory`) | reliability, external/cwe/cwe-825 | Finds functions that may return a pointer or reference to stack-allocated memory. This query existed already but has been rewritten from scratch to make the error rate low enough for use on LGTM. Results displayed by default. |
14+
| Use of string copy function in a condition (`cpp/string-copy-return-value-as-boolean`) | correctness | This query identifies calls to string copy functions used in conditions, where it's likely that a different function was intended to be called. Results are displayed by default on LGTM. |
1515

1616
## Changes to existing queries
1717

1818
| **Query** | **Expected impact** | **Change** |
1919
|----------------------------|------------------------|------------------------------------------------------------------|
20-
| Array argument size mismatch (`cpp/array-arg-size-mismatch`) | Fewer false positives | An exception has been added to this query for variable sized arrays. |
20+
| Array argument size mismatch (`cpp/array-arg-size-mismatch`) | Fewer false positive results | An exception has been added to this query for variable sized arrays. |
2121
| Call to memory access function may overflow buffer (`cpp/overflow-buffer`) | More correct results | This query now recognizes calls to `RtlCopyMemoryNonTemporal` and `RtlSecureZeroMemory`. |
22-
| Returning stack-allocated memory (`cpp/return-stack-allocated-memory`) | More correct results | Many more stack allocated expressions are now recognized. |
23-
| Suspicious add with sizeof (`cpp/suspicious-add-sizeof`) | Fewer false positives | Pointer arithmetic on `char * const` expressions (and other variations of `char *`) are now correctly excluded from the results. |
24-
| Suspicious pointer scaling (`cpp/suspicious-pointer-scaling`) | Fewer false positives | False positives involving types that are not uniquely named in the snapshot have been fixed. |
2522
| Call to memory access function may overflow buffer (`cpp/overflow-buffer`) | More correct results | Calls to `fread` are now examined by this query. |
2623
| Lossy function result cast (`cpp/lossy-function-result-cast`) | Fewer false positive results | The whitelist of rounding functions built into this query has been expanded. |
2724
| Memory is never freed (`cpp/memory-never-freed`) | More correct results | Support for more Microsoft-specific memory allocation/de-allocation functions has been added. |
2825
| Memory may not be freed (`cpp/memory-may-not-be-freed`) | More correct results | Support for more Microsoft-specific memory allocation/de-allocation functions has been added. |
29-
| Unused static variable (`cpp/unused-static-variable`) | Fewer false positive results | Variables with the attribute `unused` are now excluded from the query. |
30-
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | Fix false positives where a resource is released via a virtual method call, function pointer, or lambda. |
26+
| Mismatching new/free or malloc/delete (`cpp/new-free-mismatch`) | More correct results | Data flow through global variables for this query has been improved. |
3127
| 'new[]' array freed with 'delete' (`cpp/new-array-delete-mismatch`) | More correct results | Data flow through global variables for this query has been improved. |
3228
| 'new' object freed with 'delete[]' (`cpp/new-delete-array-mismatch`) | More correct results | Data flow through global variables for this query has been improved. |
33-
| Mismatching new/free or malloc/delete (`cpp/new-free-mismatch`) | More correct results | Data flow through global variables for this query has been improved. |
29+
| Potential buffer overflow (`cpp/potential-buffer-overflow`) | Deprecated | This query has been deprecated. Use Potentially overrunning write (`cpp/overrunning-write`) and Potentially overrunning write with float to string conversion (`cpp/overrunning-write-with-float`) instead. |
30+
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | The query no longer highlights code that releases a resource via a virtual method call, function pointer, or lambda. |
31+
| Returning stack-allocated memory (`cpp/return-stack-allocated-memory`) | More correct results | Many more stack allocated expressions are now recognized. |
32+
| Suspicious add with sizeof (`cpp/suspicious-add-sizeof`) | Fewer false positive results | Pointer arithmetic on `char * const` expressions (and other variations of `char *`) are now correctly excluded from the results. |
33+
| Suspicious pointer scaling (`cpp/suspicious-pointer-scaling`) | Fewer false positive results | False positive results involving types that are not uniquely named in the snapshot have been fixed. |
34+
| Unused static variable (`cpp/unused-static-variable`) | Fewer false positive results | Variables with the attribute `unused` are now excluded from the query. |
3435
| Use of inherently dangerous function (`cpp/potential-buffer-overflow`) | Cleaned up | This query no longer catches uses of `gets`, and has been renamed 'Potential buffer overflow'. |
3536
| Use of potentially dangerous function (`cpp/potentially-dangerous-function`) | More correct results | This query now catches uses of `gets`. |
36-
| Potential buffer overflow (`cpp/potential-buffer-overflow`) | Deprecated | This query has been deprecated. Use Potentially overrunning write (`cpp/overrunning-write`) and Potentially overrunning write with float to string conversion (`cpp/overrunning-write-with-float`) instead. |
37+
3738

3839
## Changes to QL libraries
3940

4041
* The `semmle.code.cpp.dataflow.DataFlow` library now supports _definition by reference_ via output parameters of known functions.
4142
* Data flows through `memcpy` and `memmove` by default.
42-
* Custom flow into or out of arguments assigned by reference can be modelled with the new class `DataFlow::DefinitionByReferenceNode`.
43+
* Custom flow into or out of arguments assigned by reference can be modeled with the new class `DataFlow::DefinitionByReferenceNode`.
4344
* The data flow library adds flow through library functions that are modeled in `semmle.code.cpp.models.interfaces.DataFlow`. Queries can add subclasses of `DataFlowFunction` to specify additional flow.
4445
* There is a new `Namespace.isInline()` predicate, which holds if the namespace was declared as `inline namespace`.
4546
* The `Expr.isConstant()` predicate now also holds for _address constant expressions_, which are addresses that will be constant after the program has been linked. These address constants do not have a result for `Expr.getValue()`.

config/identical-files.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
3636
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
3737
],
38-
"C++ IR FunctionIR": [
39-
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/FunctionIR.qll",
40-
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/FunctionIR.qll",
41-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/FunctionIR.qll"
38+
"C++ IR IRFunction": [
39+
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRFunction.qll",
40+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll",
41+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll"
4242
],
4343
"C++ IR Operand": [
4444
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll",

cpp/ql/src/Critical/NewDelete.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ private predicate allocReaches0(Expr e, Expr alloc, string kind) {
8080
) or exists(Variable v |
8181
// alloc via a global
8282
allocReachesVariable(v, alloc, kind) and
83+
strictcount(VariableAccess va | va.getTarget() = v) <= 50 and // avoid very expensive cases
8384
e.(VariableAccess).getTarget() = v
8485
)
8586
}

cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,8 @@ module FlowVar_internal {
237237

238238
override VariableAccess getAnAccess() {
239239
exists(SubBasicBlock reached |
240-
reached = getAReachedBlockVarSBB(this)
241-
|
240+
reached = getAReachedBlockVarSBB(this) and
242241
variableAccessInSBB(v, reached, result)
243-
or
244-
// Allow flow into a `VariableAccess` that is used as definition by
245-
// reference. This flow is blocked by `getAReachedBlockVarSBB` because
246-
// flow should not propagate past that.
247-
result = reached.getASuccessor().(VariableAccess) and
248-
blockVarDefinedByReference(result, v, _)
249242
)
250243
}
251244

@@ -420,6 +413,12 @@ module FlowVar_internal {
420413
va.getTarget() = v and
421414
va = sbb.getANode() and
422415
not overwrite(va, _)
416+
or
417+
// Allow flow into a `VariableAccess` that is used as definition by
418+
// reference. This flow is blocked by `getAReachedBlockVarSBB` because
419+
// flow should not propagate past that.
420+
va = sbb.getASuccessor().(VariableAccess) and
421+
blockVarDefinedByReference(va, v, _)
423422
}
424423

425424
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import FunctionIR
1+
import IRFunction
22
import Instruction
33
import IRBlock
44
import IRVariable

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ class IRBlockBase extends TIRBlock {
6363
result = getInstructionCount(this)
6464
}
6565

66-
final FunctionIR getEnclosingFunctionIR() {
67-
result = getFirstInstruction(this).getEnclosingFunctionIR()
66+
final IRFunction getEnclosingIRFunction() {
67+
result = getFirstInstruction(this).getEnclosingIRFunction()
6868
}
6969

7070
final Function getEnclosingFunction() {
@@ -116,7 +116,7 @@ class IRBlock extends IRBlockBase {
116116
* Holds if this block is reachable from the entry point of its function
117117
*/
118118
final predicate isReachableFromFunctionEntry() {
119-
this = getEnclosingFunctionIR().getEntryBlock() or
119+
this = getEnclosingIRFunction().getEntryBlock() or
120120
getAPredecessor().isReachableFromFunctionEntry()
121121
}
122122
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/FunctionIR.qll renamed to cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ private import internal.IRInternal
22
import Instruction
33
import cpp
44

5-
private newtype TFunctionIR =
6-
MkFunctionIR(Function func) {
5+
private newtype TIRFunction =
6+
MkIRFunction(Function func) {
77
Construction::functionHasIR(func)
88
}
99

1010
/**
1111
* Represents the IR for a function.
1212
*/
13-
class FunctionIR extends TFunctionIR {
13+
class IRFunction extends TIRFunction {
1414
Function func;
1515

16-
FunctionIR() {
17-
this = MkFunctionIR(func)
16+
IRFunction() {
17+
this = MkIRFunction(func)
1818
}
1919

2020
final string toString() {
@@ -40,33 +40,33 @@ class FunctionIR extends TFunctionIR {
4040
*/
4141
pragma[noinline]
4242
final EnterFunctionInstruction getEnterFunctionInstruction() {
43-
result.getEnclosingFunctionIR() = this
43+
result.getEnclosingIRFunction() = this
4444
}
4545

4646
/**
4747
* Gets the exit point for this function.
4848
*/
4949
pragma[noinline]
5050
final ExitFunctionInstruction getExitFunctionInstruction() {
51-
result.getEnclosingFunctionIR() = this
51+
result.getEnclosingIRFunction() = this
5252
}
5353

5454
pragma[noinline]
5555
final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() {
56-
result.getEnclosingFunctionIR() = this
56+
result.getEnclosingIRFunction() = this
5757
}
5858

5959
pragma[noinline]
6060
final UnmodeledUseInstruction getUnmodeledUseInstruction() {
61-
result.getEnclosingFunctionIR() = this
61+
result.getEnclosingIRFunction() = this
6262
}
6363

6464
/**
6565
* Gets the single return instruction for this function.
6666
*/
6767
pragma[noinline]
6868
final ReturnInstruction getReturnInstruction() {
69-
result.getEnclosingFunctionIR() = this
69+
result.getEnclosingIRFunction() = this
7070
}
7171

7272
/**
@@ -75,7 +75,7 @@ class FunctionIR extends TFunctionIR {
7575
*/
7676
pragma[noinline]
7777
final IRReturnVariable getReturnVariable() {
78-
result.getEnclosingFunctionIR() = this
78+
result.getEnclosingIRFunction() = this
7979
}
8080

8181
/**
@@ -90,13 +90,13 @@ class FunctionIR extends TFunctionIR {
9090
* Gets all instructions in this function.
9191
*/
9292
final Instruction getAnInstruction() {
93-
result.getEnclosingFunctionIR() = this
93+
result.getEnclosingIRFunction() = this
9494
}
9595

9696
/**
9797
* Gets all blocks in this function.
9898
*/
9999
final IRBlock getABlock() {
100-
result.getEnclosingFunctionIR() = this
100+
result.getEnclosingIRFunction() = this
101101
}
102102
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
private import internal.IRInternal
2-
import FunctionIR
2+
import IRFunction
33
import cpp
44
import semmle.code.cpp.ir.implementation.TempVariableTag
55
private import semmle.code.cpp.ir.internal.IRUtilities
@@ -48,7 +48,7 @@ abstract class IRVariable extends TIRVariable {
4848
/**
4949
* Gets the IR for the function that references this variable.
5050
*/
51-
final FunctionIR getEnclosingFunctionIR() {
51+
final IRFunction getEnclosingIRFunction() {
5252
result.getFunction() = func
5353
}
5454

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
private import internal.IRInternal
2-
import FunctionIR
2+
import IRFunction
33
import IRBlock
44
import IRVariable
55
import Operand
@@ -15,7 +15,7 @@ module InstructionSanity {
1515
/**
1616
* Holds if the instruction `instr` should be expected to have an operand
1717
* with operand tag `tag`. Only holds for singleton operand tags. Tags with
18-
* parameters, such as `PhiOperand` and `PositionalArgumentOperand` are handled
18+
* parameters, such as `PhiInputOperand` and `PositionalArgumentOperand` are handled
1919
* separately in `unexpectedOperand`.
2020
*/
2121
private predicate expectsOperand(Instruction instr, OperandTag tag) {
@@ -87,7 +87,7 @@ module InstructionSanity {
8787
*/
8888
query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) {
8989
pred = instr.getBlock().getAPredecessor() and
90-
not exists(PhiOperand operand |
90+
not exists(PhiInputOperand operand |
9191
operand = instr.getAnOperand() and
9292
operand.getPredecessorBlock() = pred
9393
)
@@ -153,7 +153,7 @@ module InstructionSanity {
153153
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
154154
operand.getUseInstruction() = instr and
155155
operand.getDefinitionInstruction() = defInstr and
156-
instr.getEnclosingFunctionIR() != defInstr.getEnclosingFunctionIR()
156+
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
157157
}
158158

159159
/**
@@ -174,10 +174,10 @@ module InstructionSanity {
174174
*
175175
* This check ensures we don't have too _few_ back edges.
176176
*/
177-
query predicate containsLoopOfForwardEdges(FunctionIR f) {
177+
query predicate containsLoopOfForwardEdges(IRFunction f) {
178178
exists(IRBlock block |
179179
forwardEdge+(block, block) and
180-
block.getEnclosingFunctionIR() = f
180+
block.getEnclosingIRFunction() = f
181181
)
182182
}
183183

@@ -190,7 +190,7 @@ module InstructionSanity {
190190
* This check ensures we don't have too _many_ back edges.
191191
*/
192192
query predicate lostReachability(IRBlock block) {
193-
exists(FunctionIR f, IRBlock entry |
193+
exists(IRFunction f, IRBlock entry |
194194
entry = f.getEntryBlock() and
195195
entry.getASuccessor+() = block and
196196
not forwardEdge+(entry, block) and
@@ -373,14 +373,14 @@ class Instruction extends Construction::TInstruction {
373373
* Gets the function that contains this instruction.
374374
*/
375375
final Function getEnclosingFunction() {
376-
result = getEnclosingFunctionIR().getFunction()
376+
result = getEnclosingIRFunction().getFunction()
377377
}
378378

379379
/**
380-
* Gets the FunctionIR object that contains the IR for this instruction.
380+
* Gets the IRFunction object that contains the IR for this instruction.
381381
*/
382-
final FunctionIR getEnclosingFunctionIR() {
383-
result = Construction::getInstructionEnclosingFunctionIR(this)
382+
final IRFunction getEnclosingIRFunction() {
383+
result = Construction::getInstructionEnclosingIRFunction(this)
384384
}
385385

386386
/**
@@ -1622,15 +1622,22 @@ class PhiInstruction extends Instruction {
16221622
result instanceof PhiMemoryAccess
16231623
}
16241624

1625+
/**
1626+
* Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block.
1627+
*/
1628+
final PhiInputOperand getAnInputOperand() {
1629+
result = this.getAnOperand()
1630+
}
1631+
16251632
/**
16261633
* Gets an instruction that defines the input to one of the operands of this
16271634
* instruction. It's possible for more than one operand to have the same
16281635
* defining instruction, so this predicate will have the same number of
1629-
* results as `getAnOperand()` or fewer.
1636+
* results as `getAnInputOperand()` or fewer.
16301637
*/
16311638
pragma[noinline]
1632-
final Instruction getAnOperandDefinitionInstruction() {
1633-
result = this.getAnOperand().(PhiOperand).getDefinitionInstruction()
1639+
final Instruction getAnInput() {
1640+
result = this.getAnInputOperand().getDefinitionInstruction()
16341641
}
16351642
}
16361643

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class Operand extends TOperand {
2525
result = getUseInstruction().getLocation()
2626
}
2727

28-
final FunctionIR getEnclosingFunctionIR() {
29-
result = getUseInstruction().getEnclosingFunctionIR()
28+
final IRFunction getEnclosingIRFunction() {
29+
result = getUseInstruction().getEnclosingIRFunction()
3030
}
3131

3232
/**
@@ -379,12 +379,12 @@ class SideEffectOperand extends TypedOperand {
379379
/**
380380
* An operand of a `PhiInstruction`.
381381
*/
382-
class PhiOperand extends MemoryOperand, TPhiOperand {
382+
class PhiInputOperand extends MemoryOperand, TPhiOperand {
383383
PhiInstruction useInstr;
384384
Instruction defInstr;
385385
IRBlock predecessorBlock;
386386

387-
PhiOperand() {
387+
PhiInputOperand() {
388388
this = TPhiOperand(useInstr, defInstr, predecessorBlock)
389389
}
390390

0 commit comments

Comments
 (0)