mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge remote-tracking branch 'upstream/main' into mathiasvp/replace-ast-with-ir-use-usedataflow
This commit is contained in:
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -5,6 +5,7 @@ uniqueEnclosingCallable
|
||||
| C.cpp:10:20:10:29 | new | Node should have one enclosing callable but has 0. |
|
||||
| C.cpp:35:24:35:33 | 0 | Node should have one enclosing callable but has 0. |
|
||||
| C.cpp:35:24:35:33 | new | Node should have one enclosing callable but has 0. |
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -8,6 +8,7 @@ uniqueEnclosingCallable
|
||||
| misc.c:210:24:210:24 | 0 | Node should have one enclosing callable but has 0. |
|
||||
| misc.c:210:24:210:28 | ... + ... | Node should have one enclosing callable but has 0. |
|
||||
| misc.c:210:28:210:28 | 1 | Node should have one enclosing callable but has 0. |
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
| file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -2,6 +2,7 @@ import csharp
|
||||
import cil
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPublic
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowImplConsistency::Consistency
|
||||
|
||||
private class MyConsistencyConfiguration extends ConsistencyConfiguration {
|
||||
@@ -14,6 +15,15 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) {
|
||||
// TODO: Remove once static initializers are folded into the
|
||||
// static constructors
|
||||
exists(ControlFlow::Node cfn |
|
||||
cfn.getElement() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
|
||||
cfn = call.getControlFlowNode()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate uniqueNodeLocationExclude(Node n) {
|
||||
// Methods with multiple implementations
|
||||
n instanceof ParameterNode
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -64,7 +64,14 @@ newtype TParameterPosition =
|
||||
index = any(Parameter p).getPosition() + 1
|
||||
} or
|
||||
TSynthStarArgsElementParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or
|
||||
TDictSplatParameterPosition()
|
||||
TDictSplatParameterPosition() or
|
||||
// To get flow from a **kwargs argument to a keyword parameter, we add a read-step
|
||||
// from a synthetic **kwargs parameter. We need this separate synthetic ParameterNode,
|
||||
// since we clear content of the normal **kwargs parameter for the names that
|
||||
// correspond to normal keyword parameters. Since we cannot re-use the same parameter
|
||||
// position for multiple parameter nodes in the same callable, we introduce this
|
||||
// synthetic parameter position.
|
||||
TSynthDictSplatParameterPosition()
|
||||
|
||||
/** A parameter position. */
|
||||
class ParameterPosition extends TParameterPosition {
|
||||
@@ -92,6 +99,12 @@ class ParameterPosition extends TParameterPosition {
|
||||
/** Holds if this position represents a `**kwargs` parameter. */
|
||||
predicate isDictSplat() { this = TDictSplatParameterPosition() }
|
||||
|
||||
/**
|
||||
* Holds if this position represents a **synthetic** `**kwargs` parameter
|
||||
* (see comment for `TSynthDictSplatParameterPosition`).
|
||||
*/
|
||||
predicate isSynthDictSplat() { this = TSynthDictSplatParameterPosition() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
this.isSelf() and result = "self"
|
||||
@@ -108,6 +121,8 @@ class ParameterPosition extends TParameterPosition {
|
||||
)
|
||||
or
|
||||
this.isDictSplat() and result = "**"
|
||||
or
|
||||
this.isSynthDictSplat() and result = "synthetic **"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +194,8 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
)
|
||||
or
|
||||
ppos.isDictSplat() and apos.isDictSplat()
|
||||
or
|
||||
ppos.isSynthDictSplat() and apos.isDictSplat()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
@@ -324,16 +341,9 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction {
|
||||
)
|
||||
or
|
||||
// `**kwargs`
|
||||
// since the dataflow library has the restriction that we can only have ONE result per
|
||||
// parameter position, if there is both a synthetic **kwargs and a real **kwargs
|
||||
// parameter, we only give the result for the synthetic, and add local flow from the
|
||||
// synthetic to the real. It might seem more natural to do it in the other
|
||||
// direction, but since we have a clearStep on the real **kwargs parameter, we would have that
|
||||
// content-clearing would also affect the synthetic parameter, which we don't want.
|
||||
ppos.isDictSplat() and
|
||||
if exists(func.getArgByName(_))
|
||||
then result = TSynthDictSplatParameterNode(this)
|
||||
else result.getParameter() = func.getKwarg()
|
||||
ppos.isDictSplat() and result.getParameter() = func.getKwarg()
|
||||
or
|
||||
ppos.isSynthDictSplat() and result = TSynthDictSplatParameterNode(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1460,16 +1470,7 @@ class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition ppos) {
|
||||
sc = c.asLibraryCallable() and
|
||||
ppos = pos and
|
||||
// avoid overlap with `SynthDictSplatParameterNode`
|
||||
not (
|
||||
pos.isDictSplat() and
|
||||
exists(ParameterPosition keywordPos |
|
||||
FlowSummaryImpl::Private::summaryParameterNodeRange(sc, keywordPos) and
|
||||
keywordPos.isKeyword(_)
|
||||
)
|
||||
)
|
||||
sc = c.asLibraryCallable() and ppos = pos
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc }
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -182,11 +182,7 @@ private predicate synthDictSplatArgumentNodeStoreStep(
|
||||
private predicate dictSplatParameterNodeClearStep(ParameterNode n, DictionaryElementContent c) {
|
||||
exists(DataFlowCallable callable, ParameterPosition dictSplatPos, ParameterPosition keywordPos |
|
||||
dictSplatPos.isDictSplat() and
|
||||
(
|
||||
n.getParameter() = callable.(DataFlowFunction).getScope().getKwarg()
|
||||
or
|
||||
n = TSummaryParameterNode(callable.asLibraryCallable(), dictSplatPos)
|
||||
) and
|
||||
n = callable.getParameter(dictSplatPos) and
|
||||
exists(callable.getParameter(keywordPos)) and
|
||||
keywordPos.isKeyword(c.getKey())
|
||||
)
|
||||
@@ -237,28 +233,6 @@ class SynthDictSplatParameterNode extends ParameterNodeImpl, TSynthDictSplatPara
|
||||
override Parameter getParameter() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow step from the synthetic `**kwargs` parameter to the real `**kwargs` parameter.
|
||||
* Due to restriction in dataflow library, we can only give one of them as result for
|
||||
* `DataFlowCallable.getParameter`, so this is a workaround to ensure there is flow to
|
||||
* _both_ of them.
|
||||
*/
|
||||
private predicate dictSplatParameterNodeFlowStep(
|
||||
ParameterNodeImpl nodeFrom, ParameterNodeImpl nodeTo
|
||||
) {
|
||||
exists(DataFlowCallable callable |
|
||||
nodeFrom = TSynthDictSplatParameterNode(callable) and
|
||||
(
|
||||
nodeTo.getParameter() = callable.(DataFlowFunction).getScope().getKwarg()
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
nodeTo = TSummaryParameterNode(callable.asLibraryCallable(), pos) and
|
||||
pos.isDictSplat()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the synthetic **kwargs parameter to each keyword parameter.
|
||||
*/
|
||||
@@ -404,8 +378,6 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
simpleLocalFlowStepForTypetracking(nodeFrom, nodeTo)
|
||||
or
|
||||
summaryFlowSteps(nodeFrom, nodeTo)
|
||||
or
|
||||
dictSplatParameterNodeFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,15 +20,6 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
|
||||
n instanceof SynthDictSplatParameterNode
|
||||
}
|
||||
|
||||
override predicate uniqueParameterNodeAtPositionExclude(
|
||||
DataFlowCallable c, ParameterPosition pos, Node p
|
||||
) {
|
||||
// TODO: This can be removed once we solve the overlap of dictionary splat parameters
|
||||
c.getParameter(pos) = p and
|
||||
pos.isDictSplat() and
|
||||
not exists(p.getLocation().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override predicate uniqueParameterNodePositionExclude(
|
||||
DataFlowCallable c, ParameterPosition pos, Node p
|
||||
) {
|
||||
@@ -44,4 +35,8 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
|
||||
param = func.getArgByName(_)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) {
|
||||
not exists(call.getLocation().getFile().getRelativePath())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| new_cls_param.py:14:6:14:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:21:6:21:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:25:6:25:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:29:6:29:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| datamodel.py:71:6:71:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| datamodel.py:76:6:76:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,36 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| code/bound_method_arg.py:5:6:5:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/callable_as_argument.py:37:6:37:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/callable_as_argument.py:49:10:49:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_construction.py:13:6:13:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:9:6:9:13 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:11:9:11:32 | print() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:14:6:14:15 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:19:6:19:16 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:36:12:36:62 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:38:6:38:13 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:40:9:40:38 | print() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:10:6:10:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:14:6:14:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:104:6:104:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:108:6:108:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:112:6:112:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:116:6:116:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:120:6:120:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:149:6:149:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:153:6:153:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:13:6:13:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:28:6:28:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:36:6:36:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:40:6:40:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:17:18:17:41 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:18:18:18:40 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:38:11:38:21 | _gen() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:39:11:39:21 | _gen() | Call should have one enclosing callable but has 0. |
|
||||
| code/nested_class.py:3:10:3:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/nested_class.py:7:10:7:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/self_passing.py:60:6:60:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| test_captured.py:7:22:7:25 | p() | Call should have one enclosing callable but has 0. |
|
||||
| test_captured.py:7:22:7:25 | p() | Call should have one enclosing callable but has 0. |
|
||||
| test_captured.py:14:26:14:30 | pp() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,40 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| testapp/orm_form_test.py:7:12:7:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:30:13:30:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:34:25:34:56 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:35:33:35:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:39:21:39:52 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:40:33:40:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:118:13:118:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:122:25:122:56 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:123:33:123:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:127:21:127:52 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:128:33:128:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:16:12:16:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:17:11:17:31 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:93:12:93:65 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:112:12:112:65 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:29:12:29:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:43:12:43:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:59:12:59:61 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:74:12:74:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:90:12:90:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:111:12:111:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:127:12:127:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:128:13:128:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:145:12:145:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:146:13:146:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:162:12:162:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:178:12:178:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:181:12:181:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:207:12:207:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:208:12:208:70 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:234:12:234:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:235:12:235:95 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:256:12:256:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:274:12:274:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:295:12:295:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -443,6 +443,13 @@ private module Cached {
|
||||
FlowSummaryImplSpecific::ParsePositions::isParsedKeywordArgumentPosition(_, name)
|
||||
} or
|
||||
THashSplatParameterPosition() or
|
||||
// To get flow from a hash-splat argument to a keyword parameter, we add a read-step
|
||||
// from a synthetic hash-splat parameter. We need this separate synthetic ParameterNode,
|
||||
// since we clear content of the normal hash-splat parameter for the names that
|
||||
// correspond to normal keyword parameters. Since we cannot re-use the same parameter
|
||||
// position for multiple parameter nodes in the same callable, we introduce this
|
||||
// synthetic parameter position.
|
||||
TSynthHashSplatParameterPosition() or
|
||||
TSplatAllParameterPosition() or
|
||||
TAnyParameterPosition() or
|
||||
TAnyKeywordParameterPosition()
|
||||
@@ -1249,6 +1256,8 @@ class ParameterPosition extends TParameterPosition {
|
||||
/** Holds if this position represents a hash-splat parameter. */
|
||||
predicate isHashSplat() { this = THashSplatParameterPosition() }
|
||||
|
||||
predicate isSynthHashSplat() { this = TSynthHashSplatParameterPosition() }
|
||||
|
||||
predicate isSplatAll() { this = TSplatAllParameterPosition() }
|
||||
|
||||
/**
|
||||
@@ -1274,6 +1283,8 @@ class ParameterPosition extends TParameterPosition {
|
||||
or
|
||||
this.isHashSplat() and result = "**"
|
||||
or
|
||||
this.isSynthHashSplat() and result = "synthetic **"
|
||||
or
|
||||
this.isSplatAll() and result = "*"
|
||||
or
|
||||
this.isAny() and result = "any"
|
||||
@@ -1356,6 +1367,8 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
or
|
||||
ppos.isHashSplat() and apos.isHashSplat()
|
||||
or
|
||||
ppos.isSynthHashSplat() and apos.isHashSplat()
|
||||
or
|
||||
ppos.isSplatAll() and apos.isSplatAll()
|
||||
or
|
||||
ppos.isAny() and argumentPositionIsNotSelf(apos)
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
@@ -189,18 +189,6 @@ module LocalFlow {
|
||||
}
|
||||
|
||||
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
exists(DataFlowCallable c | nodeFrom = TSynthHashSplatParameterNode(c) |
|
||||
exists(HashSplatParameter p |
|
||||
p.getCallable() = c.asCallable() and
|
||||
nodeTo = TNormalParameterNode(p)
|
||||
)
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
nodeTo = TSummaryParameterNode(c.asLibraryCallable(), pos) and
|
||||
pos.isHashSplat()
|
||||
)
|
||||
)
|
||||
or
|
||||
localSsaFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
|
||||
@@ -648,9 +636,7 @@ private module ParameterNodes {
|
||||
)
|
||||
or
|
||||
parameter = callable.getAParameter().(HashSplatParameter) and
|
||||
pos.isHashSplat() and
|
||||
// avoid overlap with `SynthHashSplatParameterNode`
|
||||
not callable.getAParameter() instanceof KeywordParameter
|
||||
pos.isHashSplat()
|
||||
or
|
||||
parameter = callable.getParameter(0).(SplatParameter) and
|
||||
pos.isSplatAll()
|
||||
@@ -780,7 +766,7 @@ private module ParameterNodes {
|
||||
final override Parameter getParameter() { none() }
|
||||
|
||||
final override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
c = callable and pos.isHashSplat()
|
||||
c = callable and pos.isSynthHashSplat()
|
||||
}
|
||||
|
||||
final override CfgScope getCfgScope() { result = callable.asCallable() }
|
||||
@@ -802,16 +788,7 @@ private module ParameterNodes {
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
sc = c.asLibraryCallable() and
|
||||
pos = pos_ and
|
||||
// avoid overlap with `SynthHashSplatParameterNode`
|
||||
not (
|
||||
pos.isHashSplat() and
|
||||
exists(ParameterPosition keywordPos |
|
||||
FlowSummaryImpl::Private::summaryParameterNodeRange(sc, keywordPos) and
|
||||
keywordPos.isKeyword(_)
|
||||
)
|
||||
)
|
||||
sc = c.asLibraryCallable() and pos = pos_
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { none() }
|
||||
|
||||
@@ -18,6 +18,9 @@ module Consistency {
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
|
||||
predicate uniqueEnclosingCallableExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */
|
||||
predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
|
||||
predicate uniqueNodeLocationExclude(Node n) { none() }
|
||||
|
||||
@@ -86,6 +89,15 @@ module Consistency {
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) {
|
||||
exists(int c |
|
||||
c = count(call.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and
|
||||
msg = "Call should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
}
|
||||
|
||||
query predicate uniqueType(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
|
||||
Reference in New Issue
Block a user