Merge pull request #20340 from hvitved/rust/taint-tracking-implicit-deref-at-sinks

Rust: Deref as taint step
This commit is contained in:
Tom Hvitved
2025-09-02 09:44:33 +02:00
committed by GitHub
6 changed files with 198 additions and 162 deletions

View File

@@ -41,13 +41,15 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
succ.asExpr() = index succ.asExpr() = index
) )
or or
// Although data flow through collections is modeled using stores/reads, // Although data flow through collections and references is modeled using
// we also allow taint to flow out of a tainted collection. This is // stores/reads, we also allow taint to flow out of a tainted collection
// needed in order to support taint-tracking configurations where the // or reference.
// source is a collection. // This is needed in order to support taint-tracking configurations where
exists(SingletonContentSet cs | // the source is a collection or reference.
RustDataFlow::readStep(pred, cs, succ) and exists(SingletonContentSet cs | RustDataFlow::readStep(pred, cs, succ) |
cs.getContent() instanceof ElementContent cs.getContent() instanceof ElementContent
or
cs.getContent() instanceof ReferenceContent
) )
or or
exists(FormatArgsExprCfgNode format | succ.asExpr() = format | exists(FormatArgsExprCfgNode format | succ.asExpr() = format |

View File

@@ -39,12 +39,6 @@ module HardcodedCryptographicValueConfig implements DataFlow::ConfigSig {
// case like `[0, 0, 0, 0]`) // case like `[0, 0, 0, 0]`)
isSource(node) isSource(node)
} }
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
// flow out from reference content at sinks.
isSink(node) and
c.getAReadContent() instanceof ReferenceContent
}
} }
module HardcodedCryptographicValueFlow = TaintTracking::Global<HardcodedCryptographicValueConfig>; module HardcodedCryptographicValueFlow = TaintTracking::Global<HardcodedCryptographicValueConfig>;

View File

