mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
103 lines
3.4 KiB
Plaintext
103 lines
3.4 KiB
Plaintext
/**
|
|
* Provides a simple base test for flow-related tests using inline expectations.
|
|
*
|
|
* Example for a test.ql:
|
|
* ```ql
|
|
* import java
|
|
* import TestUtilities.InlineFlowTest
|
|
* ```
|
|
*
|
|
* To declare expecations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
|
|
* Example of the corresponding test file, e.g. Test.java
|
|
* ```go
|
|
* public class Test {
|
|
*
|
|
* Object source() { return null; }
|
|
* String taint() { return null; }
|
|
* void sink(Object o) { }
|
|
*
|
|
* public void test() {
|
|
* Object s = source();
|
|
* sink(s); //$hasValueFlow
|
|
* String t = "foo" + taint();
|
|
* sink(t); //$hasTaintFlow
|
|
* }
|
|
*
|
|
* }
|
|
* ```
|
|
*
|
|
* If you're not interested in a specific flow type, you can disable either value or taint flow expectations as follows:
|
|
* ```ql
|
|
* class HasFlowTest extends InlineFlowTest {
|
|
* override DataFlow::Configuration getTaintFlowConfig() { none() }
|
|
*
|
|
* override DataFlow::Configuration getValueFlowConfig() { none() }
|
|
* }
|
|
* ```
|
|
*
|
|
* If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`.
|
|
*/
|
|
|
|
import go
|
|
import TestUtilities.InlineExpectationsTest
|
|
|
|
private predicate defaultSource(DataFlow::Node source) {
|
|
exists(Function fn | fn.hasQualifiedName(_, ["source", "taint"]) |
|
|
source = fn.getACall().getResult()
|
|
)
|
|
}
|
|
|
|
class DefaultValueFlowConf extends DataFlow::Configuration {
|
|
DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" }
|
|
|
|
override predicate isSource(DataFlow::Node source) { defaultSource(source) }
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument())
|
|
}
|
|
|
|
override int fieldFlowBranchLimit() { result = 1000 }
|
|
}
|
|
|
|
class DefaultTaintFlowConf extends TaintTracking::Configuration {
|
|
DefaultTaintFlowConf() { this = "qltest:defaultTaintFlowConf" }
|
|
|
|
override predicate isSource(DataFlow::Node source) { defaultSource(source) }
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument())
|
|
}
|
|
|
|
override int fieldFlowBranchLimit() { result = 1000 }
|
|
}
|
|
|
|
class InlineFlowTest extends InlineExpectationsTest {
|
|
InlineFlowTest() { this = "HasFlowTest" }
|
|
|
|
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
|
|
|
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
|
tag = "hasValueFlow" and
|
|
exists(DataFlow::Node sink | getValueFlowConfig().hasFlowTo(sink) |
|
|
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
|
|
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
|
|
element = sink.toString() and
|
|
value = "\"" + sink.toString() + "\""
|
|
)
|
|
or
|
|
tag = "hasTaintFlow" and
|
|
exists(DataFlow::Node src, DataFlow::Node sink |
|
|
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
|
|
|
|
|
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
|
|
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
|
|
element = sink.toString() and
|
|
value = "\"" + sink.toString() + "\""
|
|
)
|
|
}
|
|
|
|
DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) }
|
|
|
|
DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) }
|
|
}
|