Ruby: Pathname use TypeTracker instead of local flow

This commit is contained in:
Arthur Baars
2022-09-23 16:32:59 +02:00
parent d5478a01ab
commit f9b952f04f

View File

@@ -7,6 +7,7 @@ private import codeql.ruby.DataFlow
private import codeql.ruby.dataflow.FlowSummary
private import codeql.ruby.dataflow.internal.DataFlowDispatch
private import codeql.ruby.frameworks.data.ModelsAsData
private import codeql.ruby.typetracking.TypeTracker
/**
* Modeling of the `Pathname` class from the Ruby standard library.
@@ -31,29 +32,31 @@ module Pathname {
PathnameInstance() { this = pathnameInstance() }
}
private DataFlow::Node pathnameInstance() {
// A call to `Pathname.new`.
result = API::getTopLevelMember("Pathname").getAnInstantiation()
or
// Class methods on `Pathname` that return a new `Pathname`.
result = API::getTopLevelMember("Pathname").getAMethodCall(["getwd", "pwd",])
or
// Instance methods on `Pathname` that return a new `Pathname`.
exists(DataFlow::CallNode c | result = c |
c.getReceiver() = pathnameInstance() and
c.getMethodName() =
[
"+", "/", "basename", "cleanpath", "expand_path", "join", "realpath",
"relative_path_from", "sub", "sub_ext", "to_path"
]
private DataFlow::LocalSourceNode pathnameInstance(TypeTracker t) {
t.start() and
(
// A call to `Pathname.new`.
result = API::getTopLevelMember("Pathname").getAnInstantiation()
or
// Class methods on `Pathname` that return a new `Pathname`.
result = API::getTopLevelMember("Pathname").getAMethodCall(["getwd", "pwd",])
or
// Instance methods on `Pathname` that return a new `Pathname`.
exists(DataFlow::CallNode c | result = c |
c.getReceiver() = pathnameInstance() and
c.getMethodName() =
[
"+", "/", "basename", "cleanpath", "expand_path", "join", "realpath",
"relative_path_from", "sub", "sub_ext", "to_path"
]
)
)
or
exists(DataFlow::Node inst |
inst = pathnameInstance() and
inst.(DataFlow::LocalSourceNode).flowsTo(result)
)
exists(TypeTracker t2 | result = pathnameInstance(t2).track(t2, t))
}
private DataFlow::Node pathnameInstance() { pathnameInstance(TypeTracker::end()).flowsTo(result) }
/** A call where the receiver is a `Pathname`. */
class PathnameCall extends DataFlow::CallNode {
PathnameCall() { this.getReceiver() instanceof PathnameInstance }