diff --git a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml index 77f0212b6c15..de34d13aeaa9 100644 --- a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml @@ -3,5 +3,12 @@ extensions: pack: codeql/rust-all extensible: sourceModel data: - # Alloc - ["repo:https://github.com/rust-lang/libc:libc", "::free", "Argument[0]", "pointer-invalidate", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: sinkModel + data: + - ["repo:https://github.com/rust-lang/libc:libc", "::malloc", "Argument[0]", "alloc-size", "manual"] + - ["repo:https://github.com/rust-lang/libc:libc", "::aligned_alloc", "Argument[1]", "alloc-size", "manual"] + - ["repo:https://github.com/rust-lang/libc:libc", "::calloc", "Argument[0,1]", "alloc-size", "manual"] + - ["repo:https://github.com/rust-lang/libc:libc", "::realloc", "Argument[1]", "alloc-size", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml index fba9ae5fea33..3ac1ad0af14b 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml @@ -1,4 +1,30 @@ extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + # Alloc + - ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: sinkModel + data: + # Alloc + - ["lang:alloc", "crate::alloc::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "crate::alloc::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "crate::alloc::realloc", "Argument[2]", "alloc-size", "manual"] + - ["lang:std", "::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["lang:std", "::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["lang:std", "::allocate", "Argument[0]", "alloc-layout", "manual"] + - ["lang:std", "::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["lang:std", "::grow", "Argument[2]", "alloc-layout", "manual"] + - ["lang:std", "::grow_zeroed", "Argument[2]", "alloc-layout", "manual"] + - ["lang:alloc", "::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "::allocate", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["lang:alloc", "::grow", "Argument[2]", "alloc-layout", "manual"] + - ["lang:alloc", "::grow_zeroed", "Argument[2]", "alloc-layout", "manual"] - addsTo: pack: codeql/rust-all extensible: summaryModel @@ -9,9 +35,3 @@ extensions: - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] - - addsTo: - pack: codeql/rust-all - extensible: sourceModel - data: - # Alloc - - ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml index 69c5a1f3ba49..ab95c602d314 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml @@ -17,6 +17,21 @@ extensions: - ["lang:core", "::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] - ["lang:core", "::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] - ["lang:core", "::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + # Layout + - ["lang:core", "::from_size_align", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["lang:core", "::array", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::repeat", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["lang:core", "::repeat", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["lang:core", "::repeat_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::repeat_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::extend", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["lang:core", "::extend", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["lang:core", "::extend_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::extend_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::align_to", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["lang:core", "::size", "Argument[self]", "ReturnValue", "taint", "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"] diff --git a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll new file mode 100644 index 000000000000..b8ab16090d19 --- /dev/null +++ b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll @@ -0,0 +1,95 @@ +/** + * Provides classes and predicates for reasoning about uncontrolled allocation + * size vulnerabilities. + */ + +import rust +private import codeql.rust.Concepts +private import codeql.rust.dataflow.DataFlow +private import codeql.rust.dataflow.FlowSink +private import codeql.rust.controlflow.ControlFlowGraph as Cfg +private import codeql.rust.controlflow.CfgNodes as CfgNodes + +/** + * Provides default sources, sinks and barriers for detecting uncontrolled + * allocation size vulnerabilities, as well as extension points for adding your own. + */ +module UncontrolledAllocationSize { + /** + * A data flow sink for uncontrolled allocation size vulnerabilities. + */ + abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "UncontrolledAllocationSize" } + } + + /** + * A barrier for uncontrolled allocation size vulnerabilities. + */ + abstract class Barrier extends DataFlow::Node { } + + /** + * A sink for uncontrolled allocation size from model data. + */ + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { sinkNode(this, ["alloc-size", "alloc-layout"]) } + } + + /** + * A barrier for uncontrolled allocation size that is an upper bound check / guard. + */ + private class UpperBoundCheckBarrier extends Barrier { + UpperBoundCheckBarrier() { + this = DataFlow::BarrierGuard::getABarrierNode() + } + } + + /** + * Gets the operand on the "greater" (or "greater-or-equal") side + * of this relational expression, that is, the side that is larger + * if the overall expression evaluates to `true`; for example on + * `x <= 20` this is the `20`, and on `y > 0` it is `y`. + */ + private Expr getGreaterOperand(BinaryExpr op) { + op.getOperatorName() = ["<", "<="] and + result = op.getRhs() + or + op.getOperatorName() = [">", ">="] and + result = op.getLhs() + } + + /** + * Gets the operand on the "lesser" (or "lesser-or-equal") side + * of this relational expression, that is, the side that is smaller + * if the overall expression evaluates to `true`; for example on + * `x <= 20` this is `x`, and on `y > 0` it is the `0`. + */ + private Expr getLesserOperand(BinaryExpr op) { + op.getOperatorName() = ["<", "<="] and + result = op.getLhs() + or + op.getOperatorName() = [">", ">="] and + result = op.getRhs() + } + + /** + * Holds if comparison `g` having result `branch` indicates an upper bound for the sub-expression + * `node`. For example when the comparison `x < 10` is true, we have an upper bound for `x`. + */ + private predicate isUpperBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) { + exists(BinaryExpr cmp | g = cmp.getACfgNode() | + node = getLesserOperand(cmp).getACfgNode() and + branch = true + or + node = getGreaterOperand(cmp).getACfgNode() and + branch = false + or + cmp.getOperatorName() = "==" and + [cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and + branch = true + or + cmp.getOperatorName() = "!=" and + [cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and + branch = false + ) + } +} diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp new file mode 100644 index 000000000000..fe5a2582e309 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp @@ -0,0 +1,41 @@ + + + + +

Allocating memory with a size based on user input may allow arbitrary amounts of memory to be +allocated, leading to a crash or a denial-of-service (DoS) attack.

+ +

If the user input is multiplied by a constant, such as the size of a type, the result may +overflow. In a build with the --release flag, Rust performs two's complement wrapping, +with the result that less memory than expected may be allocated. This can lead to buffer overflow +incidents.

+ +
+ + +

Implement a guard to limit the amount of memory that is allocated, and reject the request if +the guard is not met. Ensure that any multiplications in the calculation cannot overflow, either +by guarding their inputs, or using a multiplication routine such as checked_mul that +does not wrap around.

+ +
+ + +

In the following example, an arbitrary amount of memory is allocated based on user input. In +addition, due to the multiplication operation, the result may overflow if a very large value is +provided. This may lead to less memory being allocated than expected by other parts of the program.