@@ -1,10 +1,11 @@
models models
| 1 | Summary: <alloc::string::String as core::convert::From>::from; Argument[0]; ReturnValue; value | | 1 | Summary: <alloc::string::String as core::convert::From>::from; Argument[0].Reference; ReturnValue; value |
| 2 | Summary: <alloc::string::String as core::ops::arith::Add>::add; Argument[self]; ReturnValue; value | | 2 | Summary: <alloc::string::String as core::convert::From>::from; Argument[0]; ReturnValue; value |
| 3 | Summary: <alloc::string::String>::as_str; Argument[self]; ReturnValue; value | | 3 | Summary: <alloc::string::String as core::ops::arith::Add>::add; Argument[self]; ReturnValue; value |
| 4 | Summary: <core::str>::as_str; Argument[self]; ReturnValue; value | | 4 | Summary: <alloc::string::String>::as_str; Argument[self]; ReturnValue; value |
| 5 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | | 5 | Summary: <core::str>::as_str; Argument[self]; ReturnValue; value |
| 6 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value | | 6 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
| 7 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
edges edges
| main.rs:26:9:26:9 | s | main.rs:27:19:27:25 | s[...] | provenance | | | main.rs:26:9:26:9 | s | main.rs:27:19:27:25 | s[...] | provenance | |
| main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | s | provenance | | | main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | s | provenance | |
@@ -15,46 +16,47 @@ edges
| main.rs:32:9:32:10 | s1 | main.rs:35:14:35:15 | s1 | provenance | | | main.rs:32:9:32:10 | s1 | main.rs:35:14:35:15 | s1 | provenance | |
| main.rs:32:14:32:23 | source(...) | main.rs:32:9:32:10 | s1 | provenance | | | main.rs:32:14:32:23 | source(...) | main.rs:32:9:32:10 | s1 | provenance | |
| main.rs:35:9:35:10 | s4 | main.rs:38:10:38:11 | s4 | provenance | | | main.rs:35:9:35:10 | s4 | main.rs:38:10:38:11 | s4 | provenance | |
| main.rs:35:14:35:15 | s1 | main.rs:35:14:35:20 | ... + ... | provenance | MaD:2 | | main.rs:35:14:35:15 | s1 | main.rs:35:14:35:20 | ... + ... | provenance | MaD:3 |
| main.rs:35:14:35:20 | ... + ... | main.rs:35:9:35:10 | s4 | provenance | | | main.rs:35:14:35:20 | ... + ... | main.rs:35:9:35:10 | s4 | provenance | |
| main.rs:51:9:51:10 | s1 | main.rs:52:27:52:28 | s1 | provenance | | | main.rs:51:9:51:10 | s1 | main.rs:52:27:52:28 | s1 | provenance | |
| main.rs:51:14:51:29 | source_slice(...) | main.rs:51:9:51:10 | s1 | provenance | | | main.rs:51:14:51:29 | source_slice(...) | main.rs:51:9:51:10 | s1 | provenance | |
| main.rs:52:9:52:10 | s2 | main.rs:53:10:53:11 | s2 | provenance | | | main.rs:52:9:52:10 | s2 | main.rs:53:10:53:11 | s2 | provenance | |
| main.rs:52:14:52:29 | ...::from(...) | main.rs:52:9:52:10 | s2 | provenance | | | main.rs:52:14:52:29 | ...::from(...) | main.rs:52:9:52:10 | s2 | provenance | |
| main.rs:52:27:52:28 | s1 | main.rs:52:14:52:29 | ...::from(...) | provenance | MaD:1 | | main.rs:52:27:52:28 | s1 | main.rs:52:14:52:29 | ...::from(...) | provenance | MaD:1 |
| main.rs:52:27:52:28 | s1 | main.rs:52:14:52:29 | ...::from(...) | provenance | MaD:2 |
| main.rs:63:9:63:9 | s | main.rs:64:16:64:16 | s | provenance | | | main.rs:63:9:63:9 | s | main.rs:64:16:64:16 | s | provenance | |
| main.rs:63:9:63:9 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:3 |
| main.rs:63:9:63:9 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:4 | | main.rs:63:9:63:9 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:4 |
| main.rs:63:9:63:9 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:5 |
| main.rs:63:13:63:22 | source(...) | main.rs:63:9:63:9 | s | provenance | | | main.rs:63:13:63:22 | source(...) | main.rs:63:9:63:9 | s | provenance | |
| main.rs:64:16:64:16 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:3 |
| main.rs:64:16:64:16 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:4 | | main.rs:64:16:64:16 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:4 |
| main.rs:64:16:64:16 | s | main.rs:64:16:64:25 | s.as_str() | provenance | MaD:5 |
| main.rs:68:9:68:9 | s | main.rs:70:34:70:61 | MacroExpr | provenance | | | main.rs:68:9:68:9 | s | main.rs:70:34:70:61 | MacroExpr | provenance | |
| main.rs:68:9:68:9 | s | main.rs:73:34:73:59 | MacroExpr | provenance | | | main.rs:68:9:68:9 | s | main.rs:73:34:73:59 | MacroExpr | provenance | |
| main.rs:68:13:68:22 | source(...) | main.rs:68:9:68:9 | s | provenance | | | main.rs:68:13:68:22 | source(...) | main.rs:68:9:68:9 | s | provenance | |
| main.rs:70:9:70:18 | formatted1 | main.rs:71:10:71:19 | formatted1 | provenance | | | main.rs:70:9:70:18 | formatted1 | main.rs:71:10:71:19 | formatted1 | provenance | |
| main.rs:70:22:70:62 | ...::format(...) | main.rs:70:9:70:18 | formatted1 | provenance | | | main.rs:70:22:70:62 | ...::format(...) | main.rs:70:9:70:18 | formatted1 | provenance | |
| main.rs:70:34:70:61 | MacroExpr | main.rs:70:22:70:62 | ...::format(...) | provenance | MaD:5 | | main.rs:70:34:70:61 | MacroExpr | main.rs:70:22:70:62 | ...::format(...) | provenance | MaD:6 |
| main.rs:73:9:73:18 | formatted2 | main.rs:74:10:74:19 | formatted2 | provenance | | | main.rs:73:9:73:18 | formatted2 | main.rs:74:10:74:19 | formatted2 | provenance | |
| main.rs:73:22:73:60 | ...::format(...) | main.rs:73:9:73:18 | formatted2 | provenance | | | main.rs:73:22:73:60 | ...::format(...) | main.rs:73:9:73:18 | formatted2 | provenance | |
| main.rs:73:34:73:59 | MacroExpr | main.rs:73:22:73:60 | ...::format(...) | provenance | MaD:5 | | main.rs:73:34:73:59 | MacroExpr | main.rs:73:22:73:60 | ...::format(...) | provenance | MaD:6 |
| main.rs:76:9:76:13 | width | main.rs:77:34:77:74 | MacroExpr | provenance | | | main.rs:76:9:76:13 | width | main.rs:77:34:77:74 | MacroExpr | provenance | |
| main.rs:76:17:76:32 | source_usize(...) | main.rs:76:9:76:13 | width | provenance | | | main.rs:76:17:76:32 | source_usize(...) | main.rs:76:9:76:13 | width | provenance | |
| main.rs:77:9:77:18 | formatted3 | main.rs:78:10:78:19 | formatted3 | provenance | | | main.rs:77:9:77:18 | formatted3 | main.rs:78:10:78:19 | formatted3 | provenance | |
| main.rs:77:22:77:75 | ...::format(...) | main.rs:77:9:77:18 | formatted3 | provenance | | | main.rs:77:22:77:75 | ...::format(...) | main.rs:77:9:77:18 | formatted3 | provenance | |
| main.rs:77:34:77:74 | MacroExpr | main.rs:77:22:77:75 | ...::format(...) | provenance | MaD:5 | | main.rs:77:34:77:74 | MacroExpr | main.rs:77:22:77:75 | ...::format(...) | provenance | MaD:6 |
| main.rs:82:9:82:10 | s1 | main.rs:86:18:86:25 | MacroExpr | provenance | | | main.rs:82:9:82:10 | s1 | main.rs:86:18:86:25 | MacroExpr | provenance | |
| main.rs:82:9:82:10 | s1 | main.rs:87:18:87:32 | MacroExpr | provenance | | | main.rs:82:9:82:10 | s1 | main.rs:87:18:87:32 | MacroExpr | provenance | |
| main.rs:82:14:82:23 | source(...) | main.rs:82:9:82:10 | s1 | provenance | | | main.rs:82:14:82:23 | source(...) | main.rs:82:9:82:10 | s1 | provenance | |
| main.rs:86:10:86:16 | res | main.rs:86:18:86:25 | { ... } | provenance | | | main.rs:86:10:86:16 | res | main.rs:86:18:86:25 | { ... } | provenance | |
| main.rs:86:18:86:25 | ...::format(...) | main.rs:86:10:86:16 | res | provenance | | | main.rs:86:18:86:25 | ...::format(...) | main.rs:86:10:86:16 | res | provenance | |
| main.rs:86:18:86:25 | ...::must_use(...) | main.rs:86:10:86:26 | MacroExpr | provenance | | | main.rs:86:18:86:25 | ...::must_use(...) | main.rs:86:10:86:26 | MacroExpr | provenance | |
| main.rs:86:18:86:25 | MacroExpr | main.rs:86:18:86:25 | ...::format(...) | provenance | MaD:5 | | main.rs:86:18:86:25 | MacroExpr | main.rs:86:18:86:25 | ...::format(...) | provenance | MaD:6 |
| main.rs:86:18:86:25 | { ... } | main.rs:86:18:86:25 | ...::must_use(...) | provenance | MaD:6 | | main.rs:86:18:86:25 | { ... } | main.rs:86:18:86:25 | ...::must_use(...) | provenance | MaD:7 |
| main.rs:87:10:87:16 | res | main.rs:87:18:87:32 | { ... } | provenance | | | main.rs:87:10:87:16 | res | main.rs:87:18:87:32 | { ... } | provenance | |
| main.rs:87:18:87:32 | ...::format(...) | main.rs:87:10:87:16 | res | provenance | | | main.rs:87:18:87:32 | ...::format(...) | main.rs:87:10:87:16 | res | provenance | |
| main.rs:87:18:87:32 | ...::must_use(...) | main.rs:87:10:87:33 | MacroExpr | provenance | | | main.rs:87:18:87:32 | ...::must_use(...) | main.rs:87:10:87:33 | MacroExpr | provenance | |
| main.rs:87:18:87:32 | MacroExpr | main.rs:87:18:87:32 | ...::format(...) | provenance | MaD:5 | | main.rs:87:18:87:32 | MacroExpr | main.rs:87:18:87:32 | ...::format(...) | provenance | MaD:6 |
| main.rs:87:18:87:32 | { ... } | main.rs:87:18:87:32 | ...::must_use(...) | provenance | MaD:6 | | main.rs:87:18:87:32 | { ... } | main.rs:87:18:87:32 | ...::must_use(...) | provenance | MaD:7 |
nodes nodes
| main.rs:26:9:26:9 | s | semmle.label | s | | main.rs:26:9:26:9 | s | semmle.label | s |
| main.rs:26:13:26:22 | source(...) | semmle.label | source(...) | | main.rs:26:13:26:22 | source(...) | semmle.label | source(...) |

