mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Python: Improve taint steps in for & iterable unpacking
These were written way before the ones in DataFlowPrivate, but apparently didn't cover quite as much :|
This commit is contained in:
@@ -46,9 +46,11 @@ private module Cached {
|
||||
or
|
||||
copyStep(nodeFrom, nodeTo)
|
||||
or
|
||||
forStep(nodeFrom, nodeTo)
|
||||
DataFlowPrivate::forReadStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
unpackingAssignmentStep(nodeFrom, nodeTo)
|
||||
DataFlowPrivate::iterableUnpackingReadStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
DataFlowPrivate::iterableUnpackingStoreStep(nodeFrom, _, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,28 +201,3 @@ predicate copyStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||
call.getArg(0) = nodeFrom
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to `for`-iteration,
|
||||
* for example `for x in xs`, or `for x,y in points`.
|
||||
*/
|
||||
predicate forStep(DataFlow::CfgNode nodeFrom, DataFlow::EssaNode nodeTo) {
|
||||
exists(EssaNodeDefinition defn, For for |
|
||||
for.getTarget().getAChildNode*() = defn.getDefiningNode().getNode() and
|
||||
nodeTo.getVar() = defn and
|
||||
nodeFrom.asExpr() = for.getIter()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to iterable unpacking.
|
||||
* Only handles normal assignment (`x,y = calc_point()`), since `for x,y in points` is handled by `forStep`.
|
||||
*/
|
||||
predicate unpackingAssignmentStep(DataFlow::CfgNode nodeFrom, DataFlow::EssaNode nodeTo) {
|
||||
// `a, b = myiterable` or `head, *tail = myiterable` (only Python 3)
|
||||
exists(MultiAssignmentDefinition defn, Assign assign |
|
||||
assign.getATarget().contains(defn.getDefiningNode().getNode()) and
|
||||
nodeTo.getVar() = defn and
|
||||
nodeFrom.asExpr() = assign.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ def test_access(x, y, z):
|
||||
reversed(tainted_list), # $ tainted
|
||||
iter(tainted_list), # $ tainted
|
||||
next(iter(tainted_list)), # $ tainted
|
||||
[i for i in tainted_list], # $ MISSING: tainted
|
||||
[i for i in tainted_list], # $ tainted
|
||||
[tainted_list for _i in [1,2,3]], # $ MISSING: tainted
|
||||
)
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ async def test_taint(request: web.Request): # $ requestHandler
|
||||
await request.content.readline(), # $ tainted
|
||||
await request.content.readchunk(), # $ tainted
|
||||
(await request.content.readchunk())[0], # $ tainted
|
||||
[line async for line in request.content], # $ MISSING: tainted
|
||||
[line async for line in request.content], # $ tainted
|
||||
[data async for data in request.content.iter_chunked(1024)], # $ MISSING: tainted
|
||||
[data async for data in request.content.iter_any()], # $ MISSING: tainted
|
||||
[data async for data, _ in request.content.iter_chunks()], # $ MISSING: tainted
|
||||
|
||||
@@ -108,7 +108,7 @@ def test_taint(request: HttpRequest, foo, bar, baz=None): # $requestHandler rou
|
||||
request.readline(), # $ tainted
|
||||
request.readlines(), # $ tainted
|
||||
request.readlines()[0], # $ tainted
|
||||
[line for line in request], # $ MISSING: tainted
|
||||
[line for line in request], # $ tainted
|
||||
)
|
||||
|
||||
# django.urls.ResolverMatch also supports iterable unpacking
|
||||
|
||||
@@ -63,7 +63,7 @@ class TaintTest(tornado.web.RequestHandler):
|
||||
request.headers["header-name"], # $ tainted
|
||||
request.headers.get_list("header-name"), # $ tainted
|
||||
request.headers.get_all(), # $ tainted
|
||||
[(k, v) for (k, v) in request.headers.get_all()], # $ MISSING: tainted
|
||||
[(k, v) for (k, v) in request.headers.get_all()], # $ tainted
|
||||
|
||||
# Dict[str, http.cookies.Morsel]
|
||||
request.cookies, # $ tainted
|
||||
|
||||
Reference in New Issue
Block a user