Skip to content

Commit 2c0e9f0

Browse files
authored
Merge pull request #4186 from github/rc/1.25
Mergeback: 1.25 -> main
2 parents c017308 + 8e8c65a commit 2c0e9f0

File tree

72 files changed

+728
-420
lines changed

Some content is hidden

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

72 files changed

+728
-420
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ You can use the [interactive query console](https://lgtm.com/help/lgtm/using-que
99

1010
## Contributing
1111

12-
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
12+
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/main/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
1313

1414
## License
1515

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,25 @@ class Node extends TNode {
5050
/** Gets the type of this node. */
5151
Type getType() { none() } // overridden in subclasses
5252

53-
/** Gets the expression corresponding to this node, if any. */
53+
/**
54+
* Gets the expression corresponding to this node, if any. This predicate
55+
* only has a result on nodes that represent the value of evaluating the
56+
* expression. For data flowing _out of_ an expression, like when an
57+
* argument is passed by reference, use `asDefiningArgument` instead of
58+
* `asExpr`.
59+
*/
5460
Expr asExpr() { result = this.(ExprNode).getExpr() }
5561

5662
/** Gets the parameter corresponding to this node, if any. */
5763
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
5864

59-
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
65+
/**
66+
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
67+
* This predicate should be used instead of `asExpr` when referring to the
68+
* value of a reference argument _after_ the call has returned. For example,
69+
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
70+
* that represents the new value of `x`.
71+
*/
6072
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
6173

6274
/**
@@ -383,7 +395,9 @@ class PreConstructorInitThis extends Node, TPreConstructorInitThis {
383395
}
384396

385397
/**
386-
* Gets the `Node` corresponding to `e`.
398+
* Gets the `Node` corresponding to the value of evaluating `e`. For data
399+
* flowing _out of_ an expression, like when an argument is passed by
400+
* reference, use `definitionByReferenceNodeFromArgument` instead.
387401
*/
388402
ExprNode exprNode(Expr e) { result.getExpr() = e }
389403

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

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,25 @@ private module PartialDefinitions {
120120
)
121121
}
122122

123-
predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
123+
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
124124

125-
predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
125+
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
126126

127127
/**
128128
* Gets the subBasicBlock where this `PartialDefinition` is defined.
129129
*/
130130
ControlFlowNode getSubBasicBlockStart() { result = node }
131131

132+
/**
133+
* Holds if this `PartialDefinition` defines variable `v` at control-flow
134+
* node `cfn`.
135+
*/
136+
pragma[noinline]
137+
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
138+
innerDefinedExpr = v.getAnAccess() and
139+
cfn = node
140+
}
141+
132142
/**
133143
* Holds if this partial definition may modify `inner` (or what it points
134144
* to) through `outer`. These expressions will never be `Conversion`s.
@@ -188,7 +198,7 @@ module FlowVar_internal {
188198
predicate fullySupportedSsaVariable(Variable v) {
189199
v = any(SsaDefinition def).getAVariable() and
190200
// A partially-defined variable is handled using the partial definitions logic.
191-
not any(PartialDefinition p).partiallyDefines(v) and
201+
not any(PartialDefinition p).partiallyDefinesVariableAt(v, _) and
192202
// SSA variables do not exist before their first assignment, but one
193203
// feature of this data flow library is to track where uninitialized data
194204
// ends up.
@@ -232,7 +242,7 @@ module FlowVar_internal {
232242
or
233243
assignmentLikeOperation(sbb, v, _, _)
234244
or
235-
sbb = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
245+
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb))
236246
or
237247
blockVarDefinedByVariable(sbb, v)
238248
)
@@ -363,8 +373,7 @@ module FlowVar_internal {
363373

364374
override predicate definedPartiallyAt(Expr e) {
365375
exists(PartialDefinition p |
366-
p.partiallyDefines(v) and
367-
sbb = p.getSubBasicBlockStart() and
376+
p.partiallyDefinesVariableAt(v, sbb) and
368377
p.definesExpressions(_, e)
369378
)
370379
}
@@ -427,7 +436,7 @@ module FlowVar_internal {
427436
/**
428437
* Gets a variable that is assigned in this loop and read outside the loop.
429438
*/
430-
private Variable getARelevantVariable() {
439+
Variable getARelevantVariable() {
431440
result = this.getAVariableAssignedInLoop() and
432441
exists(VariableAccess va |
433442
va.getTarget() = result and
@@ -472,10 +481,16 @@ module FlowVar_internal {
472481
reachesWithoutAssignment(bb.getAPredecessor(), v) and
473482
this.bbInLoop(bb)
474483
) and
475-
not assignmentLikeOperation(bb.getANode(), v, _, _)
484+
not assignsToVar(bb, v)
476485
}
477486
}
478487

488+
pragma[noinline]
489+
private predicate assignsToVar(BasicBlock bb, Variable v) {
490+
assignmentLikeOperation(bb.getANode(), v, _, _) and
491+
exists(AlwaysTrueUponEntryLoop loop | v = loop.getARelevantVariable())
492+
}
493+
479494
/**
480495
* Holds if `loop` always assigns to `v` before leaving through an edge
481496
* from `bbInside` in its condition to `bbOutside` outside the loop. Also,
@@ -736,7 +751,7 @@ module FlowVar_internal {
736751
exists(Variable v | not fullySupportedSsaVariable(v) |
737752
assignmentLikeOperation(this, v, _, _)
738753
or
739-
this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
754+
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this))
740755
// It is not necessary to cut the basic blocks at `Initializer` nodes
741756
// because the affected variable can have no _other_ value before its
742757
// initializer. It is not necessary to cut basic blocks at procedure

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private DataFlow::Node getNodeForSource(Expr source) {
7070
//
7171
// This case goes together with the similar (but not identical) rule in
7272
// `nodeIsBarrierIn`.
73-
result = DataFlow::definitionByReferenceNode(source) and
73+
result = DataFlow::definitionByReferenceNodeFromArgument(source) and
7474
not argv(source.(VariableAccess).getTarget())
7575
)
7676
}
@@ -210,7 +210,7 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) {
210210
or
211211
// This case goes together with the similar (but not identical) rule in
212212
// `getNodeForSource`.
213-
node = DataFlow::definitionByReferenceNode(source)
213+
node = DataFlow::definitionByReferenceNodeFromArgument(source)
214214
)
215215
}
216216

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

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@ class Node extends TIRDataFlowNode {
4242
Operand asOperand() { result = this.(OperandNode).getOperand() }
4343

4444
/**
45-
* Gets the non-conversion expression corresponding to this node, if any. If
46-
* this node strictly (in the sense of `asConvertedExpr`) corresponds to a
47-
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
45+
* Gets the non-conversion expression corresponding to this node, if any.
46+
* This predicate only has a result on nodes that represent the value of
47+
* evaluating the expression. For data flowing _out of_ an expression, like
48+
* when an argument is passed by reference, use `asDefiningArgument` instead
49+
* of `asExpr`.
50+
*
51+
* If this node strictly (in the sense of `asConvertedExpr`) corresponds to
52+
* a `Conversion`, then the result is the underlying non-`Conversion` base
4853
* expression.
4954
*/
5055
Expr asExpr() { result = this.(ExprNode).getExpr() }
@@ -55,7 +60,13 @@ class Node extends TIRDataFlowNode {
5560
*/
5661
Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() }
5762

58-
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
63+
/**
64+
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
65+
* This predicate should be used instead of `asExpr` when referring to the
66+
* value of a reference argument _after_ the call has returned. For example,
67+
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
68+
* that represents the new value of `x`.
69+
*/
5970
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
6071

6172
/** Gets the positional parameter corresponding to this node, if any. */
@@ -378,7 +389,7 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
378389
class DefinitionByReferenceNode extends InstructionNode {
379390
override WriteSideEffectInstruction instr;
380391

381-
/** Gets the argument corresponding to this node. */
392+
/** Gets the unconverted argument corresponding to this node. */
382393
Expr getArgument() {
383394
result =
384395
instr
@@ -462,20 +473,26 @@ class VariableNode extends Node, TVariableNode {
462473
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
463474

464475
/**
476+
* DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
477+
*
465478
* Gets the `Node` corresponding to a definition by reference of the variable
466479
* that is passed as `argument` of a call.
467480
*/
468-
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
481+
deprecated DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
469482

470483
/**
471-
* Gets a `Node` corresponding to `e` or any of its conversions. There is no
472-
* result if `e` is a `Conversion`.
484+
* Gets the `Node` corresponding to the value of evaluating `e` or any of its
485+
* conversions. There is no result if `e` is a `Conversion`. For data flowing
486+
* _out of_ an expression, like when an argument is passed by reference, use
487+
* `definitionByReferenceNodeFromArgument` instead.
473488
*/
474489
ExprNode exprNode(Expr e) { result.getExpr() = e }
475490

476491
/**
477-
* Gets the `Node` corresponding to `e`, if any. Here, `e` may be a
478-
* `Conversion`.
492+
* Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may
493+
* be a `Conversion`. For data flowing _out of_ an expression, like when an
494+
* argument is passed by reference, use
495+
* `definitionByReferenceNodeFromArgument` instead.
479496
*/
480497
ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
481498

@@ -484,6 +501,14 @@ ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
484501
*/
485502
ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p }
486503

504+
/**
505+
* Gets the `Node` corresponding to a definition by reference of the variable
506+
* that is passed as unconverted `argument` of a call.
507+
*/
508+
DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
509+
result.getArgument() = argument
510+
}
511+
487512
/** Gets the `VariableNode` corresponding to the variable `v`. */
488513
VariableNode variableNode(Variable v) { result.getVariable() = v }
489514

docs/language/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ generates html slide shows in the ``<slides-output>`` directory when run from
103103
the ``ql-training`` source directory.
104104

105105
For more information about creating slides for QL training and variant analysis
106-
examples, see the `template slide deck <https://github.com/github/codeql/blob/master/docs/language/ql-training/template.rst>`__.
106+
examples, see the `template slide deck <https://github.com/github/codeql/blob/main/docs/language/ql-training/template.rst>`__.
107107

108108
Viewing the current version of the CodeQL documentation
109109
*******************************************************

docs/language/global-sphinx-files/_static/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)