View File

@@ -45,12 +45,18 @@ edges
| src/main.rs:98:21:98:53 | ... .unwrap() | src/main.rs:98:9:98:17 | file_path | provenance | | | src/main.rs:98:21:98:53 | ... .unwrap() | src/main.rs:98:9:98:17 | file_path | provenance | |
| src/main.rs:99:24:99:32 | file_path | src/main.rs:99:5:99:22 | ...::read_to_string | provenance | MaD:6 Sink:MaD:6 | | src/main.rs:99:24:99:32 | file_path | src/main.rs:99:5:99:22 | ...::read_to_string | provenance | MaD:6 Sink:MaD:6 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:104:33:104:37 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:104:33:104:37 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:104:33:104:45 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:106:39:106:43 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:106:39:106:43 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:106:39:106:51 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:109:41:109:45 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:109:41:109:45 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:109:41:109:53 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:112:45:112:49 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:112:45:112:49 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:112:45:112:57 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:115:39:115:43 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:115:39:115:43 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:122:27:122:31 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:122:27:122:31 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:122:27:122:39 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:123:37:123:41 | path1 | provenance | | | src/main.rs:103:9:103:13 | path1 | src/main.rs:123:37:123:41 | path1 | provenance | |
| src/main.rs:103:9:103:13 | path1 | src/main.rs:123:37:123:49 | path1.clone() | provenance | MaD:8 |
| src/main.rs:103:17:103:30 | ...::args | src/main.rs:103:17:103:32 | ...::args(...) [element] | provenance | Src:MaD:7 | | src/main.rs:103:17:103:30 | ...::args | src/main.rs:103:17:103:32 | ...::args(...) [element] | provenance | Src:MaD:7 |
| src/main.rs:103:17:103:32 | ...::args(...) [element] | src/main.rs:103:17:103:39 | ... .nth(...) [Some] | provenance | MaD:9 | | src/main.rs:103:17:103:32 | ...::args(...) [element] | src/main.rs:103:17:103:39 | ... .nth(...) [Some] | provenance | MaD:9 |
| src/main.rs:103:17:103:39 | ... .nth(...) [Some] | src/main.rs:103:17:103:48 | ... .unwrap() | provenance | MaD:10 | | src/main.rs:103:17:103:39 | ... .nth(...) [Some] | src/main.rs:103:17:103:48 | ... .unwrap() | provenance | MaD:10 |

