mirror of
https://github.com/hohn/codeql-javascript-multiflow.git
synced 2025-12-16 20:03:04 +01:00
Add def-use code sample and query
This commit is contained in:
committed by
=Michael Hohn
parent
60ee4295b2
commit
bf9197cb57
36
cruft/snapshot-query-1
Executable file
36
cruft/snapshot-query-1
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage="Take a snapshot of the current session1.ql
|
||||
|
||||
Usage:
|
||||
$0 TheSnapShotName
|
||||
"
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
echo "$usage"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "-h" ]
|
||||
then
|
||||
echo "$usage"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
qname=$1
|
||||
# create the tests
|
||||
mkdir -p tests/$qname
|
||||
touch tests/$qname/$qname.expected
|
||||
echo $qname.ql > tests/$qname/$qname.qlref
|
||||
git add tests/$qname/$qname.expected
|
||||
git add tests/$qname/$qname.qlref
|
||||
|
||||
# snapshot the session
|
||||
cp sample-utility-0.js tests/$qname/
|
||||
git add tests/$qname/sample-utility-0.js
|
||||
|
||||
cp sample-utility-1.js tests/$qname/
|
||||
git add tests/$qname/sample-utility-1.js
|
||||
|
||||
cp session/session1.ql solutions/$qname.ql
|
||||
git add solutions/$qname.ql
|
||||
@@ -11,5 +11,6 @@ then
|
||||
fi
|
||||
mkdir -p tests
|
||||
mkdir -p solutions
|
||||
echo 'import javascript' > session.ql
|
||||
echo 'import javascript' > session/session.ql
|
||||
echo 'import javascript' > session/session1.ql
|
||||
|
||||
|
||||
80
solutions/DefUseSample.ql
Normal file
80
solutions/DefUseSample.ql
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @id javascript/example/multiflow
|
||||
*/
|
||||
|
||||
import javascript
|
||||
// XX: debug flow query
|
||||
// import semmle.javascript.explore.ForwardDataFlow
|
||||
import DataFlow::PathGraph
|
||||
|
||||
// Flow to consider:
|
||||
//
|
||||
// var value = this.getParameter('value'); //: source 1
|
||||
// var ua = new GR('status'); //: source 2
|
||||
// ua.setValue('status',value); //: taint step
|
||||
// ua.update(); //: sink (if from source 2)
|
||||
|
||||
// var value = this.getParameter('value'); //: source 1
|
||||
class ParameterSource extends CallExpr {
|
||||
ParameterSource() {
|
||||
exists(Expr inst |
|
||||
this.getCalleeName() = "getParameter" and
|
||||
(this.getReceiver().(ThisExpr) = inst or this.getReceiver().(Identifier) = inst)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ua.setValue('status',value); //: taint step
|
||||
predicate setValueTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(DotExpr temp, MethodCallExpr mce, VarAccess gr, VarAccess postgr |
|
||||
temp.getPropertyName() = "setValue" and
|
||||
mce.getReceiver() = temp.getBase() and
|
||||
gr = mce.getReceiver() and
|
||||
pred.asExpr() = mce.getArgument(1) and
|
||||
//
|
||||
// Taint all accesses after setValue call.
|
||||
// Trying data flow, this would be:
|
||||
// succ = gr.flow().getASuccessor+() and
|
||||
//
|
||||
// Using control flow:
|
||||
gr.getASuccessor+() = postgr and
|
||||
succ.asExpr() = postgr
|
||||
)
|
||||
}
|
||||
|
||||
// ua.update(); //: sink (if from source 2)
|
||||
DotExpr updateExpression() { result.getPropertyName() = "update" }
|
||||
|
||||
VarRef recordUpdate() { result = updateExpression().getBase() }
|
||||
|
||||
// var ua = new GR('status'); //: source 2
|
||||
class GR extends NewExpr {
|
||||
GR() { this.getCalleeName() = "GR" }
|
||||
}
|
||||
|
||||
class FromRequestToGrUpdate extends TaintTracking::Configuration {
|
||||
FromRequestToGrUpdate() { this = "FromRequestToGrUpdate" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(ParameterSource getParameter | source.asExpr() = getParameter)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
setValueTaintStep(pred, succ)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(VarRef grUpdate |
|
||||
sink.asExpr() = recordUpdate() and
|
||||
grUpdate = sink.asExpr() and
|
||||
grUpdate.getName() = "ua"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from FromRequestToGrUpdate dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where dataflow.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "Data flow from $@ to $@.", source, source.toString(), sink,
|
||||
sink.toString()
|
||||
30
tests/DefUseSample/DefUseSample.expected
Normal file
30
tests/DefUseSample/DefUseSample.expected
Normal file
@@ -0,0 +1,30 @@
|
||||
WARNING: Unused class GR (/Users/hohn/local/codeql-javascript-multiflow/solutions/DefUseSample.ql:53,7-9)
|
||||
nodes
|
||||
| sample-utility-0.js:5:6:5:39 | value |
|
||||
| sample-utility-0.js:5:14:5:39 | this.ge ... value') |
|
||||
| sample-utility-0.js:5:14:5:39 | this.ge ... value') |
|
||||
| sample-utility-0.js:17:27:17:31 | value |
|
||||
| sample-utility-0.js:18:6:18:7 | ua |
|
||||
| sample-utility-0.js:18:6:18:7 | ua |
|
||||
| sample-utility-1.js:2:9:2:42 | value |
|
||||
| sample-utility-1.js:2:17:2:42 | this.ge ... value') |
|
||||
| sample-utility-1.js:2:17:2:42 | this.ge ... value') |
|
||||
| sample-utility-1.js:14:23:14:27 | value |
|
||||
| sample-utility-1.js:15:2:15:3 | ua |
|
||||
| sample-utility-1.js:15:2:15:3 | ua |
|
||||
edges
|
||||
| sample-utility-0.js:5:6:5:39 | value | sample-utility-0.js:17:27:17:31 | value |
|
||||
| sample-utility-0.js:5:14:5:39 | this.ge ... value') | sample-utility-0.js:5:6:5:39 | value |
|
||||
| sample-utility-0.js:5:14:5:39 | this.ge ... value') | sample-utility-0.js:5:6:5:39 | value |
|
||||
| sample-utility-0.js:17:27:17:31 | value | sample-utility-0.js:17:27:17:31 | value |
|
||||
| sample-utility-0.js:17:27:17:31 | value | sample-utility-0.js:18:6:18:7 | ua |
|
||||
| sample-utility-0.js:17:27:17:31 | value | sample-utility-0.js:18:6:18:7 | ua |
|
||||
| sample-utility-1.js:2:9:2:42 | value | sample-utility-1.js:14:23:14:27 | value |
|
||||
| sample-utility-1.js:2:17:2:42 | this.ge ... value') | sample-utility-1.js:2:9:2:42 | value |
|
||||
| sample-utility-1.js:2:17:2:42 | this.ge ... value') | sample-utility-1.js:2:9:2:42 | value |
|
||||
| sample-utility-1.js:14:23:14:27 | value | sample-utility-1.js:14:23:14:27 | value |
|
||||
| sample-utility-1.js:14:23:14:27 | value | sample-utility-1.js:15:2:15:3 | ua |
|
||||
| sample-utility-1.js:14:23:14:27 | value | sample-utility-1.js:15:2:15:3 | ua |
|
||||
#select
|
||||
| sample-utility-0.js:18:6:18:7 | ua | sample-utility-0.js:5:14:5:39 | this.ge ... value') | sample-utility-0.js:18:6:18:7 | ua | Data flow from $@ to $@. | sample-utility-0.js:5:14:5:39 | this.ge ... value') | this.ge ... value') | sample-utility-0.js:18:6:18:7 | ua | ua |
|
||||
| sample-utility-1.js:15:2:15:3 | ua | sample-utility-1.js:2:17:2:42 | this.ge ... value') | sample-utility-1.js:15:2:15:3 | ua | Data flow from $@ to $@. | sample-utility-1.js:2:17:2:42 | this.ge ... value') | this.ge ... value') | sample-utility-1.js:15:2:15:3 | ua | ua |
|
||||
1
tests/DefUseSample/DefUseSample.qlref
Normal file
1
tests/DefUseSample/DefUseSample.qlref
Normal file
@@ -0,0 +1 @@
|
||||
DefUseSample.ql
|
||||
23
tests/DefUseSample/sample-utility-0.js
Normal file
23
tests/DefUseSample/sample-utility-0.js
Normal file
@@ -0,0 +1,23 @@
|
||||
var SampleUtility = function(){};
|
||||
SampleUtility.prototype = Object.extendsObject(Processor, {
|
||||
|
||||
setUserStatus: function() {
|
||||
var value = this.getParameter('value');
|
||||
|
||||
var ua = new GR('users');
|
||||
ua.query();
|
||||
|
||||
if(!ua.hasNext()){
|
||||
ua.initialize();
|
||||
ua.setValue('status',value);
|
||||
ua.insert();
|
||||
}
|
||||
else {
|
||||
ua.next();
|
||||
ua.setValue('status',value);
|
||||
ua.update();
|
||||
}
|
||||
},
|
||||
|
||||
type: 'SampleUtility'
|
||||
});
|
||||
17
tests/DefUseSample/sample-utility-1.js
Normal file
17
tests/DefUseSample/sample-utility-1.js
Normal file
@@ -0,0 +1,17 @@
|
||||
var SampleUtility = function() {
|
||||
var value = this.getParameter('value');
|
||||
|
||||
var ua = new GR('users');
|
||||
ua.query();
|
||||
|
||||
if(!ua.hasNext()){
|
||||
ua.initialize();
|
||||
ua.setValue('status',value);
|
||||
ua.insert();
|
||||
}
|
||||
else {
|
||||
ua.next();
|
||||
ua.setValue('status',value);
|
||||
ua.update();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user