Skip to content

Rust: Make SummarizedCallable extend Function instead of string #19268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 1 addition & 26 deletions rust/ql/lib/codeql/rust/dataflow/FlowSummary.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,17 @@

private import rust
private import internal.FlowSummaryImpl as Impl
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl

// import all instances below
private module Summaries {
private import codeql.rust.Frameworks
private import codeql.rust.dataflow.internal.ModelsAsData
}

/** Provides the `Range` class used to define the extent of `LibraryCallable`. */
module LibraryCallable {
/** A callable defined in library code, identified by a unique string. */
abstract class Range extends string {
bindingset[this]
Range() { any() }

/** Gets a call to this library callable. */
CallExprBase getACall() {
exists(Resolvable r, string crate |
r = CallExprBaseImpl::getCallResolvable(result) and
this = crate + r.getResolvedPath()
|
crate = r.getResolvedCrateOrigin() + "::_::"
or
not r.hasResolvedCrateOrigin() and
crate = ""
)
}
}
}

final class LibraryCallable = LibraryCallable::Range;

/** Provides the `Range` class used to define the extent of `SummarizedCallable`. */
module SummarizedCallable {
/** A callable with a flow summary, identified by a unique string. */
abstract class Range extends LibraryCallable::Range, Impl::Public::SummarizedCallable {
abstract class Range extends Impl::Public::SummarizedCallable {
bindingset[this]
Range() { any() }

Expand Down
27 changes: 15 additions & 12 deletions rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ final class DataFlowCallable extends TDataFlowCallable {
/**
* Gets the underlying library callable, if any.
*/
LibraryCallable asLibraryCallable() { this = TLibraryCallable(result) }
SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }

/** Gets a textual representation of this callable. */
string toString() { result = [this.asCfgScope().toString(), this.asLibraryCallable().toString()] }
string toString() {
result = [this.asCfgScope().toString(), this.asSummarizedCallable().toString()]
}

/** Gets the location of this callable. */
Location getLocation() { result = this.asCfgScope().getLocation() }
Expand All @@ -67,12 +69,9 @@ final class DataFlowCall extends TDataFlowCall {
}

DataFlowCallable getEnclosingCallable() {
result = TCfgScope(this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope())
result.asCfgScope() = this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope()
or
exists(FlowSummaryImpl::Public::SummarizedCallable c |
this.isSummaryCall(c, _) and
result = TLibraryCallable(c)
)
this.isSummaryCall(result.asSummarizedCallable(), _)
}

string toString() {
Expand Down Expand Up @@ -434,9 +433,13 @@ module RustDataFlow implements InputSig<Location> {

/** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall call) {
result.asCfgScope() = call.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget()
or
result.asLibraryCallable().getACall() = call.asCallBaseExprCfgNode().getCallExprBase()
exists(Callable target |
target = call.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget()
|
target = result.asCfgScope()
or
target = result.asSummarizedCallable()
)
}

/**
Expand Down Expand Up @@ -784,7 +787,7 @@ module RustDataFlow implements InputSig<Location> {
predicate allowParameterReturnInSelf(ParameterNode p) {
exists(DataFlowCallable c, ParameterPosition pos |
p.isParameterOf(c, pos) and
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(c.asLibraryCallable(), pos)
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(c.asSummarizedCallable(), pos)
)
or
VariableCapture::Flow::heuristicAllowInstanceParameterReturnInSelf(p.(ClosureParameterNode)
Expand Down Expand Up @@ -993,7 +996,7 @@ private module Cached {
cached
newtype TDataFlowCallable =
TCfgScope(CfgScope scope) or
TLibraryCallable(LibraryCallable c)
TSummarizedCallable(SummarizedCallable c)

/** This is the local flow predicate that is exposed. */
cached
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module Input implements InputSig<Location, RustDataFlow> {
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
private import codeql.rust.frameworks.stdlib.Stdlib

class SummarizedCallableBase = string;
class SummarizedCallableBase = Function;

abstract private class SourceSinkBase extends AstNode {
/** Gets the associated call. */
Expand Down Expand Up @@ -153,7 +153,7 @@ private import Make<Location, RustDataFlow, Input> as Impl

private module StepsInput implements Impl::Private::StepsInputSig {
DataFlowCall getACall(Public::SummarizedCallable sc) {
result.asCallBaseExprCfgNode().getCallExprBase() = sc.(LibraryCallable).getACall()
result.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget() = sc
}

RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
Expand Down
20 changes: 19 additions & 1 deletion rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
private import codeql.rust.dataflow.FlowSummary
private import codeql.rust.dataflow.FlowSource
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl

/**
* Holds if in a call to the function with canonical path `path`, defined in the
Expand Down Expand Up @@ -114,13 +115,30 @@
)
}

private predicate sdf(CallExprBase call, Function f) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
CallExprBaseImpl::getCallResolvable(call).getResolvedPath() = "<crate::option::Option>::unwrap" and
// CallExprBaseImpl::getCallResolvable(call).getResolvedCrateOrigin() = "lang:core" and
f = call.getStaticTarget()
}

private predicate sdf2(CallExprBase call) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
CallExprBaseImpl::getCallResolvable(call).getResolvedPath() = "<crate::option::Option>::unwrap"
// CallExprBaseImpl::getCallResolvable(call).getResolvedCrateOrigin() = "lang:core" and
// f = call.getStaticTarget()
}

private class SummarizedCallableFromModel extends SummarizedCallable::Range {
private string crate;
private string path;

SummarizedCallableFromModel() {
summaryModel(crate, path, _, _, _, _, _) and
this = crate + "::_::" + path
exists(CallExprBase call, Resolvable r |
call.getStaticTarget() = this and
r = CallExprBaseImpl::getCallResolvable(call) and
r.getResolvedPath() = path and
r.getResolvedCrateOrigin() = crate
)
}

override predicate propagatesFlow(
Expand Down
8 changes: 4 additions & 4 deletions rust/ql/lib/codeql/rust/dataflow/internal/Node.qll
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ abstract class NodePublic extends TNode {

abstract class Node extends NodePublic {
/** Gets the enclosing callable. */
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
DataFlowCallable getEnclosingCallable() { result.asCfgScope() = this.getCfgScope() }

/** Do not call: use `getEnclosingCallable()` instead. */
abstract CfgScope getCfgScope();
Expand Down Expand Up @@ -102,9 +102,9 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
}

override DataFlowCallable getEnclosingCallable() {
result.asLibraryCallable() = this.getSummarizedCallable()
or
result.asCfgScope() = this.getCfgScope()
or
result.asSummarizedCallable() = this.getSummarizedCallable()
}

override Location getLocation() {
Expand Down Expand Up @@ -195,7 +195,7 @@ final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
}

override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.getSummarizedCallable() = c.asLibraryCallable() and pos = pos_
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
}
}

Expand Down
16 changes: 9 additions & 7 deletions rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@
/** A `clone` method. */
final class CloneCallable extends SummarizedCallable::Range {
CloneCallable() {
// NOTE: The function target may not exist in the database, so we base this
// on method calls.
exists(MethodCallExpr c |
c.getIdentifier().getText() = "clone" and
c.getArgList().getNumberOfArgs() = 0 and
this = c.getResolvedCrateOrigin() + "::_::" + c.getResolvedPath()
)
this.getParamList().getNumberOfParams() = 0 and
this.getName().getText() = "clone"
}

final override predicate propagatesFlow(
Expand All @@ -24,3 +19,10 @@
model = "generated"
}
}

private predicate sdf(MethodCallExpr c, string s, Addressable a) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
c.getIdentifier().getText() = "clone" and
c.getArgList().getNumberOfArgs() = 0 and
s = c.getResolvedPath() and
s = a.getExtendedCanonicalPath()
}
18 changes: 18 additions & 0 deletions rust/ql/lib/codeql/rust/internal/PathResolution.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1180,3 +1180,21 @@
fileImport(m, f)
}
}

private predicate sdfs(Impl impl, string s) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
impl.toString() = "impl ...::Option { ... }" and
s = impl.getSelfTy().(PathTypeRepr).getPath().toStringDebug()
}

private predicate sdfs2(Impl impl, RelevantPath path, RelevantPath q, string p, ItemNode i) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
impl.toString() = "impl ...::Option { ... }" and
path = impl.getSelfTy().(PathTypeRepr).getPath() and
q = path.getQualifier*() and
p = path.toStringDebug() and
// parent = i.getImmediateParent().getImmediateParent() and
// rootHasCratePathTc(encl, i) and
// crate = encl.getASuccessor(name)
// crate = encl.getASuccessor(name)
i = resolvePath(q)
// unqualifiedPathLookup(q, name, ns, encl)
}
23 changes: 23 additions & 0 deletions rust/ql/lib/codeql/rust/internal/TypeInference.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1017,3 +1017,26 @@
* Gets a type that `n` infers to, if any.
*/
Type inferType(AstNode n) { result = inferType(n, TypePath::nil()) }