View File

@@ -22,6 +22,7 @@
| lifetime.rs:667:14:667:17 | ref1 | lifetime.rs:655:11:655:25 | &raw const str2 | lifetime.rs:667:14:667:17 | ref1 | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:651:7:651:10 | str2 | str2 | | lifetime.rs:667:14:667:17 | ref1 | lifetime.rs:655:11:655:25 | &raw const str2 | lifetime.rs:667:14:667:17 | ref1 | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:651:7:651:10 | str2 | str2 |
| lifetime.rs:789:12:789:13 | p1 | lifetime.rs:781:9:781:19 | &my_local10 | lifetime.rs:789:12:789:13 | p1 | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:779:6:779:15 | my_local10 | my_local10 | | lifetime.rs:789:12:789:13 | p1 | lifetime.rs:781:9:781:19 | &my_local10 | lifetime.rs:789:12:789:13 | p1 | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:779:6:779:15 | my_local10 | my_local10 |
| lifetime.rs:808:23:808:25 | ptr | lifetime.rs:798:9:798:12 | &val | lifetime.rs:808:23:808:25 | ptr | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:796:6:796:8 | val | val | | lifetime.rs:808:23:808:25 | ptr | lifetime.rs:798:9:798:12 | &val | lifetime.rs:808:23:808:25 | ptr | Access of a pointer to $@ after its lifetime has ended. | lifetime.rs:796:6:796:8 | val | val |
| main.rs:64:23:64:24 | p2 | main.rs:44:26:44:28 | &b2 | main.rs:64:23:64:24 | p2 | Access of a pointer to $@ after its lifetime has ended. | main.rs:43:13:43:14 | b2 | b2 |
edges edges
| deallocation.rs:148:6:148:7 | p1 | deallocation.rs:151:14:151:15 | p1 | provenance | | | deallocation.rs:148:6:148:7 | p1 | deallocation.rs:151:14:151:15 | p1 | provenance | |
| deallocation.rs:148:6:148:7 | p1 | deallocation.rs:158:14:158:15 | p1 | provenance | | | deallocation.rs:148:6:148:7 | p1 | deallocation.rs:158:14:158:15 | p1 | provenance | |
@@ -163,7 +164,7 @@ edges
| lifetime.rs:443:6:443:7 | p1 | lifetime.rs:446:13:446:14 | p1 | provenance | | | lifetime.rs:443:6:443:7 | p1 | lifetime.rs:446:13:446:14 | p1 | provenance | |
| lifetime.rs:443:6:443:7 | p1 | lifetime.rs:450:2:450:10 | return p1 | provenance | | | lifetime.rs:443:6:443:7 | p1 | lifetime.rs:450:2:450:10 | return p1 | provenance | |
| lifetime.rs:443:23:443:44 | ...::from_ref(...) | lifetime.rs:443:6:443:7 | p1 | provenance | | | lifetime.rs:443:23:443:44 | ...::from_ref(...) | lifetime.rs:443:6:443:7 | p1 | provenance | |
| lifetime.rs:443:42:443:43 | r1 | lifetime.rs:443:23:443:44 | ...::from_ref(...) | provenance | MaD:1 | | lifetime.rs:443:42:443:43 | r1 | lifetime.rs:443:23:443:44 | ...::from_ref(...) | provenance | MaD:3 |
| lifetime.rs:450:2:450:10 | return p1 | lifetime.rs:454:11:454:29 | get_ptr_from_ref(...) | provenance | | | lifetime.rs:450:2:450:10 | return p1 | lifetime.rs:454:11:454:29 | get_ptr_from_ref(...) | provenance | |
| lifetime.rs:450:2:450:10 | return p1 | lifetime.rs:460:13:460:31 | get_ptr_from_ref(...) | provenance | | | lifetime.rs:450:2:450:10 | return p1 | lifetime.rs:460:13:460:31 | get_ptr_from_ref(...) | provenance | |
| lifetime.rs:454:6:454:7 | p1 | lifetime.rs:459:13:459:14 | p1 | provenance | | | lifetime.rs:454:6:454:7 | p1 | lifetime.rs:459:13:459:14 | p1 | provenance | |
@@ -212,8 +213,21 @@ edges
| lifetime.rs:798:9:798:12 | &val | lifetime.rs:798:2:798:12 | return ... | provenance | | | lifetime.rs:798:9:798:12 | &val | lifetime.rs:798:2:798:12 | return ... | provenance | |
| lifetime.rs:802:6:802:8 | ptr | lifetime.rs:808:23:808:25 | ptr | provenance | | | lifetime.rs:802:6:802:8 | ptr | lifetime.rs:808:23:808:25 | ptr | provenance | |
| lifetime.rs:802:12:802:24 | get_pointer(...) | lifetime.rs:802:6:802:8 | ptr | provenance | | | lifetime.rs:802:12:802:24 | get_pointer(...) | lifetime.rs:802:6:802:8 | ptr | provenance | |
| main.rs:18:9:18:10 | p1 [&ref] | main.rs:21:19:21:20 | p1 | provenance | |
| main.rs:18:9:18:10 | p1 [&ref] | main.rs:29:19:29:20 | p1 | provenance | |
| main.rs:18:14:18:29 | ...::as_ptr(...) [&ref] | main.rs:18:9:18:10 | p1 [&ref] | provenance | |
| main.rs:18:26:18:28 | &b1 | main.rs:18:14:18:29 | ...::as_ptr(...) [&ref] | provenance | MaD:2 |
| main.rs:44:9:44:10 | p2 [&ref] | main.rs:51:23:51:24 | p2 | provenance | |
| main.rs:44:9:44:10 | p2 [&ref] | main.rs:64:23:64:24 | p2 | provenance | |
| main.rs:44:14:44:29 | ...::as_ptr(...) [&ref] | main.rs:44:9:44:10 | p2 [&ref] | provenance | |
| main.rs:44:26:44:28 | &b2 | main.rs:44:14:44:29 | ...::as_ptr(...) [&ref] | provenance | MaD:2 |
| main.rs:47:9:47:10 | p3 [&ref] | main.rs:52:23:52:24 | p3 | provenance | |
| main.rs:47:14:47:37 | ...::as_mut_ptr(...) [&ref] | main.rs:47:9:47:10 | p3 [&ref] | provenance | |
| main.rs:47:30:47:36 | &mut b3 | main.rs:47:14:47:37 | ...::as_mut_ptr(...) [&ref] | provenance | MaD:1 |
models models
| 1 | Summary: core::ptr::from_ref; Argument[0]; ReturnValue; value | | 1 | Summary: <alloc::boxed::Box>::as_mut_ptr; Argument[0].Reference.Reference; ReturnValue.Reference; value |
| 2 | Summary: <alloc::boxed::Box>::as_ptr; Argument[0].Reference.Reference; ReturnValue.Reference; value |
| 3 | Summary: core::ptr::from_ref; Argument[0]; ReturnValue; value |
nodes nodes
| deallocation.rs:148:6:148:7 | p1 | semmle.label | p1 | | deallocation.rs:148:6:148:7 | p1 | semmle.label | p1 |
| deallocation.rs:148:30:148:38 | &raw const my_buffer | semmle.label | &raw const my_buffer | | deallocation.rs:148:30:148:38 | &raw const my_buffer | semmle.label | &raw const my_buffer |
@@ -440,4 +454,18 @@ nodes
| lifetime.rs:802:6:802:8 | ptr | semmle.label | ptr | | lifetime.rs:802:6:802:8 | ptr | semmle.label | ptr |
| lifetime.rs:802:12:802:24 | get_pointer(...) | semmle.label | get_pointer(...) | | lifetime.rs:802:12:802:24 | get_pointer(...) | semmle.label | get_pointer(...) |
| lifetime.rs:808:23:808:25 | ptr | semmle.label | ptr | | lifetime.rs:808:23:808:25 | ptr | semmle.label | ptr |
| main.rs:18:9:18:10 | p1 [&ref] | semmle.label | p1 [&ref] |
| main.rs:18:14:18:29 | ...::as_ptr(...) [&ref] | semmle.label | ...::as_ptr(...) [&ref] |
| main.rs:18:26:18:28 | &b1 | semmle.label | &b1 |
| main.rs:21:19:21:20 | p1 | semmle.label | p1 |
| main.rs:29:19:29:20 | p1 | semmle.label | p1 |
| main.rs:44:9:44:10 | p2 [&ref] | semmle.label | p2 [&ref] |
| main.rs:44:14:44:29 | ...::as_ptr(...) [&ref] | semmle.label | ...::as_ptr(...) [&ref] |
| main.rs:44:26:44:28 | &b2 | semmle.label | &b2 |
| main.rs:47:9:47:10 | p3 [&ref] | semmle.label | p3 [&ref] |
| main.rs:47:14:47:37 | ...::as_mut_ptr(...) [&ref] | semmle.label | ...::as_mut_ptr(...) [&ref] |
| main.rs:47:30:47:36 | &mut b3 | semmle.label | &mut b3 |
| main.rs:51:23:51:24 | p2 | semmle.label | p2 |
| main.rs:52:23:52:24 | p3 | semmle.label | p3 |
| main.rs:64:23:64:24 | p2 | semmle.label | p2 |
subpaths subpaths

