Skip to content

Commit

Permalink
Rust: Model pointer read and write functions
Browse files Browse the repository at this point in the history
  • Loading branch information
paldepind committed Feb 28, 2025
1 parent 5b65703 commit c6f56fc
Showing 4 changed files with 35 additions and 6 deletions.
7 changes: 7 additions & 0 deletions rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
Original file line number Diff line number Diff line change
@@ -19,6 +19,13 @@ extensions:
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
# ptr
- ["lang:core", "crate::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_volatile", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::write", "Argument[1]", "Argument[0].Reference", "value", "manual"]
- ["lang:core", "crate::ptr::write_unaligned", "Argument[1]", "Argument[0].Reference", "value", "manual"]
- ["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"]
# String
10 changes: 10 additions & 0 deletions rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ models
| 3 | Summary: lang:core; <crate::option::Option>::zip; Argument[0].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)].Field[1]; value |
| 4 | Summary: lang:core; <crate::result::Result as crate::clone::Clone>::clone; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue.Field[crate::result::Result::Ok(0)]; value |
| 5 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 6 | Summary: lang:core; crate::ptr::read; Argument[0].Reference; ReturnValue; value |
| 7 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value |
edges
| main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:10 | a [Some] | provenance | |
| main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | |
@@ -54,6 +56,9 @@ edges
| main.rs:61:13:61:24 | Some(...) [Some, tuple.1] | main.rs:61:18:61:23 | TuplePat [tuple.1] | provenance | |
| main.rs:61:18:61:23 | TuplePat [tuple.1] | main.rs:61:22:61:22 | m | provenance | |
| main.rs:61:22:61:22 | m | main.rs:63:22:63:22 | m | provenance | |
| main.rs:84:29:84:29 | [post] y [&ref] | main.rs:85:33:85:33 | y [&ref] | provenance | |
| main.rs:84:32:84:41 | source(...) | main.rs:84:29:84:29 | [post] y [&ref] | provenance | MaD:7 |
| main.rs:85:33:85:33 | y [&ref] | main.rs:85:18:85:34 | ...::read(...) | provenance | MaD:6 |
nodes
| main.rs:12:9:12:9 | a [Some] | semmle.label | a [Some] |
| main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] |
@@ -107,6 +112,10 @@ nodes
| main.rs:61:18:61:23 | TuplePat [tuple.1] | semmle.label | TuplePat [tuple.1] |
| main.rs:61:22:61:22 | m | semmle.label | m |
| main.rs:63:22:63:22 | m | semmle.label | m |
| main.rs:84:29:84:29 | [post] y [&ref] | semmle.label | [post] y [&ref] |
| main.rs:84:32:84:41 | source(...) | semmle.label | source(...) |
| main.rs:85:18:85:34 | ...::read(...) | semmle.label | ...::read(...) |
| main.rs:85:33:85:33 | y [&ref] | semmle.label | y [&ref] |
subpaths
testFailures
#select
@@ -119,3 +128,4 @@ testFailures
| main.rs:43:38:43:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:43:38:43:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) |
| main.rs:47:38:47:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:47:38:47:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) |
| main.rs:63:22:63:22 | m | main.rs:58:22:58:31 | source(...) | main.rs:63:22:63:22 | m | $@ | main.rs:58:22:58:31 | source(...) | source(...) |
| main.rs:85:18:85:34 | ...::read(...) | main.rs:84:32:84:41 | source(...) | main.rs:85:18:85:34 | ...::read(...) | $@ | main.rs:84:32:84:41 | source(...) | source(...) |
2 changes: 1 addition & 1 deletion rust/ql/test/library-tests/dataflow/modeled/main.rs
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ mod ptr {
unsafe {
sink(std::ptr::read(y));
std::ptr::write(y, source(30));
sink(std::ptr::read(y)); // $ MISSING: hasValueFlow=30
sink(std::ptr::read(y)); // $ hasValueFlow=30
}
}
}
22 changes: 17 additions & 5 deletions rust/ql/test/utils-tests/modelgenerator/option.rs
Original file line number Diff line number Diff line change
@@ -5,8 +5,19 @@

use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr;
use core::{hint, mem};

// summary=repo::test;crate::option::replace;Argument[0].Reference;ReturnValue;value;dfc-generated
// summary=repo::test;crate::option::replace;Argument[1];Argument[0].Reference;value;dfc-generated
pub fn replace<T>(dest: &mut T, src: T) -> T {
unsafe {
let result = ptr::read(dest);
ptr::write(dest, src);
result
}
}

#[derive(Copy, Eq, Debug, Hash)]
pub enum MyOption<T> {
MyNone,
@@ -326,14 +337,14 @@ impl<T> MyOption<T> {
unsafe { self.as_mut().unwrap_unchecked() }
}

// MISSING: Uses `mem::replace`
// summary=repo::test;<crate::option::MyOption>::take;Argument[self].Reference;ReturnValue;value;dfc-generated
pub fn take(&mut self) -> MyOption<T> {
// FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready
mem::replace(self, MyNone)
replace(self, MyNone)
}

// summary=repo::test;<crate::option::MyOption>::take_if;Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];Argument[0].Parameter[0].Reference;value;dfc-generated
// MISSING: Uses `take` which doesn't have flow
// summary=repo::test;<crate::option::MyOption>::take_if;Argument[self].Reference;ReturnValue;value;dfc-generated
pub fn take_if<P>(&mut self, predicate: P) -> MyOption<T>
where
P: FnOnce(&mut T) -> bool,
@@ -345,9 +356,10 @@ impl<T> MyOption<T> {
}
}

// MISSING: Uses `mem::replace`
// summary=repo::test;<crate::option::MyOption>::replace;Argument[0];Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::replace;Argument[self].Reference;ReturnValue;value;dfc-generated
pub fn replace(&mut self, value: T) -> MyOption<T> {
mem::replace(self, MySome(value))
replace(self, MySome(value))
}

// summary=repo::test;<crate::option::MyOption>::zip;Argument[0].Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)].Field[1];value;dfc-generated

0 comments on commit c6f56fc

Please sign in to comment.