Files
codeql/python/ql/test/library-tests/dataflow/tainttracking/TestTaintLib.qll
yoff de7744950f Python: migrate remaining tests off getAFlowNode() and fix star-import SSA step
Sweep the last few uses of legacy AstNode.getAFlowNode() in tests over to
explicit ControlFlowNode joins after the shared-CFG migration. importflow.ql
needs the new Cfg::ControlFlowNode/CompareNode types because DataFlow::Node.
asCfgNode() now returns the shared-CFG node.

Also extend ImportResolution::allowedEssaImportStep to walk back through
uncertain-write SSA inputs, so that a later 'from X import *' does not hide
the preceding explicit (re)assignment from module-export resolution. Without
this, a reassigned name that survives a wildcard import was no longer
recognised as the module export. Rebless ModuleExport.expected to drop the
legacy 'ControlFlowNode for' toString prefix and pick up the two correct rows
exposed by the fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-28 21:09:49 +00:00

60 lines
2.1 KiB
Plaintext

import python
private import semmle.python.controlflow.internal.Cfg as Cfg
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.PrintNode
module TestTaintTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// Standard sources
source.(DataFlow::CfgNode).getNode().(Cfg::NameNode).getId() in [
"TAINTED_STRING", "TAINTED_BYTES", "TAINTED_LIST", "TAINTED_DICT"
]
or
// User defined sources
exists(Cfg::CallNode call |
call.getFunction().(Cfg::NameNode).getId() = "taint" and
source.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
predicate isSink(DataFlow::Node sink) {
exists(Cfg::CallNode call |
call.getFunction().(Cfg::NameNode).getId() in ["ensure_tainted", "ensure_not_tainted"] and
sink.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
}
module TestTaintTrackingFlow = DataFlow::Global<TestTaintTrackingConfig>;
query predicate test_taint(string arg_location, string test_res, string scope_name, string repr) {
exists(Call call, Expr arg, boolean expected_taint, boolean has_taint |
// only consider files that are extracted as part of the test
exists(call.getLocation().getFile().getRelativePath()) and
(
call.getFunc().(Name).getId() = "ensure_tainted" and
expected_taint = true
or
call.getFunc().(Name).getId() = "ensure_not_tainted" and
expected_taint = false
) and
arg = call.getAnArg() and
(
// TODO: Replace with `hasFlowToExpr` once that is working
if
TestTaintTrackingFlow::flowTo(any(DataFlow::Node n |
n.(DataFlow::CfgNode).getNode().getNode() = arg
))
then has_taint = true
else has_taint = false
) and
(if expected_taint = has_taint then test_res = "ok " else test_res = "fail") and
// select
arg_location = arg.getLocation().toString() and
test_res = test_res and
scope_name = call.getScope().getName() and
repr = prettyExpr(arg)
)
}