mirror of
https://github.com/github/codeql.git
synced 2026-04-14 11:34:00 +02:00
Rust: Initial version of the query.
This commit is contained in:
@@ -26,3 +26,11 @@ extensions:
|
||||
- ["lang:core", "crate::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
# Str
|
||||
- ["lang:core", "<str>::parse", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
# Alloc
|
||||
- ["lang:core", "crate::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["lang:core", "crate::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["lang:core", "crate::ptr::null", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about accesses to invalid
|
||||
* pointers.
|
||||
*/
|
||||
|
||||
import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.FlowSource
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.Concepts
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting accesses to
|
||||
* invalid pointers, as well as extension points for adding your own.
|
||||
*/
|
||||
module AccessInvalidPointer {
|
||||
/**
|
||||
* A data flow source for invalid pointer accesses, that is, an operation
|
||||
* where a pointer becomes invalid.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for invalid pointer accesses, that is, a pointer
|
||||
* dereference.
|
||||
*/
|
||||
abstract class Sink extends QuerySink::Range {
|
||||
override string getSinkType() { result = "AccessInvalidPointer" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for invalid pointer accesses.
|
||||
*/
|
||||
abstract class Barrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A pointer invalidation from model data.
|
||||
*/
|
||||
private class ModelsAsDataSource extends Source {
|
||||
ModelsAsDataSource() { sourceNode(this, "pointer-invalidate") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A pointer access using the unary `*` operator.
|
||||
*/
|
||||
private class DereferenceSink extends Sink {
|
||||
DereferenceSink() {
|
||||
exists(PrefixExpr p | p.getOperatorName() = "*" and p.getExpr() = this.asExpr().getExpr())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A pointer access from model data.
|
||||
*/
|
||||
private class ModelsAsDataSink extends Sink {
|
||||
ModelsAsDataSink() { sinkNode(this, "pointer-access") }
|
||||
}
|
||||
}
|
||||
35
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
Normal file
35
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @name Access of invalid pointer
|
||||
* @description Dereferencing an invalid or dangling pointer is undefined behavior and may cause memory corruption.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity TODO
|
||||
* @precision TODO
|
||||
* @id rust/access-invalid-pointer
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-476
|
||||
* external/cwe/cwe-825
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.security.AccessInvalidPointerExtensions
|
||||
import AccessInvalidPointerFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A data flow configuration for accesses to invalid pointers.
|
||||
*/
|
||||
module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof AccessInvalidPointer::Source }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof AccessInvalidPointer::Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessInvalidPointer::Barrier }
|
||||
}
|
||||
|
||||
module AccessInvalidPointerFlow = DataFlow::Global<AccessInvalidPointerConfig>;
|
||||
|
||||
from AccessInvalidPointerFlow::PathNode sourceNode, AccessInvalidPointerFlow::PathNode sinkNode
|
||||
where AccessInvalidPointerFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode, "This operation dereferences a pointer that may be $@.", sourceNode.getNode(), "invalid"
|
||||
@@ -12,6 +12,7 @@ private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
|
||||
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
|
||||
private import codeql.rust.Concepts
|
||||
// import all query extensions files, so that all extensions of `QuerySink` are found
|
||||
private import codeql.rust.security.AccessInvalidPointerExtensions
|
||||
private import codeql.rust.security.CleartextLoggingExtensions
|
||||
private import codeql.rust.security.SqlInjectionExtensions
|
||||
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#select
|
||||
| deallocation.rs:96:14:96:15 | p1 | deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:96:14:96:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:89:23:89:40 | ...::dangling | invalid |
|
||||
| deallocation.rs:97:14:97:15 | p2 | deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:97:14:97:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:90:21:90:42 | ...::dangling_mut | invalid |
|
||||
| deallocation.rs:98:14:98:15 | p3 | deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:98:14:98:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:91:23:91:36 | ...::null | invalid |
|
||||
edges
|
||||
| deallocation.rs:89:6:89:7 | p1 | deallocation.rs:96:14:96:15 | p1 | provenance | |
|
||||
| deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:89:23:89:42 | ...::dangling(...) | provenance | Src:MaD:1 MaD:1 |
|
||||
| deallocation.rs:89:23:89:42 | ...::dangling(...) | deallocation.rs:89:6:89:7 | p1 | provenance | |
|
||||
| deallocation.rs:90:6:90:7 | p2 | deallocation.rs:97:14:97:15 | p2 | provenance | |
|
||||
| deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | provenance | Src:MaD:2 MaD:2 |
|
||||
| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | deallocation.rs:90:6:90:7 | p2 | provenance | |
|
||||
| deallocation.rs:91:6:91:7 | p3 | deallocation.rs:98:14:98:15 | p3 | provenance | |
|
||||
| deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:91:23:91:38 | ...::null(...) | provenance | Src:MaD:3 MaD:3 |
|
||||
| deallocation.rs:91:23:91:38 | ...::null(...) | deallocation.rs:91:6:91:7 | p3 | provenance | |
|
||||
models
|
||||
| 1 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
|
||||
| 2 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
|
||||
| 3 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
|
||||
nodes
|
||||
| deallocation.rs:89:6:89:7 | p1 | semmle.label | p1 |
|
||||
| deallocation.rs:89:23:89:40 | ...::dangling | semmle.label | ...::dangling |
|
||||
| deallocation.rs:89:23:89:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
|
||||
| deallocation.rs:90:6:90:7 | p2 | semmle.label | p2 |
|
||||
| deallocation.rs:90:21:90:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
|
||||
| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
|
||||
| deallocation.rs:91:6:91:7 | p3 | semmle.label | p3 |
|
||||
| deallocation.rs:91:23:91:36 | ...::null | semmle.label | ...::null |
|
||||
| deallocation.rs:91:23:91:38 | ...::null(...) | semmle.label | ...::null(...) |
|
||||
| deallocation.rs:96:14:96:15 | p1 | semmle.label | p1 |
|
||||
| deallocation.rs:97:14:97:15 | p2 | semmle.label | p2 |
|
||||
| deallocation.rs:98:14:98:15 | p3 | semmle.label | p3 |
|
||||
subpaths
|
||||
@@ -0,0 +1,4 @@
|
||||
query: queries/security/CWE-825/AccessInvalidPointer.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -86,16 +86,16 @@ pub fn test_libc() {
|
||||
// --- std::ptr ---
|
||||
|
||||
pub fn test_ptr_invalid(do_dangerous_accesses: bool) {
|
||||
let p1: *const i64 = std::ptr::dangling();
|
||||
let p2: *mut i64 = std::ptr::dangling_mut();
|
||||
let p3: *const i64 = std::ptr::null();
|
||||
let p1: *const i64 = std::ptr::dangling(); // $ Source=dangling
|
||||
let p2: *mut i64 = std::ptr::dangling_mut(); // $ Source=dangling_mut
|
||||
let p3: *const i64 = std::ptr::null(); // $ Source=null
|
||||
|
||||
if do_dangerous_accesses {
|
||||
unsafe {
|
||||
// (a segmentation fault occurs in the code below)
|
||||
let v1 = *p1; // $ MISSING: Alert
|
||||
let v2 = *p2; // $ MISSING: Alert
|
||||
let v3 = *p3; // $ MISSING: Alert
|
||||
let v1 = *p1; // $ Alert[rust/access-invalid-pointer]=dangling
|
||||
let v2 = *p2; // $ Alert[rust/access-invalid-pointer]=dangling_mut
|
||||
let v3 = *p3; // $ Alert[rust/access-invalid-pointer]=null
|
||||
println!(" v1 = {v1} (!)");
|
||||
println!(" v2 = {v2} (!)");
|
||||
println!(" v3 = {v3} (!)");
|
||||
|
||||
Reference in New Issue
Block a user