Skip to content
Closed
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
123 changes: 99 additions & 24 deletions rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,35 @@ private class SummarizedCallableWithCallback extends SummarizedCallable::Range {

private class FlowSourceFromModel extends FlowSource::Range {
private string path;
private string output_;
private string kind_;
private Provenance provenance_;
private QlBuiltins::ExtensionId madId;

FlowSourceFromModel() {
sourceModel(path, _, _, _, _) and
this.getCanonicalPath() = path
exists(string output, string kind, Function f, Provenance p |
sourceModel(path, output, kind, p, madId) and
f.getCanonicalPath() = path
|
output_ = output and
kind_ = kind and
(
this = f and
provenance_ = p
or
this.implements(f) and
not this.getCanonicalPath() = path and
this.getCanonicalPath().matches("<_ as %") and
provenance_ = "hq-generated"
)
)
}

override predicate isSource(string output, string kind, Provenance provenance, string model) {
exists(QlBuiltins::ExtensionId madId |
sourceModel(path, output, kind, provenance, madId) and
model = "MaD:" + madId.toString()
) and
output = output_ and
kind = kind_ and
provenance = provenance_ and
model = "MaD:" + madId.toString() and
// Only apply generated models when no neutral model exists
// (the shared code only applies neutral models to summaries at present)
not (
Expand All @@ -268,17 +286,35 @@ private class FlowSourceFromModel extends FlowSource::Range {

private class FlowSinkFromModel extends FlowSink::Range {
private string path;
private string input_;
private string kind_;
private Provenance provenance_;
private QlBuiltins::ExtensionId madId;

FlowSinkFromModel() {
sinkModel(path, _, _, _, _) and
this.getCanonicalPath() = path
exists(string input, string kind, Function f, Provenance p |
sinkModel(path, input, kind, p, madId) and
f.getCanonicalPath() = path
|
input_ = input and
kind_ = kind and
(
this = f and
provenance_ = p
or
this.implements(f) and
not this.getCanonicalPath() = path and
this.getCanonicalPath().matches("<_ as %") and
provenance_ = "hq-generated"
)
)
}

override predicate isSink(string input, string kind, Provenance provenance, string model) {
exists(QlBuiltins::ExtensionId madId |
sinkModel(path, input, kind, provenance, madId) and
model = "MaD:" + madId.toString()
) and
input = input_ and
kind = kind_ and
provenance = provenance_ and
model = "MaD:" + madId.toString() and
// Only apply generated models when no neutral model exists
// (the shared code only applies neutral models to summaries at present)
not (
Expand All @@ -290,35 +326,74 @@ private class FlowSinkFromModel extends FlowSink::Range {

private class FlowBarrierFromModel extends FlowBarrier::Range {
private string path;
private string output_;
private string kind_;
private Provenance provenance_;
private QlBuiltins::ExtensionId madId;

FlowBarrierFromModel() {
barrierModel(path, _, _, _, _) and
this.getCanonicalPath() = path
exists(string output, string kind, Function f, Provenance p |
barrierModel(path, output, kind, p, madId) and
f.getCanonicalPath() = path
|
output_ = output and
kind_ = kind and
(
this = f and
provenance_ = p
or
this.implements(f) and
not this.getCanonicalPath() = path and
this.getCanonicalPath().matches("<_ as %") and
provenance_ = "hq-generated"
)
)
}

override predicate isBarrier(string output, string kind, Provenance provenance, string model) {
exists(QlBuiltins::ExtensionId madId |
barrierModel(path, output, kind, provenance, madId) and
model = "MaD:" + madId.toString()
)
output = output_ and
kind = kind_ and
provenance = provenance_ and
model = "MaD:" + madId.toString()
}
}

private class FlowBarrierGuardFromModel extends FlowBarrierGuard::Range {
private string path;
private string input_;
private string acceptingValue_;
private string kind_;
private Provenance provenance_;
private QlBuiltins::ExtensionId madId;

FlowBarrierGuardFromModel() {
barrierGuardModel(path, _, _, _, _, _) and
this.getCanonicalPath() = path
exists(string input, string acceptingValue, string kind, Function f, Provenance p |
barrierGuardModel(path, input, acceptingValue, kind, p, madId) and
f.getCanonicalPath() = path
|
input_ = input and
acceptingValue_ = acceptingValue and
kind_ = kind and
(
this = f and
provenance_ = p
or
this.implements(f) and
not this.getCanonicalPath() = path and
this.getCanonicalPath().matches("<_ as %") and
provenance_ = "hq-generated"
)
)
}

override predicate isBarrierGuard(
string input, string acceptingValue, string kind, Provenance provenance, string model
) {
exists(QlBuiltins::ExtensionId madId |
barrierGuardModel(path, input, acceptingValue, kind, provenance, madId) and
model = "MaD:" + madId.toString()
)
input = input_ and
acceptingValue = acceptingValue_ and
kind = kind_ and
provenance = provenance_ and
model = "MaD:" + madId.toString()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extensions:
- ["alloc::alloc::realloc", "Argument[2]", "alloc-size", "manual"]
- ["core::alloc::global::GlobalAlloc::alloc", "Argument[0]", "alloc-layout", "manual"]
- ["core::alloc::global::GlobalAlloc::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["core::alloc::global::GlobalAlloc::realloc", "Argument[2]", "alloc-size", "manual"]
- ["core::alloc::Allocator::allocate", "Argument[0]", "alloc-layout", "manual"]
- ["core::alloc::Allocator::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["core::alloc::Allocator::grow", "Argument[2]", "alloc-layout", "manual"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ extensions:
extensible: barrierModel
data:
- ["main::sanitize", "ReturnValue", "test-barrier", "manual"]
- ["main::MyTraitBarrier::sanitize_trait", "ReturnValue", "test-barrier", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: barrierGuardModel
data:
- ["main::verify_safe", "Argument[0]", "true", "test-barrier", "manual"]
- ["main::MyTraitBarrier::verify_safe_trait", "Argument[0]", "true", "test-barrier", "manual"]
28 changes: 28 additions & 0 deletions rust/ql/test/library-tests/dataflow/barrier/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,31 @@ fn with_barrier_guard() {
sink(s);
}
}

trait MyTraitBarrier {
fn sanitize_trait(s: &str) -> &str;
fn verify_safe_trait(s: &str) -> bool;
}

impl<T> MyTraitBarrier for T {
fn sanitize_trait(s: &str) -> &str {
sanitize(s)
}

fn verify_safe_trait(s: &str) -> bool {
verify_safe(s)
}
}

fn with_trait_barrier() {
let s = source(1);
let s = <()>::sanitize_trait(s);
sink(s);
}

fn with_trait_barrier_guard() {
let s = source(1);
if <()>::verify_safe_trait(s) {
sink(s);
}
}