Rust: Add taint from children of format_args to format_args

This commit is contained in:
Simon Friis Vindum
2025-01-03 14:06:47 +01:00
parent 2ef9339d00
commit 0d19fb6040
4 changed files with 67 additions and 3 deletions

View File

@@ -173,6 +173,32 @@ final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCall
*/
final class CallExprCfgNode extends CallExprBaseCfgNode, Nodes::CallExprCfgNode { }
/**
* A FormatArgsExpr. For example:
* ```rust
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
*/
final class FormatArgsExprCfgNode extends Nodes::FormatArgsExprCfgNode {
private FormatArgsExprChildMapping node;
ExprCfgNode getArgumentExpr(int i) {
any(ChildMapping mapping).hasCfgChild(node, node.getArg(i).getExpr(), this, result)
}
FormatTemplateVariableAccessCfgNode getFormatTemplateVariableAccess(int i) {
exists(FormatTemplateVariableAccess v |
v.getArgument() = node.getFormat(i).getArgument() and
result.getFormatTemplateVariableAccess() = v and
any(ChildMapping mapping).hasCfgChild(node, v, this, result)
)
}
}
final class MacroCallCfgNode extends Nodes::MacroCallCfgNode {
private MacroCallChildMapping node;

View File

@@ -46,6 +46,10 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
RustDataFlow::readStep(pred, cs, succ) and
cs.getContent() instanceof ArrayElementContent
)
or
exists(FormatArgsExprCfgNode format | succ.asExpr() = format |
pred.asExpr() = [format.getArgumentExpr(_), format.getFormatTemplateVariableAccess(_)]
)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),

View File

@@ -1,5 +1,6 @@
models
| 1 | Summary: lang:alloc; <crate::string::String>::as_str; Argument[self]; ReturnValue; taint |
| 2 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint |
edges
| 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 | |
@@ -12,6 +13,20 @@ edges
| main.rs:63:9:63:9 | s | main.rs:64:16:64:16 | 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:1 |
| 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: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: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:2 |
| 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:34:73:59 | MacroExpr | main.rs:73:22:73:60 | ...::format(...) | provenance | MaD:2 |
| 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: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:34:77:74 | MacroExpr | main.rs:77:22:77:75 | ...::format(...) | provenance | MaD:2 |
nodes
| main.rs:26:9:26:9 | s | semmle.label | s |
| main.rs:26:13:26:22 | source(...) | semmle.label | source(...) |
@@ -27,9 +42,28 @@ nodes
| main.rs:63:13:63:22 | source(...) | semmle.label | source(...) |
| main.rs:64:16:64:16 | s | semmle.label | s |
| main.rs:64:16:64:25 | s.as_str(...) | semmle.label | s.as_str(...) |
| main.rs:68:9:68:9 | s | semmle.label | s |
| main.rs:68:13:68:22 | source(...) | semmle.label | source(...) |
| main.rs:70:9:70:18 | formatted1 | semmle.label | formatted1 |
| main.rs:70:22:70:62 | ...::format(...) | semmle.label | ...::format(...) |
| main.rs:70:34:70:61 | MacroExpr | semmle.label | MacroExpr |
| main.rs:71:10:71:19 | formatted1 | semmle.label | formatted1 |
| main.rs:73:9:73:18 | formatted2 | semmle.label | formatted2 |
| main.rs:73:22:73:60 | ...::format(...) | semmle.label | ...::format(...) |
| main.rs:73:34:73:59 | MacroExpr | semmle.label | MacroExpr |
| main.rs:74:10:74:19 | formatted2 | semmle.label | formatted2 |
| main.rs:76:9:76:13 | width | semmle.label | width |
| main.rs:76:17:76:32 | source_usize(...) | semmle.label | source_usize(...) |
| main.rs:77:9:77:18 | formatted3 | semmle.label | formatted3 |
| main.rs:77:22:77:75 | ...::format(...) | semmle.label | ...::format(...) |
| main.rs:77:34:77:74 | MacroExpr | semmle.label | MacroExpr |
| main.rs:78:10:78:19 | formatted3 | semmle.label | formatted3 |
subpaths
testFailures
#select
| main.rs:28:16:28:21 | sliced | main.rs:26:13:26:22 | source(...) | main.rs:28:16:28:21 | sliced | $@ | main.rs:26:13:26:22 | source(...) | source(...) |
| main.rs:38:10:38:11 | s4 | main.rs:32:14:32:23 | source(...) | main.rs:38:10:38:11 | s4 | $@ | main.rs:32:14:32:23 | source(...) | source(...) |
| main.rs:64:16:64:25 | s.as_str(...) | main.rs:63:13:63:22 | source(...) | main.rs:64:16:64:25 | s.as_str(...) | $@ | main.rs:63:13:63:22 | source(...) | source(...) |
| main.rs:71:10:71:19 | formatted1 | main.rs:68:13:68:22 | source(...) | main.rs:71:10:71:19 | formatted1 | $@ | main.rs:68:13:68:22 | source(...) | source(...) |
| main.rs:74:10:74:19 | formatted2 | main.rs:68:13:68:22 | source(...) | main.rs:74:10:74:19 | formatted2 | $@ | main.rs:68:13:68:22 | source(...) | source(...) |
| main.rs:78:10:78:19 | formatted3 | main.rs:76:17:76:32 | source_usize(...) | main.rs:78:10:78:19 | formatted3 | $@ | main.rs:76:17:76:32 | source_usize(...) | source_usize(...) |

View File

@@ -68,14 +68,14 @@ fn format_args_built_in() {
let s = source(88);
let formatted1 = fmt::format(format_args!("Hello {}!", s));
sink(formatted1); // $ MISSING: hasTaintFlow=88
sink(formatted1); // $ hasTaintFlow=88
let formatted2 = fmt::format(format_args!("Hello {s}!"));
sink(formatted2); // $ MISSING: hasTaintFlow=88
sink(formatted2); // $ hasTaintFlow=88
let width = source_usize(10);
let formatted3 = fmt::format(format_args!("Hello {:width$}!", "World"));
sink(formatted3); // $ MISSING: hasTaintFlow=10
sink(formatted3); // $ hasTaintFlow=10
}
fn format_macro() {