/** Provides predicates for debugging the type inference implementation. */
private module Debug {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
private Locatable getRelevantLocatable() {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |

Check warning

Code scanning / CodeQL

Omittable 'exists' variable Warning

This exists variable can be omitted by using a don't-care expression
in this argument
.

Check warning

Code scanning / CodeQL

Omittable 'exists' variable Warning

This exists variable can be omitted by using a don't-care expression
in this argument
.

Check warning

Code scanning / CodeQL

Omittable 'exists' variable Warning

This exists variable can be omitted by using a don't-care expression
in this argument
.
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
filepath.matches("%/main.rs") and
startline = 13
)
}

Type debugInferType(AstNode n, TypePath path) {
n = getRelevantLocatable() and
result = inferType(n, path)
}

EnumType debugInferTyp2(AstNode n, TypePath path, ImplItemNode impl) {
n = getRelevantLocatable() and
result = inferType(n, path) and
// exists(result.getMethod(name)) and
impl.resolveSelfTy() = result.asItemNode()
}
}
6 changes: 2 additions & 4 deletions rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF

Type getType() { any() }

Callable getEnclosingCallable() {
result = this.(Node::Node).getEnclosingCallable().asCfgScope()
}
Callable getEnclosingCallable() { result = this.(Node::Node).getEnclosingCallable() }
}

private predicate relevant(Function api) {
Expand Down Expand Up @@ -102,7 +100,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
}

Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
result = ret.(Node::Node).getEnclosingCallable().asCfgScope()
result = ret.(Node::Node).getEnclosingCallable()
}

predicate isOwnInstanceAccessNode(RustDataFlow::ReturnNode node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@
| main.rs:238:17:238:25 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:239:9:239:15 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:242:5:242:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:246:13:246:55 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
| main.rs:246:13:246:55 | ...::block_on(...) | file://:0:0:0:0 | fn block_on |
| main.rs:246:41:246:54 | async_source(...) | main.rs:227:1:231:1 | fn async_source |
| main.rs:247:5:247:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:249:5:249:62 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
| main.rs:249:5:249:62 | ...::block_on(...) | file://:0:0:0:0 | fn block_on |
| main.rs:249:33:249:61 | test_async_await_async_part(...) | main.rs:233:1:243:1 | fn test_async_await_async_part |
| main.rs:253:5:253:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:254:5:254:35 | data_out_of_call_side_effect1(...) | main.rs:35:1:40:1 | fn data_out_of_call_side_effect1 |
Expand Down
Loading
Loading