mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Merge pull request #15936 from yoff/python/test-conflicting-summaries
Python: No `fieldFlowBranchLimit` for `SummarizedCallable`s
This commit is contained in:
@@ -22,4 +22,6 @@ module PythonDataFlow implements InputSig<Python::Location> {
|
||||
predicate neverSkipInPathGraph = Private::neverSkipInPathGraph/1;
|
||||
|
||||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
|
||||
predicate ignoreFieldFlowBranchLimit(DataFlowCallable c) { exists(c.asLibraryCallable()) }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
argumentToEnsureNotTaintedNotMarkedAsSpurious
|
||||
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,4 @@
|
||||
import python
|
||||
import experimental.meta.InlineTaintTest
|
||||
import MakeInlineTaintTest<TestTaintTrackingConfig>
|
||||
import TestSummaries
|
||||
@@ -136,3 +136,108 @@ private class SummarizedCallableJsonLoads extends SummarizedCallable {
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
// Repeated summaries
|
||||
private class SummarizedCallableWithSubpath extends SummarizedCallable {
|
||||
SummarizedCallableWithSubpath() { this = "extracted_package.functions.with_subpath" }
|
||||
|
||||
override DataFlow::CallCfgNode getACall() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("with_subpath")
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::ArgumentNode getACallback() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("with_subpath")
|
||||
.getAValueReachableFromSource()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue" and
|
||||
preservesValue = false
|
||||
}
|
||||
}
|
||||
|
||||
private class SummarizedCallableWithSubpathAgain extends SummarizedCallable {
|
||||
SummarizedCallableWithSubpathAgain() { this = "extracted_package.functions.with_subpathII" }
|
||||
|
||||
override DataFlow::CallCfgNode getACall() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("with_subpath")
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::ArgumentNode getACallback() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("with_subpath")
|
||||
.getAValueReachableFromSource()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue.Attribute[pattern]" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
private class SummarizedCallableWithoutSubpath extends SummarizedCallable {
|
||||
SummarizedCallableWithoutSubpath() { this = "extracted_package.functions.without_subpath" }
|
||||
|
||||
override DataFlow::CallCfgNode getACall() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("without_subpath")
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::ArgumentNode getACallback() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("without_subpath")
|
||||
.getAValueReachableFromSource()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue" and
|
||||
preservesValue = false
|
||||
}
|
||||
}
|
||||
|
||||
private class SummarizedCallableWithoutSubpathAgain extends SummarizedCallable {
|
||||
SummarizedCallableWithoutSubpathAgain() { this = "extracted_package.functions.without_subpathII" }
|
||||
|
||||
override DataFlow::CallCfgNode getACall() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("without_subpath")
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::ArgumentNode getACallback() {
|
||||
result =
|
||||
API::moduleImport("extracted_package")
|
||||
.getMember("functions")
|
||||
.getMember("without_subpath")
|
||||
.getAValueReachableFromSource()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue.Attribute[pattern]" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Bad interaction of two summaries for the same function
|
||||
ts = TAINTED_STRING
|
||||
|
||||
from extracted_package.functions import with_subpath, without_subpath
|
||||
|
||||
# For the function `with_subpath`, flow from the first argument to the return value
|
||||
# can be concluded from its definition. This seems to discard all summaries, including
|
||||
# the one with flow to `ReturnValue.Attribute[pattern]`.
|
||||
ensure_tainted(
|
||||
with_subpath(ts).pattern, # $ tainted
|
||||
with_subpath(ts), # $ tainted
|
||||
with_subpath(ts), # $ tainted
|
||||
)
|
||||
ensure_tainted(
|
||||
without_subpath(ts).pattern, # $ tainted
|
||||
without_subpath(ts), # $ tainted
|
||||
without_subpath(ts), # $ tainted
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
def with_subpath(x):
|
||||
return x
|
||||
|
||||
def without_subpath(x):
|
||||
pass
|
||||
Reference in New Issue
Block a user