mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Moves the existing points-to predicates to the newly added class `ControlFlowNodeWithPointsTo` which resides in the `LegacyPointsTo` module. (Existing code that uses these predicates should import this module, and references to `ControlFlowNode` should be changed to `ControlFlowNodeWithPointsTo`.) Also updates all existing points-to based code to do just this.
96 lines
2.7 KiB
Plaintext
96 lines
2.7 KiB
Plaintext
import python
|
|
private import LegacyPointsTo
|
|
private import semmle.python.types.Object
|
|
private import semmle.python.types.ClassObject
|
|
private import semmle.python.types.FunctionObject
|
|
|
|
predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) {
|
|
(n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and
|
|
attr = "const"
|
|
or
|
|
exists(Object s |
|
|
n.refersTo(s, theBytesType(), _) and
|
|
attr = "bytes" and
|
|
// We are only interested in bytes if they may cause an exception if
|
|
// implicitly converted to unicode. ASCII is safe.
|
|
not s.(StringObject).isAscii()
|
|
)
|
|
}
|
|
|
|
predicate tracked_object(ControlFlowNode obj, string attr) {
|
|
tracked_object_all(obj, attr)
|
|
or
|
|
tracked_object_any(obj, attr)
|
|
}
|
|
|
|
predicate open_file(Object obj) {
|
|
obj.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("open"))
|
|
}
|
|
|
|
predicate string_attribute_any(ControlFlowNodeWithPointsTo n, string attr) {
|
|
attr = "user-input" and
|
|
exists(Object input | n.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(input) |
|
|
if major_version() = 2
|
|
then input = Object::builtin("raw_input")
|
|
else input = Object::builtin("input")
|
|
)
|
|
or
|
|
attr = "file-input" and
|
|
exists(Object fd |
|
|
n.(CallNode)
|
|
.getFunction()
|
|
.(AttrNode)
|
|
.getObject("read")
|
|
.(ControlFlowNodeWithPointsTo)
|
|
.refersTo(fd)
|
|
|
|
|
open_file(fd)
|
|
)
|
|
or
|
|
n.refersTo(_, theUnicodeType(), _) and attr = "unicode"
|
|
}
|
|
|
|
predicate tracked_object_any(ControlFlowNode obj, string attr) {
|
|
string_attribute_any(obj, attr)
|
|
or
|
|
exists(ControlFlowNode other | tracking_step(other, obj) | tracked_object_any(other, attr))
|
|
}
|
|
|
|
predicate tracked_object_all(ControlFlowNode obj, string attr) {
|
|
string_attribute_all(obj, attr)
|
|
or
|
|
forex(ControlFlowNode other | tracking_step(other, obj) | tracked_object_all(other, attr))
|
|
}
|
|
|
|
predicate tracked_call_step(ControlFlowNode ret, ControlFlowNode call) {
|
|
exists(FunctionObject func, Return r |
|
|
func.getACall() = call and
|
|
func.getFunction() = r.getScope() and
|
|
r.getValue() = ret.getNode()
|
|
)
|
|
}
|
|
|
|
ControlFlowNode sequence_for_iterator(ControlFlowNode f) {
|
|
exists(For for | f.getNode() = for.getTarget() |
|
|
result.getNode() = for.getIter() and
|
|
result.getBasicBlock().dominates(f.getBasicBlock())
|
|
)
|
|
}
|
|
|
|
pragma[noinline]
|
|
private predicate tracking_step(ControlFlowNode src, ControlFlowNodeWithPointsTo dest) {
|
|
src = dest.(BinaryExprNode).getAnOperand()
|
|
or
|
|
src = dest.(UnaryExprNode).getOperand()
|
|
or
|
|
src = sequence_for_iterator(dest)
|
|
or
|
|
src = dest.(AttrNode).getObject()
|
|
or
|
|
src = dest.(SubscriptNode).getObject()
|
|
or
|
|
tracked_call_step(src, dest)
|
|
or
|
|
dest.refersTo(src)
|
|
}
|