+ + +

In the fixed example, the user input is checked against a maximum value. If the check fails, an +error is returned, and both the multiplication and allocation do not take place.

+ + +
+ + +
  • The Rust Programming Language: Data Types - Integer Overflow.
  • + +
    +
    diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql new file mode 100644 index 000000000000..c41257743152 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql @@ -0,0 +1,45 @@ +/** + * @name Uncontrolled allocation size + * @description Allocating memory with a size controlled by an external user can result in + * arbitrary amounts of memory being allocated, leading to a crash or a + * denial-of-service (DoS) attack. + * @kind path-problem + * @problem.severity recommendation + * @security-severity 7.5 + * @precision high + * @id rust/uncontrolled-allocation-size + * @tags reliability + * security + * external/cwe/cwe-770 + * external/cwe/cwe-789 + */ + +import rust +import codeql.rust.Concepts +import codeql.rust.dataflow.DataFlow +import codeql.rust.dataflow.TaintTracking +import codeql.rust.dataflow.internal.DataFlowImpl +import codeql.rust.security.UncontrolledAllocationSizeExtensions + +/** + * A taint-tracking configuration for uncontrolled allocation size vulnerabilities. + */ +module UncontrolledAllocationConfig implements DataFlow::ConfigSig { + import UncontrolledAllocationSize + + predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } +} + +module UncontrolledAllocationFlow = TaintTracking::Global; + +import UncontrolledAllocationFlow::PathGraph + +from UncontrolledAllocationFlow::PathNode source, UncontrolledAllocationFlow::PathNode sink +where UncontrolledAllocationFlow::flowPath(source, sink) +select sink.getNode(), source, sink, + "This allocation size is derived from a $@ and could allocate arbitrary amounts of memory.", + source.getNode(), "user-provided value" diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs new file mode 100644 index 000000000000..40794494f3bf --- /dev/null +++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs @@ -0,0 +1,11 @@ + +fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> { + let num_bytes = user_input.parse::()? * std::mem::size_of::(); + + let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap(); + unsafe { + let buffer = std::alloc::alloc(layout); // BAD: uncontrolled allocation size + + Ok(buffer) + } +} diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs new file mode 100644 index 000000000000..92c9a5b291b5 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs @@ -0,0 +1,17 @@ + +const BUFFER_LIMIT: usize = 10 * 1024; + +fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> { + let size = user_input.parse::()?; + if size > BUFFER_LIMIT { + return Err("Size exceeds limit".into()); + } + let num_bytes = size * std::mem::size_of::(); + + let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap(); + unsafe { + let buffer = std::alloc::alloc(layout); // GOOD + + Ok(buffer) + } +} diff --git a/rust/ql/src/queries/summary/Stats.qll b/rust/ql/src/queries/summary/Stats.qll index ec252c36d701..fe8966bcaaef 100644 --- a/rust/ql/src/queries/summary/Stats.qll +++ b/rust/ql/src/queries/summary/Stats.qll @@ -21,6 +21,7 @@ private import codeql.rust.security.CleartextLoggingExtensions private import codeql.rust.security.CleartextTransmissionExtensions private import codeql.rust.security.SqlInjectionExtensions private import codeql.rust.security.TaintedPathExtensions +private import codeql.rust.security.UncontrolledAllocationSizeExtensions private import codeql.rust.security.WeakSensitiveDataHashingExtensions /** diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 9676fd3f2afe..6edba8b73ba6 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -2161,6 +2161,13 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)].Reference in lang:core::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::as_ref | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::search_tree_for_bifurcation | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::search_tree_for_bifurcation | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::from_str | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::from_str | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::align_to | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::align_to | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::array | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::array | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::extend | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::extend | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::extend_packed | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::extend_packed | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::from_size_align | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::from_size_align | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::repeat | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::repeat | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::repeat_packed | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::repeat_packed | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_insert | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::try_insert | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or_else | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or_else | @@ -2194,6 +2201,8 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/servo/rust-url:url::_::::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/servo/rust-url:url::_::::parse | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:alloc::_::::search_tree_for_bifurcation | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::search_tree_for_bifurcation | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::::extend | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::extend | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::::repeat | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::repeat | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout_ms | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout_ms | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout_while | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout_while | diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected index c02b7a5eed55..c86d5f444d67 100644 --- a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected @@ -2,16 +2,21 @@ | main.rs:6:25:6:30 | ®ex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | ®ex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value | edges | main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | | -| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:65 | -| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1640 | +| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:1 | +| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:3 | | main.rs:4:20:4:66 | ... .unwrap_or(...) | main.rs:4:9:4:16 | username | provenance | | | main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | | | main.rs:5:17:5:45 | res | main.rs:5:25:5:44 | { ... } | provenance | | | main.rs:5:25:5:44 | ...::format(...) | main.rs:5:17:5:45 | res | provenance | | | main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | | -| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:101 | -| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3063 | +| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:2 | +| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:4 | | main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | ®ex | provenance | | +models +| 1 | Source: lang:std; crate::env::var; environment-source; ReturnValue.Field[crate::result::Result::Ok(0)] | +| 2 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | +| 3 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | +| 4 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | nodes | main.rs:4:9:4:16 | username | semmle.label | username | | main.rs:4:20:4:32 | ...::var | semmle.label | ...::var | diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.qlref b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.qlref index bc028b7e20d6..390ef3fe5757 100644 --- a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.qlref +++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.qlref @@ -1,2 +1,4 @@ query: queries/security/CWE-020/RegexInjection.ql -postprocess: utils/test/InlineExpectationsTestQuery.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected new file mode 100644 index 000000000000..8fbaf7659394 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected @@ -0,0 +1,503 @@ +#select +| main.rs:18:13:18:31 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:21:13:21:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:22:13:22:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:23:13:23:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:30:13:30:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:33:13:33:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:37:13:37:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:40:13:40:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:50:13:50:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:51:13:51:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:53:13:53:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:54:13:54:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:59:13:59:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:61:13:61:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:63:13:63:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:64:13:64:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:65:13:65:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:68:13:68:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:88:13:88:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:88:13:88:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:96:17:96:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:96:17:96:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:102:17:102:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:102:17:102:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:103:17:103:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:103:17:103:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:109:17:109:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:109:17:109:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:111:17:111:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:111:17:111:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:146:17:146:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:146:17:146:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:148:17:148:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:148:17:148:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:152:13:152:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:152:13:152:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:155:13:155:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:155:13:155:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:162:17:162:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:162:17:162:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:169:17:169:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:169:17:169:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:177:13:177:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:177:13:177:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:193:32:193:36 | alloc | main.rs:317:13:317:26 | ...::args | main.rs:193:32:193:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:194:32:194:43 | alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:194:32:194:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:195:32:195:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:195:32:195:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:196:32:196:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:196:32:196:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:197:32:197:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:197:32:197:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:198:32:198:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:198:32:198:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:208:40:208:43 | grow | main.rs:317:13:317:26 | ...::args | main.rs:208:40:208:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:210:40:210:50 | grow_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:210:40:210:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:219:13:219:24 | ...::malloc | main.rs:317:13:317:26 | ...::args | main.rs:219:13:219:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:220:13:220:31 | ...::aligned_alloc | main.rs:317:13:317:26 | ...::args | main.rs:220:13:220:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:222:13:222:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:222:13:222:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:223:13:223:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:223:13:223:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value | +| main.rs:284:22:284:38 | ...::alloc | main.rs:308:25:308:38 | ...::args | main.rs:284:22:284:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:308:25:308:38 | ...::args | user-provided value | +edges +| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | | +| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 | +| main.rs:18:41:18:41 | v | main.rs:20:50:20:50 | v | provenance | | +| main.rs:18:41:18:41 | v | main.rs:29:60:29:60 | v | provenance | | +| main.rs:18:41:18:41 | v | main.rs:32:60:32:89 | ... * ... | provenance | | +| main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | | +| main.rs:20:9:20:10 | l2 | main.rs:21:31:21:32 | l2 | provenance | | +| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap() | provenance | MaD:31 | +| main.rs:20:14:20:63 | ... .unwrap() | main.rs:20:9:20:10 | l2 | provenance | | +| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:23 | +| main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:17 | +| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:17 | +| main.rs:21:31:21:32 | l2 | main.rs:24:38:24:39 | l2 | provenance | | +| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | main.rs:22:31:22:53 | ... .unwrap() | provenance | MaD:31 | +| main.rs:22:31:22:53 | ... .unwrap() | main.rs:22:13:22:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | main.rs:23:31:23:53 | ... .unwrap() | provenance | MaD:31 | +| main.rs:23:31:23:53 | ... .unwrap() | main.rs:23:31:23:68 | ... .pad_to_align() | provenance | MaD:25 | +| main.rs:23:31:23:68 | ... .pad_to_align() | main.rs:23:13:23:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:4 Sink:MaD:4 | +| main.rs:29:9:29:10 | l4 | main.rs:30:31:30:32 | l4 | provenance | | +| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | main.rs:29:9:29:10 | l4 | provenance | | +| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:24 | +| main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:32:9:32:10 | l5 | main.rs:33:31:33:32 | l5 | provenance | | +| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | main.rs:32:9:32:10 | l5 | provenance | | +| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:24 | +| main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | | +| main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | | +| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | | +| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:24 | +| main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:28 | +| main.rs:39:9:39:10 | l7 | main.rs:40:31:40:32 | l7 | provenance | | +| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | main.rs:39:9:39:10 | l7 | provenance | | +| main.rs:39:60:39:68 | l6.size() | main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | provenance | MaD:24 | +| main.rs:40:31:40:32 | l7 | main.rs:40:13:40:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:43:44:43:51 | ...: usize | main.rs:50:41:50:41 | v | provenance | | +| main.rs:43:44:43:51 | ...: usize | main.rs:51:41:51:45 | ... + ... | provenance | | +| main.rs:43:44:43:51 | ...: usize | main.rs:53:48:53:48 | v | provenance | | +| main.rs:43:44:43:51 | ...: usize | main.rs:54:48:54:53 | ... * ... | provenance | | +| main.rs:43:44:43:51 | ...: usize | main.rs:58:34:58:34 | v | provenance | | +| main.rs:43:44:43:51 | ...: usize | main.rs:67:46:67:46 | v | provenance | | +| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | provenance | MaD:31 | +| main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | main.rs:50:31:50:53 | ... .0 | provenance | | +| main.rs:50:31:50:53 | ... .0 | main.rs:50:13:50:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 | +| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | provenance | MaD:31 | +| main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | main.rs:51:31:51:57 | ... .0 | provenance | | +| main.rs:51:31:51:57 | ... .0 | main.rs:51:13:51:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 | +| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap() | provenance | MaD:31 | +| main.rs:53:31:53:58 | ... .unwrap() | main.rs:53:13:53:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 | +| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap() | provenance | MaD:31 | +| main.rs:54:31:54:63 | ... .unwrap() | main.rs:54:13:54:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 | +| main.rs:58:9:58:20 | TuplePat [tuple.0] | main.rs:58:10:58:11 | k1 | provenance | | +| main.rs:58:10:58:11 | k1 | main.rs:59:31:59:32 | k1 | provenance | | +| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:30 | +| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | main.rs:58:9:58:20 | TuplePat [tuple.0] | provenance | | +| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:26 | +| main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | | +| main.rs:59:31:59:32 | k1 | main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | provenance | MaD:20 | +| main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | | +| main.rs:59:31:59:32 | k1 | main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | provenance | MaD:22 | +| main.rs:60:9:60:20 | TuplePat [tuple.0] | main.rs:60:10:60:11 | k2 | provenance | | +| main.rs:60:10:60:11 | k2 | main.rs:61:31:61:32 | k2 | provenance | | +| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | provenance | MaD:31 | +| main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | main.rs:60:9:60:20 | TuplePat [tuple.0] | provenance | | +| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:19 | +| main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:62:9:62:20 | TuplePat [tuple.0] | main.rs:62:10:62:11 | k3 | provenance | | +| main.rs:62:10:62:11 | k3 | main.rs:63:31:63:32 | k3 | provenance | | +| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | provenance | MaD:31 | +| main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | main.rs:62:9:62:20 | TuplePat [tuple.0] | provenance | | +| main.rs:63:31:63:32 | k3 | main.rs:63:13:63:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap() | provenance | MaD:31 | +| main.rs:64:31:64:59 | ... .unwrap() | main.rs:64:13:64:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:21 | +| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | main.rs:65:31:65:59 | ... .unwrap() | provenance | MaD:31 | +| main.rs:65:31:65:59 | ... .unwrap() | main.rs:65:13:65:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:67:9:67:10 | l4 | main.rs:68:31:68:32 | l4 | provenance | | +| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap() | provenance | MaD:31 | +| main.rs:67:14:67:56 | ... .unwrap() | main.rs:67:9:67:10 | l4 | provenance | | +| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:86:35:86:42 | ...: usize | main.rs:87:54:87:54 | v | provenance | | +| main.rs:87:9:87:14 | layout | main.rs:88:31:88:36 | layout | provenance | | +| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | main.rs:87:18:87:67 | ... .unwrap() | provenance | MaD:31 | +| main.rs:87:18:87:67 | ... .unwrap() | main.rs:87:9:87:14 | layout | provenance | | +| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 | +| main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:105:33:105:33 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:145:51:145:51 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:151:62:151:62 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:154:62:154:62 | v | provenance | | +| main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | v | provenance | | +| main.rs:92:9:92:10 | l1 | main.rs:96:35:96:36 | l1 | provenance | | +| main.rs:92:9:92:10 | l1 | main.rs:102:35:102:36 | l1 | provenance | | +| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | main.rs:92:14:92:57 | ... .unwrap() | provenance | MaD:31 | +| main.rs:92:14:92:57 | ... .unwrap() | main.rs:92:9:92:10 | l1 | provenance | | +| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:96:35:96:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | | +| main.rs:96:35:96:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | | +| main.rs:101:13:101:14 | l3 | main.rs:103:35:103:36 | l3 | provenance | | +| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | main.rs:101:18:101:61 | ... .unwrap() | provenance | MaD:31 | +| main.rs:101:18:101:61 | ... .unwrap() | main.rs:101:13:101:14 | l3 | provenance | | +| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:102:35:102:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | | +| main.rs:102:35:102:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | | +| main.rs:103:35:103:36 | l3 | main.rs:103:17:103:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:105:33:105:33 | v | main.rs:86:35:86:42 | ...: usize | provenance | | +| main.rs:109:35:109:36 | l1 | main.rs:109:17:109:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:109:35:109:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | | +| main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | | +| main.rs:145:13:145:14 | l9 | main.rs:148:35:148:36 | l9 | provenance | | +| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | main.rs:145:18:145:61 | ... .unwrap() | provenance | MaD:31 | +| main.rs:145:18:145:61 | ... .unwrap() | main.rs:145:13:145:14 | l9 | provenance | | +| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | | +| main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:151:9:151:11 | l10 | main.rs:152:31:152:33 | l10 | provenance | | +| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | main.rs:151:15:151:78 | ... .unwrap() | provenance | MaD:31 | +| main.rs:151:15:151:78 | ... .unwrap() | main.rs:151:9:151:11 | l10 | provenance | | +| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:34 | +| main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:154:9:154:11 | l11 | main.rs:155:31:155:33 | l11 | provenance | | +| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | main.rs:154:15:154:78 | ... .unwrap() | provenance | MaD:31 | +| main.rs:154:15:154:78 | ... .unwrap() | main.rs:154:9:154:11 | l11 | provenance | | +| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:33 | +| main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:161:13:161:15 | l13 | main.rs:162:35:162:37 | l13 | provenance | | +| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | main.rs:161:19:161:68 | ... .unwrap() | provenance | MaD:31 | +| main.rs:161:19:161:68 | ... .unwrap() | main.rs:161:13:161:15 | l13 | provenance | | +| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 | +| main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | | +| main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:177:31:177:32 | l1 | main.rs:177:13:177:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | | +| main.rs:192:9:192:10 | l2 | main.rs:193:38:193:39 | l2 | provenance | | +| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | main.rs:192:14:192:56 | ... .unwrap() | provenance | MaD:31 | +| main.rs:192:14:192:56 | ... .unwrap() | main.rs:192:9:192:10 | l2 | provenance | | +| main.rs:192:46:192:46 | v | main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 | +| main.rs:193:38:193:39 | l2 | main.rs:193:32:193:36 | alloc | provenance | MaD:10 Sink:MaD:10 | +| main.rs:193:38:193:39 | l2 | main.rs:194:45:194:46 | l2 | provenance | | +| main.rs:194:45:194:46 | l2 | main.rs:194:32:194:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 | +| main.rs:194:45:194:46 | l2 | main.rs:195:41:195:42 | l2 | provenance | | +| main.rs:195:41:195:42 | l2 | main.rs:195:32:195:39 | allocate | provenance | MaD:6 Sink:MaD:6 | +| main.rs:195:41:195:42 | l2 | main.rs:196:48:196:49 | l2 | provenance | | +| main.rs:196:48:196:49 | l2 | main.rs:196:32:196:46 | allocate_zeroed | provenance | MaD:7 Sink:MaD:7 | +| main.rs:196:48:196:49 | l2 | main.rs:197:41:197:42 | l2 | provenance | | +| main.rs:197:41:197:42 | l2 | main.rs:197:32:197:39 | allocate | provenance | MaD:1 Sink:MaD:1 | +| main.rs:197:41:197:42 | l2 | main.rs:198:48:198:49 | l2 | provenance | | +| main.rs:198:48:198:49 | l2 | main.rs:198:32:198:46 | allocate_zeroed | provenance | MaD:2 Sink:MaD:2 | +| main.rs:198:48:198:49 | l2 | main.rs:208:53:208:54 | l2 | provenance | | +| main.rs:198:48:198:49 | l2 | main.rs:210:60:210:61 | l2 | provenance | | +| main.rs:208:53:208:54 | l2 | main.rs:208:40:208:43 | grow | provenance | MaD:8 Sink:MaD:8 | +| main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:9 Sink:MaD:9 | +| main.rs:217:27:217:34 | ...: usize | main.rs:219:26:219:26 | v | provenance | | +| main.rs:219:26:219:26 | v | main.rs:219:13:219:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 | +| main.rs:219:26:219:26 | v | main.rs:220:36:220:36 | v | provenance | | +| main.rs:220:36:220:36 | v | main.rs:220:13:220:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 | +| main.rs:220:36:220:36 | v | main.rs:222:30:222:30 | v | provenance | | +| main.rs:222:30:222:30 | v | main.rs:222:13:222:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 | +| main.rs:222:30:222:30 | v | main.rs:223:26:223:26 | v | provenance | | +| main.rs:223:26:223:26 | v | main.rs:223:13:223:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 | +| main.rs:223:26:223:26 | v | main.rs:224:31:224:31 | v | provenance | | +| main.rs:224:31:224:31 | v | main.rs:224:13:224:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 | +| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:32 | +| main.rs:280:9:280:17 | num_bytes | main.rs:282:54:282:62 | num_bytes | provenance | | +| main.rs:280:21:280:47 | user_input.parse() [Ok] | main.rs:280:21:280:48 | TryExpr | provenance | | +| main.rs:280:21:280:48 | TryExpr | main.rs:280:9:280:17 | num_bytes | provenance | | +| main.rs:282:9:282:14 | layout | main.rs:284:40:284:45 | layout | provenance | | +| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | main.rs:282:18:282:75 | ... .unwrap() | provenance | MaD:31 | +| main.rs:282:18:282:75 | ... .unwrap() | main.rs:282:9:282:14 | layout | provenance | | +| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 | +| main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 | +| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:16 | +| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:35 | +| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:29 | +| main.rs:308:25:308:74 | ... .unwrap_or(...) | main.rs:279:24:279:41 | ...: String | provenance | | +| main.rs:317:9:317:9 | v | main.rs:320:34:320:34 | v | provenance | | +| main.rs:317:9:317:9 | v | main.rs:321:42:321:42 | v | provenance | | +| main.rs:317:9:317:9 | v | main.rs:322:36:322:36 | v | provenance | | +| main.rs:317:9:317:9 | v | main.rs:323:27:323:27 | v | provenance | | +| main.rs:317:9:317:9 | v | main.rs:324:25:324:25 | v | provenance | | +| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:16 | +| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:35 | +| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:29 | +| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse() [Ok] | provenance | MaD:32 | +| main.rs:317:13:317:82 | ... .parse() [Ok] | main.rs:317:13:317:91 | ... .unwrap() | provenance | MaD:31 | +| main.rs:317:13:317:91 | ... .unwrap() | main.rs:317:9:317:9 | v | provenance | | +| main.rs:320:34:320:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | | +| main.rs:321:42:321:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | | +| main.rs:322:36:322:36 | v | main.rs:91:38:91:45 | ...: usize | provenance | | +| main.rs:323:27:323:27 | v | main.rs:183:29:183:36 | ...: usize | provenance | | +| main.rs:324:25:324:25 | v | main.rs:217:27:217:34 | ...: usize | provenance | | +models +| 1 | Sink: lang:alloc; ::allocate; alloc-layout; Argument[0] | +| 2 | Sink: lang:alloc; ::allocate_zeroed; alloc-layout; Argument[0] | +| 3 | Sink: lang:alloc; crate::alloc::alloc; alloc-layout; Argument[0] | +| 4 | Sink: lang:alloc; crate::alloc::alloc_zeroed; alloc-layout; Argument[0] | +| 5 | Sink: lang:alloc; crate::alloc::realloc; alloc-size; Argument[2] | +| 6 | Sink: lang:std; ::allocate; alloc-layout; Argument[0] | +| 7 | Sink: lang:std; ::allocate_zeroed; alloc-layout; Argument[0] | +| 8 | Sink: lang:std; ::grow; alloc-layout; Argument[2] | +| 9 | Sink: lang:std; ::grow_zeroed; alloc-layout; Argument[2] | +| 10 | Sink: lang:std; ::alloc; alloc-layout; Argument[0] | +| 11 | Sink: lang:std; ::alloc_zeroed; alloc-layout; Argument[0] | +| 12 | Sink: repo:https://github.com/rust-lang/libc:libc; ::aligned_alloc; alloc-size; Argument[1] | +| 13 | Sink: repo:https://github.com/rust-lang/libc:libc; ::calloc; alloc-size; Argument[0,1] | +| 14 | Sink: repo:https://github.com/rust-lang/libc:libc; ::malloc; alloc-size; Argument[0] | +| 15 | Sink: repo:https://github.com/rust-lang/libc:libc; ::realloc; alloc-size; Argument[1] | +| 16 | Source: lang:std; crate::env::args; command-line-source; ReturnValue.Element | +| 17 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 18 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 19 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint | +| 20 | Summary: lang:core; ::extend; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint | +| 21 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 22 | Summary: lang:core; ::extend_packed; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 23 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 24 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint | +| 25 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint | +| 26 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint | +| 27 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 28 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint | +| 29 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value | +| 30 | Summary: lang:core; ::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | +| 31 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | +| 32 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 33 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value | +| 34 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value | +| 35 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | +nodes +| main.rs:12:36:12:43 | ...: usize | semmle.label | ...: usize | +| main.rs:18:13:18:31 | ...::realloc | semmle.label | ...::realloc | +| main.rs:18:41:18:41 | v | semmle.label | v | +| main.rs:20:9:20:10 | l2 | semmle.label | l2 | +| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] | +| main.rs:20:14:20:63 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:20:50:20:50 | v | semmle.label | v | +| main.rs:21:13:21:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:21:31:21:32 | l2 | semmle.label | l2 | +| main.rs:22:13:22:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] | +| main.rs:22:31:22:53 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:23:13:23:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] | +| main.rs:23:31:23:53 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:23:31:23:68 | ... .pad_to_align() | semmle.label | ... .pad_to_align() | +| main.rs:24:13:24:36 | ...::alloc_zeroed | semmle.label | ...::alloc_zeroed | +| main.rs:24:38:24:39 | l2 | semmle.label | l2 | +| main.rs:29:9:29:10 | l4 | semmle.label | l4 | +| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) | +| main.rs:29:60:29:60 | v | semmle.label | v | +| main.rs:30:13:30:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:30:31:30:32 | l4 | semmle.label | l4 | +| main.rs:32:9:32:10 | l5 | semmle.label | l5 | +| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) | +| main.rs:32:60:32:89 | ... * ... | semmle.label | ... * ... | +| main.rs:33:13:33:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:33:31:33:32 | l5 | semmle.label | l5 | +| main.rs:35:9:35:10 | s6 | semmle.label | s6 | +| main.rs:36:9:36:10 | l6 | semmle.label | l6 | +| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) | +| main.rs:36:60:36:61 | s6 | semmle.label | s6 | +| main.rs:37:13:37:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:37:31:37:32 | l6 | semmle.label | l6 | +| main.rs:39:9:39:10 | l7 | semmle.label | l7 | +| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) | +| main.rs:39:60:39:68 | l6.size() | semmle.label | l6.size() | +| main.rs:40:13:40:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:40:31:40:32 | l7 | semmle.label | l7 | +| main.rs:43:44:43:51 | ...: usize | semmle.label | ...: usize | +| main.rs:50:13:50:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] | +| main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] | +| main.rs:50:31:50:53 | ... .0 | semmle.label | ... .0 | +| main.rs:50:41:50:41 | v | semmle.label | v | +| main.rs:51:13:51:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] | +| main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] | +| main.rs:51:31:51:57 | ... .0 | semmle.label | ... .0 | +| main.rs:51:41:51:45 | ... + ... | semmle.label | ... + ... | +| main.rs:53:13:53:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] | +| main.rs:53:31:53:58 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:53:48:53:48 | v | semmle.label | v | +| main.rs:54:13:54:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] | +| main.rs:54:31:54:63 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:54:48:54:53 | ... * ... | semmle.label | ... * ... | +| main.rs:58:9:58:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] | +| main.rs:58:10:58:11 | k1 | semmle.label | k1 | +| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | semmle.label | l3.repeat(...) [Ok, tuple.0] | +| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | semmle.label | ... .expect(...) [tuple.0] | +| main.rs:58:34:58:34 | v | semmle.label | v | +| main.rs:59:13:59:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:59:31:59:32 | k1 | semmle.label | k1 | +| main.rs:60:9:60:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] | +| main.rs:60:10:60:11 | k2 | semmle.label | k2 | +| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | semmle.label | l3.extend(...) [Ok, tuple.0] | +| main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] | +| main.rs:60:34:60:35 | k1 | semmle.label | k1 | +| main.rs:61:13:61:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:61:31:61:32 | k2 | semmle.label | k2 | +| main.rs:62:9:62:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] | +| main.rs:62:10:62:11 | k3 | semmle.label | k3 | +| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | semmle.label | k1.extend(...) [Ok, tuple.0] | +| main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] | +| main.rs:63:13:63:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:63:31:63:32 | k3 | semmle.label | k3 | +| main.rs:64:13:64:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | semmle.label | l3.extend_packed(...) [Ok] | +| main.rs:64:31:64:59 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:64:48:64:49 | k1 | semmle.label | k1 | +| main.rs:65:13:65:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | semmle.label | k1.extend_packed(...) [Ok] | +| main.rs:65:31:65:59 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:67:9:67:10 | l4 | semmle.label | l4 | +| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:67:14:67:56 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:67:46:67:46 | v | semmle.label | v | +| main.rs:68:13:68:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:68:31:68:32 | l4 | semmle.label | l4 | +| main.rs:86:35:86:42 | ...: usize | semmle.label | ...: usize | +| main.rs:87:9:87:14 | layout | semmle.label | layout | +| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] | +| main.rs:87:18:87:67 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:87:54:87:54 | v | semmle.label | v | +| main.rs:88:13:88:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:88:31:88:36 | layout | semmle.label | layout | +| main.rs:91:38:91:45 | ...: usize | semmle.label | ...: usize | +| main.rs:92:9:92:10 | l1 | semmle.label | l1 | +| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:92:14:92:57 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:92:47:92:47 | v | semmle.label | v | +| main.rs:96:17:96:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:96:35:96:36 | l1 | semmle.label | l1 | +| main.rs:101:13:101:14 | l3 | semmle.label | l3 | +| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:101:18:101:61 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:101:51:101:51 | v | semmle.label | v | +| main.rs:102:17:102:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:102:35:102:36 | l1 | semmle.label | l1 | +| main.rs:103:17:103:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:103:35:103:36 | l3 | semmle.label | l3 | +| main.rs:105:33:105:33 | v | semmle.label | v | +| main.rs:109:17:109:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:109:35:109:36 | l1 | semmle.label | l1 | +| main.rs:111:17:111:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:111:35:111:36 | l1 | semmle.label | l1 | +| main.rs:145:13:145:14 | l9 | semmle.label | l9 | +| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:145:18:145:61 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:145:51:145:51 | v | semmle.label | v | +| main.rs:146:17:146:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:146:35:146:36 | l1 | semmle.label | l1 | +| main.rs:148:17:148:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:148:35:148:36 | l9 | semmle.label | l9 | +| main.rs:151:9:151:11 | l10 | semmle.label | l10 | +| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:151:15:151:78 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:151:48:151:68 | ...::min(...) | semmle.label | ...::min(...) | +| main.rs:151:62:151:62 | v | semmle.label | v | +| main.rs:152:13:152:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:152:31:152:33 | l10 | semmle.label | l10 | +| main.rs:154:9:154:11 | l11 | semmle.label | l11 | +| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:154:15:154:78 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:154:48:154:68 | ...::max(...) | semmle.label | ...::max(...) | +| main.rs:154:62:154:62 | v | semmle.label | v | +| main.rs:155:13:155:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:155:31:155:33 | l11 | semmle.label | l11 | +| main.rs:161:13:161:15 | l13 | semmle.label | l13 | +| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] | +| main.rs:161:19:161:68 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:161:55:161:55 | v | semmle.label | v | +| main.rs:162:17:162:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:162:35:162:37 | l13 | semmle.label | l13 | +| main.rs:169:17:169:33 | ...::alloc | semmle.label | ...::alloc | +| main.rs:169:35:169:37 | l13 | semmle.label | l13 | +| main.rs:177:13:177:29 | ...::alloc | semmle.label | ...::alloc | +| main.rs:177:31:177:32 | l1 | semmle.label | l1 | +| main.rs:183:29:183:36 | ...: usize | semmle.label | ...: usize | +| main.rs:192:9:192:10 | l2 | semmle.label | l2 | +| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] | +| main.rs:192:14:192:56 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:192:46:192:46 | v | semmle.label | v | +| main.rs:193:32:193:36 | alloc | semmle.label | alloc | +| main.rs:193:38:193:39 | l2 | semmle.label | l2 | +| main.rs:194:32:194:43 | alloc_zeroed | semmle.label | alloc_zeroed | +| main.rs:194:45:194:46 | l2 | semmle.label | l2 | +| main.rs:195:32:195:39 | allocate | semmle.label | allocate | +| main.rs:195:41:195:42 | l2 | semmle.label | l2 | +| main.rs:196:32:196:46 | allocate_zeroed | semmle.label | allocate_zeroed | +| main.rs:196:48:196:49 | l2 | semmle.label | l2 | +| main.rs:197:32:197:39 | allocate | semmle.label | allocate | +| main.rs:197:41:197:42 | l2 | semmle.label | l2 | +| main.rs:198:32:198:46 | allocate_zeroed | semmle.label | allocate_zeroed | +| main.rs:198:48:198:49 | l2 | semmle.label | l2 | +| main.rs:208:40:208:43 | grow | semmle.label | grow | +| main.rs:208:53:208:54 | l2 | semmle.label | l2 | +| main.rs:210:40:210:50 | grow_zeroed | semmle.label | grow_zeroed | +| main.rs:210:60:210:61 | l2 | semmle.label | l2 | +| main.rs:217:27:217:34 | ...: usize | semmle.label | ...: usize | +| main.rs:219:13:219:24 | ...::malloc | semmle.label | ...::malloc | +| main.rs:219:26:219:26 | v | semmle.label | v | +| main.rs:220:13:220:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc | +| main.rs:220:36:220:36 | v | semmle.label | v | +| main.rs:222:13:222:24 | ...::calloc | semmle.label | ...::calloc | +| main.rs:222:30:222:30 | v | semmle.label | v | +| main.rs:223:13:223:24 | ...::calloc | semmle.label | ...::calloc | +| main.rs:223:26:223:26 | v | semmle.label | v | +| main.rs:224:13:224:25 | ...::realloc | semmle.label | ...::realloc | +| main.rs:224:31:224:31 | v | semmle.label | v | +| main.rs:279:24:279:41 | ...: String | semmle.label | ...: String | +| main.rs:280:9:280:17 | num_bytes | semmle.label | num_bytes | +| main.rs:280:21:280:47 | user_input.parse() [Ok] | semmle.label | user_input.parse() [Ok] | +| main.rs:280:21:280:48 | TryExpr | semmle.label | TryExpr | +| main.rs:282:9:282:14 | layout | semmle.label | layout | +| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] | +| main.rs:282:18:282:75 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:282:54:282:62 | num_bytes | semmle.label | num_bytes | +| main.rs:284:22:284:38 | ...::alloc | semmle.label | ...::alloc | +| main.rs:284:40:284:45 | layout | semmle.label | layout | +| main.rs:308:25:308:38 | ...::args | semmle.label | ...::args | +| main.rs:308:25:308:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] | +| main.rs:308:25:308:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] | +| main.rs:308:25:308:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| main.rs:317:9:317:9 | v | semmle.label | v | +| main.rs:317:13:317:26 | ...::args | semmle.label | ...::args | +| main.rs:317:13:317:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] | +| main.rs:317:13:317:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] | +| main.rs:317:13:317:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| main.rs:317:13:317:82 | ... .parse() [Ok] | semmle.label | ... .parse() [Ok] | +| main.rs:317:13:317:91 | ... .unwrap() | semmle.label | ... .unwrap() | +| main.rs:320:34:320:34 | v | semmle.label | v | +| main.rs:321:42:321:42 | v | semmle.label | v | +| main.rs:322:36:322:36 | v | semmle.label | v | +| main.rs:323:27:323:27 | v | semmle.label | v | +| main.rs:324:25:324:25 | v | semmle.label | v | +subpaths diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref new file mode 100644 index 000000000000..2e30becb92cd --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref @@ -0,0 +1,4 @@ +query: queries/security/CWE-770/UncontrolledAllocationSize.ql +postprocess: + - utils/test/InlineExpectationsTestQuery.ql + - utils/test/PrettyPrintModels.ql diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs new file mode 100644 index 000000000000..6d786dd0323e --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-770/main.rs @@ -0,0 +1,330 @@ +#![feature(alloc_layout_extra)] +#![feature(allocator_api)] +#![feature(try_with_capacity)] +#![feature(box_vec_non_null)] +#![feature(non_null_from_ref)] + +struct MyStruct { + _a: usize, + _b: i64, +} + +unsafe fn test_std_alloc_from_size(v: usize) { + let l1 = std::alloc::Layout::from_size_align(16, 1).unwrap(); + let m1 = std::alloc::alloc(l1); + let _ = std::alloc::alloc(l1.align_to(8).unwrap()); + let _ = std::alloc::alloc(l1.align_to(8).unwrap().pad_to_align()); + let _ = std::alloc::alloc_zeroed(l1); + let _ = std::alloc::realloc(m1, l1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous? + let _ = std::alloc::alloc(l3); + + let l4 = std::alloc::Layout::from_size_align_unchecked(v, 1); + let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l5 = std::alloc::Layout::from_size_align_unchecked(v * std::mem::size_of::(), std::mem::size_of::()); + let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let s6 = (std::mem::size_of::() * v) + 1; + let l6 = std::alloc::Layout::from_size_align_unchecked(s6, 4); + let _ = std::alloc::alloc(l6); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8); + let _ = std::alloc::alloc(l7); // $ Alert[rust/uncontrolled-allocation-size]=arg1 +} + +unsafe fn test_std_alloc_new_repeat_extend(v: usize) { + let l1 = std::alloc::Layout::new::<[u8; 10]>(); + let _ = std::alloc::alloc(l1); + + let l2 = std::alloc::Layout::new::(); + let _ = std::alloc::alloc(l2); + let _ = std::alloc::alloc(l2.repeat(10).unwrap().0); + let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2.repeat_packed(10).unwrap()); + let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l3 = std::alloc::Layout::array::(10).unwrap(); + let _ = std::alloc::alloc(l3); + let (k1, _offs1) = l3.repeat(v).expect("arithmetic overflow?"); + let _ = std::alloc::alloc(k1); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let (k2, _offs2) = l3.extend(k1).unwrap(); + let _ = std::alloc::alloc(k2); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let (k3, _offs3) = k1.extend(l3).unwrap(); + let _ = std::alloc::alloc(k3); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l4 = std::alloc::Layout::array::(v).unwrap(); + let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1 +} + +fn clamp(v: T, min: T, max: T) -> T { + if v < min { + return min; + } else if v > max { + return max; + } else { + return v; + } +} + +unsafe fn test_fn_alloc_bounded(v: usize) { + let layout = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(layout); // $ GOOD (bounded) +} + +unsafe fn test_fn_alloc_unbounded(v: usize) { + let layout = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=arg1 +} + +unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) { + let l1 = std::alloc::Layout::array::(v).unwrap(); + + if v < 100 { + let l2 = std::alloc::Layout::array::(v).unwrap(); + let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l2); // $ GOOD (bounded) + + test_fn_alloc_bounded(v); + } else { + let l3 = std::alloc::Layout::array::(v).unwrap(); + let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + test_fn_alloc_unbounded(v); + } + + if v == 100 { + let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1 + } else { + let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + } + + if (v < limit) { + let l4 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l4); // $ GOOD (bounded) + } + + if (v < 2 * v) { // not a good bound + let l5 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + } + + if (true && v < limit && true) { + let l6 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l6); // $ GOOD (bounded) + } + + let mut l7; + if (v < 100) { + l7 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + } else { + l7 = std::alloc::Layout::from_size_align(100, 1).unwrap(); + } + let _ = std::alloc::alloc(l7); // $ GOOD (bounded) + + { + let mut v_mut = v; + + if v_mut > 100 { + v_mut = 100; + } + + let l8 = std::alloc::Layout::array::(v_mut).unwrap(); + let l9 = std::alloc::Layout::array::(v).unwrap(); + let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l8); // $ GOOD (bounded) + let _ = std::alloc::alloc(l9); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + } + + let l10 = std::alloc::Layout::array::(std::cmp::min(v, 100)).unwrap(); + let _ = std::alloc::alloc(l10); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1 + + let l11 = std::alloc::Layout::array::(std::cmp::max(v, 100)).unwrap(); + let _ = std::alloc::alloc(l11); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l12 = std::alloc::Layout::array::(clamp(v, 1, 100)).unwrap(); + let _ = std::alloc::alloc(l12); // $ GOOD (bounded) + + for i in 0..10 { + let l13 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l13); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + if (v > 1000) { + continue; + } + + let l14 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l13); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l14); // $ GOOD (bounded) + } + + if v > 100 { + return; + } + let l15 = std::alloc::Layout::from_size_align(v, 1).unwrap(); + let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::alloc(l15); // $ GOOD (bounded) +} + +use std::alloc::{GlobalAlloc, Allocator}; + +unsafe fn test_system_alloc(v: usize) { + let l1 = std::alloc::Layout::array::(10).unwrap(); + let _ = std::alloc::System.alloc(l1); + let _ = std::alloc::System.alloc_zeroed(l1); + let _ = std::alloc::System.allocate(l1).unwrap(); + let _ = std::alloc::System.allocate_zeroed(l1).unwrap(); + let _ = std::alloc::Global.allocate(l1).unwrap(); + let _ = std::alloc::Global.allocate_zeroed(l1).unwrap(); + + let l2 = std::alloc::Layout::array::(v).unwrap(); + let _ = std::alloc::System.alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::System.alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::System.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::Global.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + + let l3 = std::alloc::Layout::array::(10).unwrap(); + let m3 = std::alloc::System.alloc(l3); + let _ = std::alloc::System.realloc(m3, l3, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let l4 = std::alloc::Layout::array::(10).unwrap(); + let m4 = std::ptr::NonNull::::new(std::alloc::alloc(l4)).unwrap(); + if v > 10 { + if v % 2 == 0 { + let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + } else { + let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + } + } else { + let _ = std::alloc::System.shrink(m4, l4, l2).unwrap(); + } +} + +unsafe fn test_libc_alloc(v: usize) { + let m1 = libc::malloc(256); + let _ = libc::malloc(v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::aligned_alloc(8, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::aligned_alloc(v, 8); + let _ = libc::calloc(64, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::calloc(v, std::mem::size_of::()); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::realloc(m1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 +} + +unsafe fn test_vectors(v: usize) { + let _ = Vec::::try_with_capacity(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + let _ = Vec::::with_capacity(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + let _ = Vec::::try_with_capacity_in(v, std::alloc::Global).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + let _ = Vec::::with_capacity_in(v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let mut v1 = Vec::::with_capacity(100); + v1.reserve(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + v1.reserve_exact(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + let _ = v1.try_reserve(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + let _ = v1.try_reserve_exact(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + v1.resize(v, 1); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + v1.set_len(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let l2 = std::alloc::Layout::new::<[u64; 200]>(); + let m2 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap(); + let _ = Vec::::from_parts(m2, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let m3 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap(); + let _ = Vec::::from_parts(m3, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let m4 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap(); + let _ = Vec::::from_parts_in(m4, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let m5 = std::alloc::alloc(l2).cast::(); + let _ = Vec::::from_raw_parts(m5, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let m6 = std::alloc::alloc(l2).cast::(); + let _ = Vec::::from_raw_parts(m6, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size] + + let m7 = std::alloc::alloc(l2).cast::(); + let _ = Vec::::from_raw_parts_in(m7, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size] +} + +// --- examples from the qhelp --- + +struct Error { + msg: String, +} + +impl From for Error { + fn from(err: std::num::ParseIntError) -> Self { + Error { msg: "ParseIntError".to_string() } + } +} + +impl From<&str> for Error { + fn from(msg: &str) -> Self { + Error { msg: msg.to_string() } + } +} + +fn allocate_buffer_bad(user_input: String) -> Result<*mut u8, Error> { + let num_bytes = user_input.parse::()? * std::mem::size_of::(); + + let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap(); + unsafe { + let buffer = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=example1 + + Ok(buffer) + } +} + +const BUFFER_LIMIT: usize = 10 * 1024; + +fn allocate_buffer_good(user_input: String) -> Result<*mut u8, Error> { + let size = user_input.parse::()?; + if size > BUFFER_LIMIT { + return Err("Size exceeds limit".into()); + } + let num_bytes = size * std::mem::size_of::(); + + let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap(); + unsafe { + let buffer = std::alloc::alloc(layout); // $ GOOD (bounded) + + Ok(buffer) + } +} + +fn test_examples() { + allocate_buffer_bad(std::env::args().nth(1).unwrap_or("0".to_string())); // $ Source=example1 + allocate_buffer_good(std::env::args().nth(1).unwrap_or("0".to_string())); +} + +// --- main --- + +fn main() { + println!("--- begin ---"); + + let v = std::env::args().nth(1).unwrap_or("1024".to_string()).parse::().unwrap(); // $ Source=arg1 + + unsafe { + test_std_alloc_from_size(v); + test_std_alloc_new_repeat_extend(v); + test_std_alloc_with_bounds(v, 1000); + test_system_alloc(v); + test_libc_alloc(v); + test_vectors(v); + test_examples(); + } + + println!("--- end ---"); +} diff --git a/rust/ql/test/query-tests/security/CWE-770/options.yml b/rust/ql/test/query-tests/security/CWE-770/options.yml new file mode 100644 index 000000000000..95a17a53b431 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-770/options.yml @@ -0,0 +1,3 @@ +qltest_cargo_check: true +qltest_dependencies: + - libc = { version = "0.2.11" } diff --git a/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml b/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml new file mode 100644 index 000000000000..afeb59293258 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2025-03-17"