Skip to content

Commit e0c027f

Browse files
authored
Merge pull request #14848 from hvitved/python/shared-type-tracking
Python: Adopt shared type tracking library
2 parents 41c49ae + a776132 commit e0c027f

File tree

24 files changed

+503
-731
lines changed

24 files changed

+503
-731
lines changed

config/identical-files.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,6 @@
454454
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
455455
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
456456
],
457-
"SummaryTypeTracker": [
458-
"python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll",
459-
"ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll"
460-
],
461457
"IncompleteUrlSubstringSanitization": [
462458
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
463459
"ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Python now makes use of the shared type tracking library, exposed as `semmle.python.dataflow.new.TypeTracking`. The existing type tracking library, `semmle.python.dataflow.new.TypeTracker`, has consequently been deprecated.

python/ql/lib/experimental/cryptography/utils/CallCfgNodeWithTarget.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
*/
55

66
import python
7-
private import semmle.python.dataflow.new.internal.TypeTrackerSpecific
7+
private import semmle.python.dataflow.new.internal.TypeTrackingImpl
88
private import semmle.python.ApiGraphs
99

1010
class CallCfgNodeWithTarget extends DataFlow::Node instanceof DataFlow::CallCfgNode {
11-
DataFlow::Node getTarget() { returnStep(result, this) }
11+
DataFlow::Node getTarget() { TypeTrackingInput::returnStep(result, this) }
1212
}

python/ql/lib/semmle/python/dataflow/new/TypeTracker.qll

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/**
2+
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
3+
*
24
* This file acts as a wrapper for `internal.TypeTracker`, exposing some of the functionality with
35
* names that are more appropriate for Python.
46
*/
@@ -8,12 +10,14 @@ private import internal.TypeTracker as Internal
810
private import internal.TypeTrackerSpecific as InternalSpecific
911

1012
/** A string that may appear as the name of an attribute or access path. */
11-
class AttributeName = InternalSpecific::TypeTrackerContent;
13+
deprecated class AttributeName = InternalSpecific::TypeTrackerContent;
1214

1315
/** An attribute name, or the empty string (representing no attribute). */
14-
class OptionalAttributeName = InternalSpecific::OptionalTypeTrackerContent;
16+
deprecated class OptionalAttributeName = InternalSpecific::OptionalTypeTrackerContent;
1517

1618
/**
19+
* DEPRECATED: Use `semmle.python.dataflow.new.TypeTracking` instead.
20+
*
1721
* The summary of the steps needed to track a value to a given dataflow node.
1822
*
1923
* This can be used to track objects that implement a certain API in order to
@@ -40,7 +44,7 @@ class OptionalAttributeName = InternalSpecific::OptionalTypeTrackerContent;
4044
* `t = t2.step(myType(t2), result)`. If you additionally want to track individual
4145
* intra-procedural steps, use `t = t2.smallstep(myCallback(t2), result)`.
4246
*/
43-
class TypeTracker extends Internal::TypeTracker {
47+
deprecated class TypeTracker extends Internal::TypeTracker {
4448
/**
4549
* Holds if this is the starting point of type tracking, and the value starts in the attribute named `attrName`.
4650
* The type tracking only ends after the attribute has been loaded.
@@ -55,12 +59,12 @@ class TypeTracker extends Internal::TypeTracker {
5559
string getAttr() { result = this.getContent() }
5660
}
5761

58-
module TypeTracker = Internal::TypeTracker;
62+
deprecated module TypeTracker = Internal::TypeTracker;
5963

60-
class StepSummary = Internal::StepSummary;
64+
deprecated class StepSummary = Internal::StepSummary;
6165

62-
module StepSummary = Internal::StepSummary;
66+
deprecated module StepSummary = Internal::StepSummary;
6367

64-
class TypeBackTracker = Internal::TypeBackTracker;
68+
deprecated class TypeBackTracker = Internal::TypeBackTracker;
6569

66-
module TypeBackTracker = Internal::TypeBackTracker;
70+
deprecated module TypeBackTracker = Internal::TypeBackTracker;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Provides classes and predicates for simple data-flow reachability suitable
3+
* for tracking types.
4+
*/
5+
6+
private import internal.TypeTrackingImpl as Impl
7+
import Impl::Shared::TypeTracking<Impl::TypeTrackingInput>
8+
9+
/** A string that may appear as the name of an attribute or access path. */
10+
class AttributeName = Impl::TypeTrackingInput::Content;
11+
12+
/**
13+
* A summary of the steps needed to track a value to a given dataflow node.
14+
*
15+
* This can be used to track objects that implement a certain API in order to
16+
* recognize calls to that API. Note that type-tracking does not by itself provide a
17+
* source/sink relation, that is, it may determine that a node has a given type,
18+
* but it won't determine where that type came from.
19+
*
20+
* It is recommended that all uses of this type are written in the following form,
21+
* for tracking some type `myType`:
22+
* ```ql
23+
* Node myType(TypeTracker tt) {
24+
* tt.start() and
25+
* result = < source of myType >
26+
* or
27+
* exists(TypeTracker tt2 |
28+
* tt = tt2.step(myType(tt2), result)
29+
* )
30+
* }
31+
*
32+
* Node myType() { myType(TypeTracker::end()).flowsTo(result) }
33+
* ```
34+
*
35+
* If you want to track individual intra-procedural steps, use `tt2.smallstep`
36+
* instead of `tt2.step`.
37+
*/
38+
class TypeTracker extends Impl::TypeTracker {
39+
/**
40+
* Holds if this is the starting point of type tracking, and the value starts in the attribute named `attrName`.
41+
* The type tracking only ends after the attribute has been loaded.
42+
*/
43+
predicate startInAttr(string attrName) { this.startInContent(attrName) }
44+
45+
/**
46+
* INTERNAL. DO NOT USE.
47+
*
48+
* Gets the attribute associated with this type tracker.
49+
*/
50+
string getAttr() {
51+
result = this.getContent().asSome()
52+
or
53+
this.getContent().isNone() and
54+
result = ""
55+
}
56+
}

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ private import DataFlowPublic
3737
private import DataFlowPrivate
3838
private import FlowSummaryImpl as FlowSummaryImpl
3939
private import semmle.python.internal.CachedStages
40-
private import semmle.python.dataflow.new.internal.TypeTracker::CallGraphConstruction as CallGraphConstruction
40+
private import semmle.python.dataflow.new.internal.TypeTrackingImpl::CallGraphConstruction as CallGraphConstruction
4141

4242
newtype TParameterPosition =
4343
/** Used for `self` in methods, and `cls` in classmethods. */

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
private import python
66
private import DataFlowPrivate
7-
import semmle.python.dataflow.new.TypeTracker
7+
import semmle.python.dataflow.new.TypeTracking
88
import Attributes
99
import LocalSources
1010
private import semmle.python.essa.SsaCompute

python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
private import python
88
private import semmle.python.dataflow.new.DataFlow
99
private import semmle.python.dataflow.new.internal.ImportStar
10-
private import semmle.python.dataflow.new.TypeTracker
10+
private import semmle.python.dataflow.new.TypeTracking
1111
private import semmle.python.dataflow.new.internal.DataFlowPrivate
1212

1313
/**

python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class LocalSourceNode extends Node {
7272
// We include all scope entry definitions, as these act as the local source within the scope they
7373
// enter.
7474
this.asCfgNode() = any(ScopeEntryDefinition def).getDefiningNode()
75+
or
76+
this instanceof ParameterNode
7577
}
7678

7779
/** Holds if this `LocalSourceNode` can flow to `nodeTo` in one or more local flow steps. */
@@ -151,7 +153,7 @@ class LocalSourceNode extends Node {
151153
* See `TypeBackTracker` for more details about how to use this.
152154
*/
153155
pragma[inline]
154-
LocalSourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t2 = t.step(result, this) }
156+
LocalSourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t = t2.step(result, this) }
155157
}
156158

157159
/**
@@ -238,7 +240,7 @@ private module Cached {
238240
* Helper predicate for `hasLocalSource`. Removes any steps go to module variable reads, as these
239241
* are already local source nodes in their own right.
240242
*/
241-
cached
243+
pragma[nomagic]
242244
private predicate localSourceFlowStep(Node nodeFrom, Node nodeTo) {
243245
simpleLocalFlowStep(nodeFrom, nodeTo) and
244246
not nodeTo = any(ModuleVariableNode v).getARead()

0 commit comments

Comments
 (0)