forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Python: Add argument passing meta-queries (++)
and overall overview queries. Relies on points-to dataflow copy
- Loading branch information
Showing
8 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** Provides comparison of argument passing between type-tracking and points-to. */ | ||
|
||
import python | ||
|
||
module PointsToArgumentPassing { | ||
module DataFlow { | ||
import semmle.python.dataflow.new.internal_pt.DataFlowImpl | ||
} | ||
|
||
// import semmle.python.dataflow.new.internal_pt.DataFlowPrivate as DFP | ||
class PointsToArgumentPassingConfig extends DataFlow::Configuration { | ||
PointsToArgumentPassingConfig() { this = "PointsToArgumentPassingConfig" } | ||
|
||
override predicate isSource(DataFlow::Node node) { | ||
node instanceof DataFlow::ArgumentNode and | ||
exists(node.getLocation().getFile().getRelativePath()) | ||
} | ||
|
||
override predicate isSink(DataFlow::Node node) { | ||
node instanceof DataFlow::ParameterNode and | ||
exists(node.getLocation().getFile().getRelativePath()) | ||
} | ||
|
||
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } | ||
|
||
override predicate isBarrierOut(DataFlow::Node node) { this.isSink(node) } | ||
} | ||
|
||
predicate argumentPassing(ControlFlowNode arg, Parameter param) { | ||
exists(PointsToArgumentPassingConfig config | | ||
config | ||
.hasFlow(any(DataFlow::ArgumentNode node | node.asCfgNode() = arg), | ||
any(DataFlow::ParameterNode node | node.getParameter() = param)) | ||
) | ||
} | ||
} | ||
|
||
module TypeTrackingArgumentPassing { | ||
import semmle.python.dataflow.new.DataFlow | ||
|
||
class TypeTrackingArgumentPassingConfig extends DataFlow::Configuration { | ||
TypeTrackingArgumentPassingConfig() { this = "TypeTrackingArgumentPassingConfig" } | ||
|
||
override predicate isSource(DataFlow::Node node) { | ||
node instanceof DataFlow::ArgumentNode and | ||
exists(node.getLocation().getFile().getRelativePath()) | ||
} | ||
|
||
override predicate isSink(DataFlow::Node node) { | ||
node instanceof DataFlow::ParameterNode and | ||
exists(node.getLocation().getFile().getRelativePath()) | ||
} | ||
|
||
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } | ||
|
||
override predicate isBarrierOut(DataFlow::Node node) { this.isSink(node) } | ||
} | ||
|
||
predicate argumentPassing(ControlFlowNode arg, Parameter param) { | ||
exists(TypeTrackingArgumentPassingConfig config | | ||
config | ||
.hasFlow(any(DataFlow::ArgumentNode node | node.asCfgNode() = arg), | ||
any(DataFlow::ParameterNode node | node.getParameter() = param)) | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* @name arg->param edge from using type-tracking | ||
* @kind problem | ||
* @problem.severity recommendation | ||
* @id py/meta/arg-passing | ||
* @tags meta | ||
* @precision very-low | ||
*/ | ||
|
||
import python | ||
import ArgumentPassing | ||
|
||
from ControlFlowNode arg, Parameter param | ||
where TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
select arg, "$@ flow to $@", arg, "Argument", param, param.toString() |
17 changes: 17 additions & 0 deletions
17
python/ql/src/meta/analysis-quality/TTArgumentPassingMissing.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* @name Missing arg->param edge from using type-tracking instead of points-to | ||
* @kind problem | ||
* @problem.severity recommendation | ||
* @id py/meta/arg-passing-missing | ||
* @tags meta | ||
* @precision very-low | ||
*/ | ||
|
||
import python | ||
import ArgumentPassing | ||
|
||
from ControlFlowNode arg, Parameter param | ||
where | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
not TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
select arg, "MISSING: $@ flow to $@", arg, "Argument", param, param.toString() |
17 changes: 17 additions & 0 deletions
17
python/ql/src/meta/analysis-quality/TTArgumentPassingNew.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* @name New arg->param edge from using type-tracking instead of points-to | ||
* @kind problem | ||
* @problem.severity recommendation | ||
* @id py/meta/arg-passing-new | ||
* @tags meta | ||
* @precision very-low | ||
*/ | ||
|
||
import python | ||
import ArgumentPassing | ||
|
||
from ControlFlowNode arg, Parameter param | ||
where | ||
not PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
select arg, "NEW: $@ flow to $@", arg, "Argument", param, param.toString() |
31 changes: 31 additions & 0 deletions
31
python/ql/src/meta/analysis-quality/TTArgumentPassingOverview.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* @name arg->param edge from using type-tracking vs. points-to | ||
* @id py/meta/arg-passing-overview | ||
*/ | ||
|
||
import python | ||
import ArgumentPassing | ||
|
||
from string tag, int c | ||
where | ||
tag = "SHARED" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
or | ||
tag = "NEW" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
not PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
or | ||
tag = "MISSING" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
not TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
select tag, c |
17 changes: 17 additions & 0 deletions
17
python/ql/src/meta/analysis-quality/TTArgumentPassingShared.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* @name Shared arg->param edge from using type-tracking instead of points-to | ||
* @kind problem | ||
* @problem.severity recommendation | ||
* @id py/meta/arg-passing-shared | ||
* @tags meta | ||
* @precision very-low | ||
*/ | ||
|
||
import python | ||
import ArgumentPassing | ||
|
||
from ControlFlowNode arg, Parameter param | ||
where | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
select arg, "SHARED: $@ flow to $@", arg, "Argument", param, param.toString() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* @name Overview from using type-tracking instead of points-to, for both call-graph and | ||
* argument passing | ||
* @kind problem | ||
* @problem.severity recommendation | ||
* @id py/meta/type-tracking-overview | ||
* @precision very-low | ||
*/ | ||
|
||
import python | ||
import CallGraphQuality | ||
import ArgumentPassing | ||
|
||
/** Helper predicate to select a single valid AST node, otherwise MRVA will not show results. */ | ||
Location firsExprLocation() { | ||
result = | ||
min(Expr expr, Location loc | | ||
exists(loc.getFile().getRelativePath()) and | ||
loc = expr.getLocation() | ||
| | ||
loc | ||
order by | ||
loc.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), | ||
loc.getEndColumn() | ||
) | ||
} | ||
|
||
from string part, string tag, int c | ||
where | ||
part = "call-graph" and | ||
( | ||
tag = "SHARED" and | ||
c = | ||
count(CallNode call, Target target | | ||
target.isRelevant() and | ||
call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
) | ||
or | ||
tag = "NEW" and | ||
c = | ||
count(CallNode call, Target target | | ||
target.isRelevant() and | ||
not call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
) | ||
or | ||
tag = "MISSING" and | ||
c = | ||
count(CallNode call, Target target | | ||
target.isRelevant() and | ||
call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
not call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
) | ||
) | ||
or | ||
part = "argument-passing" and | ||
( | ||
tag = "SHARED" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
or | ||
tag = "NEW" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
not PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
or | ||
tag = "MISSING" and | ||
c = | ||
count(ControlFlowNode arg, Parameter param | | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
not TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
) | ||
) | ||
select firsExprLocation(), part + " | " + tag + " | " + c as msg order by msg desc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// this version can be run locally, which will allow you to dig into shared/missing/new | ||
// results without running a new query. (but does not work for MRVA). | ||
import python | ||
import CallGraphQuality | ||
import ArgumentPassing | ||
|
||
query predicate call_graph_shared(CallNode call, Target target) { | ||
target.isRelevant() and | ||
call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
} | ||
|
||
query predicate call_graph_new(CallNode call, Target target) { | ||
target.isRelevant() and | ||
not call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
} | ||
|
||
query predicate call_graph_missing(CallNode call, Target target) { | ||
target.isRelevant() and | ||
call.(PointsToBasedCallGraph::ResolvableCall).getTarget() = target and | ||
not call.(TypeTrackingBasedCallGraph::ResolvableCall).getTarget() = target | ||
} | ||
|
||
query predicate argument_passing_shared(ControlFlowNode arg, Parameter param) { | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
} | ||
|
||
query predicate argument_passing_new(ControlFlowNode arg, Parameter param) { | ||
not PointsToArgumentPassing::argumentPassing(arg, param) and | ||
TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
} | ||
|
||
query predicate argument_passing_missing(ControlFlowNode arg, Parameter param) { | ||
PointsToArgumentPassing::argumentPassing(arg, param) and | ||
not TypeTrackingArgumentPassing::argumentPassing(arg, param) | ||
} | ||
|
||
from string part, string tag, int c | ||
where | ||
part = "call-graph" and | ||
( | ||
tag = "SHARED" and | ||
c = count(CallNode call, Target target | call_graph_shared(call, target)) | ||
or | ||
tag = "NEW" and | ||
c = count(CallNode call, Target target | call_graph_new(call, target)) | ||
or | ||
tag = "MISSING" and | ||
c = count(CallNode call, Target target | call_graph_missing(call, target)) | ||
) | ||
or | ||
part = "argument-passing" and | ||
( | ||
tag = "SHARED" and | ||
c = count(ControlFlowNode arg, Parameter param | argument_passing_shared(arg, param)) | ||
or | ||
tag = "NEW" and | ||
c = count(ControlFlowNode arg, Parameter param | argument_passing_new(arg, param)) | ||
or | ||
tag = "MISSING" and | ||
c = count(ControlFlowNode arg, Parameter param | argument_passing_missing(arg, param)) | ||
) | ||
select part + " | " + tag as msg, c order by msg desc |