View File

@@ -7,197 +7,201 @@ mod lifetime;
use lifetime::*; use lifetime::*;
fn use_the_heap() { fn use_the_heap() {
let _a = Box::new(0x7FFFFFFF); let _a = Box::new(0x7FFFFFFF);
let _b = Box::new(0x7FFFFFFF); let _b = Box::new(0x7FFFFFFF);
} }
// --- boxes --- // --- boxes ---
pub fn test_boxes_into() { pub fn test_boxes_into() {
let b1: Box<i64> = Box::new(7); // b1 owns the memory for '50' let b1: Box<i64> = Box::new(7); // b1 owns the memory for '50'
let p1 = Box::as_ptr(&b1); // b1 still owns the memory let p1 = Box::as_ptr(&b1); // b1 still owns the memory
unsafe { unsafe {
let v1 = *p1; // GOOD let v1 = *p1; // GOOD
println!(" v1 = {v1}"); println!(" v1 = {v1}");
} }
let v2 = Box::into_inner(b1); // b1 is explicitly freed here, thus p1 is dangling let v2 = Box::into_inner(b1); // b1 is explicitly freed here, thus p1 is dangling
println!(" v2 = {v2}"); println!(" v2 = {v2}");
unsafe { unsafe {
let v3 = *p1; // $ MISSING: Alert let v3 = *p1; // $ MISSING: Alert
println!(" v3 = {v3} (!)"); // corrupt in practice println!(" v3 = {v3} (!)"); // corrupt in practice
} }
} }
pub fn test_boxes_1(mode: i32) { pub fn test_boxes_1(mode: i32) {
let p1: *const i64; let p1: *const i64;
let p2: *const i64; let p2: *const i64;
let p3: *mut i64; let p3: *mut i64;
{ {
let b1: Box<i64> = Box::new(1); let b1: Box<i64> = Box::new(1);
p1 = Box::into_raw(b1); // now owned by p1 p1 = Box::into_raw(b1); // now owned by p1
let b2: Box<i64> = Box::new(2); let b2: Box<i64> = Box::new(2);
p2 = Box::as_ptr(&b2); // still owned by b2 p2 = Box::as_ptr(&b2); // $ Source[rust/access-after-lifetime-ended]=b2 -- still owned by b2
let mut b3: Box<i64> = Box::new(3); let mut b3: Box<i64> = Box::new(3);
p3 = Box::as_mut_ptr(&mut b3); // still owned by b3 p3 = Box::as_mut_ptr(&mut b3); // still owned by b3
unsafe { unsafe {
let v1 = *p1; // GOOD let v1 = *p1; // GOOD
let v2 = *p2; // GOOD let v2 = *p2; // GOOD
let v3 = *p3; // GOOD let v3 = *p3; // GOOD
println!(" v1 = {v1}"); println!(" v1 = {v1}");
println!(" v2 = {v2}"); println!(" v2 = {v2}");
println!(" v3 = {v3}"); println!(" v3 = {v3}");
*p3 = 4; *p3 = 4;
} }
} // (b2, b3 go out of scope, thus p2, p3 are dangling) } // (b2, b3 go out of scope, thus p2, p3 are dangling)
unsafe { unsafe {
if mode == 0 { if mode == 0 {
// reads // reads
let v4 = *p1; // GOOD let v4 = *p1; // GOOD
let v5 = *p2; // $ MISSING: Alert let v5 = *p2; // $ Alert[rust/access-after-lifetime-ended]=b2
let v6 = *p3; // $ MISSING: Alert let v6 = *p3; // $ MISSING: Alert
println!(" v4 = {v4}"); println!(" v4 = {v4}");
println!(" v5 = {v5} (!)"); // corrupt in practice println!(" v5 = {v5} (!)"); // corrupt in practice
println!(" v6 = {v6} (!)"); // corrupt in practice println!(" v6 = {v6} (!)"); // corrupt in practice
} }
if mode == 10 { if mode == 10 {
// write // write
*p3 = 5; // $ MISSING: Alert *p3 = 5; // $ MISSING: Alert
use_the_heap(); // "malloc: Heap corruption detected" use_the_heap(); // "malloc: Heap corruption detected"
} }
} }
} }
pub fn test_boxes_2() { pub fn test_boxes_2() {
let b1: Box<i64> = Box::new(6); // b1 owns the memory let b1: Box<i64> = Box::new(6); // b1 owns the memory
let p1 = Box::into_raw(b1); // now p1 owns the memory let p1 = Box::into_raw(b1); // now p1 owns the memory
unsafe { unsafe {
let _b2 = Box::from_raw(p1); // now _b2 owns the memory let _b2 = Box::from_raw(p1); // now _b2 owns the memory
let v1 = *p1; // GOOD let v1 = *p1; // GOOD
println!(" v1 = {v1}"); println!(" v1 = {v1}");
} // (_b2 goes out of scope, thus the memory is freed and p1 is dangling) } // (_b2 goes out of scope, thus the memory is freed and p1 is dangling)
unsafe { unsafe {
let v2 = *p1; // $ MISSING: Alert let v2 = *p1; // $ MISSING: Alert
println!(" v2 = {v2} (!)"); // corrupt in practice println!(" v2 = {v2} (!)"); // corrupt in practice
} }
} }
// --- main --- // --- main ---
fn main() { fn main() {
let mode = std::env::args().nth(1).unwrap_or("0".to_string()).parse::<i32>().unwrap_or(0); let mode = std::env::args()
// mode = which test cases to explore (0 should be safe; some will crash / segfault). .nth(1)
println!("mode = {mode}"); .unwrap_or("0".to_string())
.parse::<i32>()
.unwrap_or(0);
// mode = which test cases to explore (0 should be safe; some will crash / segfault).
println!("mode = {mode}");
println!("test_boxes_into:"); println!("test_boxes_into:");
test_boxes_into(); test_boxes_into();
println!("test_boxes_1:"); println!("test_boxes_1:");
test_boxes_1(mode); test_boxes_1(mode);
println!("test_boxes_2:"); println!("test_boxes_2:");
test_boxes_2(); test_boxes_2();
// --- // ---
println!("test_alloc:"); println!("test_alloc:");
test_alloc(mode); test_alloc(mode);
println!("test_alloc_array:"); println!("test_alloc_array:");
test_alloc_array(mode); test_alloc_array(mode);
println!("test_libc:"); println!("test_libc:");
test_libc(); test_libc();
println!("test_ptr_invalid:"); println!("test_ptr_invalid:");
test_ptr_invalid(mode); test_ptr_invalid(mode);
println!("test_drop:"); println!("test_drop:");
test_drop(); test_drop();
println!("test_ptr_drop:"); println!("test_ptr_drop:");
test_ptr_drop(mode); test_ptr_drop(mode);
println!("test_qhelp_tests:"); println!("test_qhelp_tests:");
test_qhelp_examples(); test_qhelp_examples();
println!("test_vec_reserve:"); println!("test_vec_reserve:");
test_vec_reserve(); test_vec_reserve();
// --- // ---
println!("test_local_dangling:"); println!("test_local_dangling:");
test_local_dangling(); test_local_dangling();
println!("test_local_in_scope:"); println!("test_local_in_scope:");
test_local_in_scope(mode); test_local_in_scope(mode);
println!("test_static:"); println!("test_static:");
test_static(mode); test_static(mode);
println!("test_call_contexts:"); println!("test_call_contexts:");
test_call_contexts(); test_call_contexts();
println!("test_call_contexts_rec:"); println!("test_call_contexts_rec:");
test_call_contexts_rec(); test_call_contexts_rec();
println!("test_loop:"); println!("test_loop:");
test_loop(); test_loop();
println!("test_enums:"); println!("test_enums:");
test_enums(); test_enums();
println!("test_recursive_enums:"); println!("test_recursive_enums:");
test_recursive_enums(); test_recursive_enums();
println!("test_ptr_to_struct:"); println!("test_ptr_to_struct:");
test_ptr_to_struct(mode); test_ptr_to_struct(mode);
println!("test_ptr_from_ref:"); println!("test_ptr_from_ref:");
test_ptr_from_ref(); test_ptr_from_ref();
println!("test_rc:"); println!("test_rc:");
test_rc(); test_rc();
println!("test_closures:"); println!("test_closures:");
test_closures(); test_closures();
println!("test_async:"); println!("test_async:");
test_async(); test_async();
println!("test_lifetime_annotations:"); println!("test_lifetime_annotations:");
test_lifetime_annotations(); test_lifetime_annotations();
println!("test_implicit_derefs:"); println!("test_implicit_derefs:");
test_implicit_derefs(); test_implicit_derefs();
println!("test_members:"); println!("test_members:");
test_members(); test_members();
println!("test_enum_members:"); println!("test_enum_members:");
test_enum_members(); test_enum_members();
println!("test_macros:"); println!("test_macros:");
test_macros(); test_macros();
println!("test_unsafe_function:"); println!("test_unsafe_function:");
unsafe { unsafe {
test_unsafe_function(); test_unsafe_function();
} }
println!("test_lifetimes_example_bad:"); println!("test_lifetimes_example_bad:");
test_lifetimes_example_bad(); test_lifetimes_example_bad();
println!("test_lifetimes_example_good:"); println!("test_lifetimes_example_good:");
test_lifetimes_example_good(); test_lifetimes_example_good();
} }