зеркало из https://github.com/github/codeql.git
Swift: global dataflow WIP
This commit is contained in:
Родитель
bba3564187
Коммит
d326b3a91c
|
@ -64,6 +64,12 @@ module Ssa {
|
|||
a = bb.getNode(i).getNode().asAstNode() and
|
||||
value.getNode().asAstNode() = a.getSource()
|
||||
)
|
||||
or
|
||||
exists(VarDecl var, BasicBlock bb, int blockIndex, PatternBindingDecl pbd |
|
||||
this.definesAt(var, bb, blockIndex) and
|
||||
pbd.getAPattern() = bb.getNode(blockIndex).getNode() and
|
||||
value.getNode() = var.getParentInitializer()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
private import swift
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowPublic
|
||||
|
||||
newtype TReturnKind = TNormalReturnKind()
|
||||
|
||||
|
@ -42,47 +43,35 @@ class DataFlowCallable extends TDataFlowCallable {
|
|||
* A call. This includes calls from source code, as well as call(back)s
|
||||
* inside library callables with a flow summary.
|
||||
*/
|
||||
class DataFlowCall extends TDataFlowCall {
|
||||
class DataFlowCall extends ExprNode {
|
||||
DataFlowCall() {
|
||||
this.asExpr() instanceof CallExpr
|
||||
}
|
||||
|
||||
/** Gets the enclosing callable. */
|
||||
DataFlowCallable getEnclosingCallable() { none() }
|
||||
|
||||
/** Gets a textual representation of this call. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this call. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
newtype TDataFlowCallable = TODO_TDataFlowCallable()
|
||||
|
||||
cached
|
||||
newtype TDataFlowCall = TODO_TDataFlowCall()
|
||||
newtype TDataFlowCallable = TDataFlowFunc(FuncDecl func)
|
||||
|
||||
/** Gets a viable run-time target for the call `call`. */
|
||||
cached
|
||||
DataFlowCallable viableCallable(DataFlowCall call) { none() }
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
result = TDataFlowFunc(call.asExpr().(CallExpr).getStaticTarget())
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TArgumentPosition = TODO_TArgumentPosition()
|
||||
newtype TArgumentPosition =
|
||||
TThisArgument() or
|
||||
TPositionalArgument(int n) { n in [0 .. 100] } // we rely on default exprs generated in the caller for ordering. TODO: compute range properly. TODO: varargs?
|
||||
|
||||
cached
|
||||
newtype TParameterPosition = TODO_TParameterPosition()
|
||||
newtype TParameterPosition =
|
||||
TThisParameter() or
|
||||
TPositionalParameter(int n) { n in [0 .. 100] } // TODO: compute range properly
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
@ -111,6 +100,12 @@ class ArgumentPosition extends TArgumentPosition {
|
|||
string toString() { none() }
|
||||
}
|
||||
|
||||
class PositionalArgumentPosition extends ArgumentPosition, TPositionalArgument {
|
||||
int getIndex() {
|
||||
this = TPositionalArgument(result)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { none() }
|
||||
|
|
|
@ -31,12 +31,18 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
|
|||
override Location getLocationImpl() { result = expr.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = expr.toString() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(expr.getScope()) }
|
||||
}
|
||||
|
||||
private class SsaDefinitionNodeImpl extends SsaDefinitionNode, NodeImpl {
|
||||
override Location getLocationImpl() { result = def.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = def.toString() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result = TDataFlowFunc(def.getBasicBlock().getScope())
|
||||
}
|
||||
}
|
||||
|
||||
/** A collection of cached types and predicates to be evaluated in the same stage. */
|
||||
|
@ -103,7 +109,11 @@ private module ParameterNodes {
|
|||
override string toStringImpl() { result = param.toString() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
none() // TODO
|
||||
exists(FuncDecl f, int index |
|
||||
c = TDataFlowFunc(f) and
|
||||
f.getParam(index) = param and
|
||||
pos = TPositionalParameter(index)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +129,16 @@ abstract class ArgumentNode extends Node {
|
|||
final DataFlowCall getCall() { this.argumentOf(result, _) }
|
||||
}
|
||||
|
||||
private module ArgumentNodes { }
|
||||
private module ArgumentNodes {
|
||||
class NormalArgumentNode extends ExprNode, ArgumentNode {
|
||||
NormalArgumentNode() { exists(CallExpr call | call.getAnArgument().getExpr() = this.asExpr()) }
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
call.asExpr().(CallExpr).getArgument(pos.(PositionalArgumentPosition).getIndex()).getExpr() =
|
||||
this.asExpr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import ArgumentNodes
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class TestConfiguration extends DataFlow::Configuration {
|
||||
TestConfiguration() { this = "TestConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) {
|
||||
src.asExpr().(CallExpr).getStaticTarget().getName() = "source"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(CallExpr sinkCall |
|
||||
sinkCall.getStaticTarget().getName() = "sink" and
|
||||
sinkCall.getAnArgument() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override int explorationLimit() { result = 100 }
|
||||
}
|
||||
|
||||
from DataFlow::PartialPathNode src, DataFlow::PartialPathNode sink, TestConfiguration test
|
||||
where
|
||||
//test.isSource(src) and
|
||||
// test.isSink(sink) and
|
||||
//DataFlow::localFlow(src, sink)
|
||||
test.hasPartialFlow(src, sink, _)
|
||||
select src, sink
|
Загрузка…
Ссылка в новой задаче