diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 850ee8e01f7b..b13b4bc6db95 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -1,4 +1,4 @@ -lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 96fd8843973b9846cf282cde51e35a5e9118625453156300e0540940ff0f2f86 8028eec3c0ff7636ce18d820357347498564e05b6970cdf86e0beecda1ecd7e7 +lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 12a240e8392e4b0ad9ddb8067b25a1b5e4c1151886d9d64292a7a9ff29d11d97 fdbe7ca4f085d04371280299fd10a604ee5a059294d2c4c836f334d2b5f8926d lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893 lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71 @@ -21,7 +21,7 @@ lib/codeql/rust/elements/BreakExpr.qll 7ca3807a20e9a9a988d1fd7abebf240325ed422fc lib/codeql/rust/elements/CallExpr.qll f336500ca7a611b164d48b90e80edb0c0d3816792b0ececce659ac1ff1ffeb3e f99a9c55466418ef53860c44d9f2d6161af4b492178ddd9e5870dff742b70ae5 lib/codeql/rust/elements/CallExprBase.qll 2846202b5208b541977500286951d96487bf555838c6c16cdd006a71e383745a c789d412bf099c624329379e0c7d94fa0d23ae2edea7a25a2ea0f3c0042ccf62 lib/codeql/rust/elements/Callable.qll e1ed21a7e6bd2426f6ccd0e46cee506d8ebf90a6fdc4dca0979157da439853aa 02f6c09710116ce82157aec9a5ec706983c38e4d85cc631327baf8d409b018c6 -lib/codeql/rust/elements/CastExpr.qll cd8333612f94b47b19ea45cd0f78d62855b30e1a86d7f3052a7bec503bc8f575 198089248d838155081586f81403320ca88375bf178f8d831b0860693bb85386 +lib/codeql/rust/elements/CastExpr.qll 2fe1f36ba31fa29de309baf0a665cfcae67b61c73345e8f9bbd41e8c235fec45 c5b4c1e9dc24eb2357799defcb2df25989075e3a80e8663b74204a1c1b70e29a lib/codeql/rust/elements/ClosureBinder.qll 977df800f97cc9b03fffb5e5e1fc6acd08a2938e04cb6ad91108784a15b0d510 f6fad4127226fe1dff2f16416d8a7fde5d8ab4a88f30e443ac5e5ff618de3e05 lib/codeql/rust/elements/ClosureExpr.qll 67e2a106e9154c90367b129987e574d2a9ecf5b297536627e43706675d35eaed d6a381132ddd589c5a7ce174f50f9620041ddf690e15a65ebfb05ff7e7c02de7 lib/codeql/rust/elements/Comment.qll fedad50575125e9a64a8a8776a8c1dbf1e76df990f01849d9f0955f9d74cb2a6 8eb1afad1e1007a4f0090fdac65d81726b23eda6517d067fd0185f70f17635ab @@ -441,7 +441,7 @@ lib/codeql/rust/elements/internal/generated/BreakExpr.qll 0f428a8b2f4209b134c2ff lib/codeql/rust/elements/internal/generated/CallExpr.qll f1b8dae487077cc9d1dccf8c3cd61fd17afe860585f17ce8b860be4859be7ca4 6034fc03778e38802cdf3a6e460364b74e92912622581b31e6179951022bbbd6 lib/codeql/rust/elements/internal/generated/CallExprBase.qll cce796e36847249f416629bacf3ea146313084de3374587412e66c10d2917b83 c219aa2174321c161a4a742ca0605521687ca9a5ca32db453a5c62db6f7784cc lib/codeql/rust/elements/internal/generated/Callable.qll b0502b5263b7bcd18e740f284f992c0e600e37d68556e3e0ba54a2ac42b94934 bda3e1eea11cacf5a9b932cd72efc2de6105103e8c575880fcd0cd89daadf068 -lib/codeql/rust/elements/internal/generated/CastExpr.qll 427bfd937cd3e737c65aa121aab2a7dc166f82aaacb9a7c41a3d211d4c1dcfb0 642c8c27d4a8752744dadce45814d4e289ce02b67eb2bc2e63ff4c2e5f7825f5 +lib/codeql/rust/elements/internal/generated/CastExpr.qll ddc20054b0b339ad4d40298f3461490d25d00af87c876da5ffbc6a11c0832295 f4247307afcd74d80e926f29f8c57e78c50800984483e6b6003a44681e4a71f3 lib/codeql/rust/elements/internal/generated/ClosureBinder.qll 94c0dcdd4cd87d115659d496c88a98354bc7d4ddc0fa27028003bf7688b99987 d59d713b426dbbdb775df9092d176eea031dac1f14e468810f2fc8591399cd19 lib/codeql/rust/elements/internal/generated/ClosureExpr.qll 34149bf82f107591e65738221e1407ec1dc9cc0dfb10ae7f761116fda45162de fd2fbc9a87fc0773c940db64013cf784d5e4137515cc1020e2076da329f5a952 lib/codeql/rust/elements/internal/generated/Comment.qll cd1ef861e3803618f9f78a4ac00516d50ecfecdca1c1d14304dc5327cbe07a3b 8b67345aeb15beb5895212228761ea3496297846c93fd2127b417406ae87c201 @@ -537,7 +537,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9 lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9 -lib/codeql/rust/elements/internal/generated/Raw.qll 40a4900214b83a2be04427d42f26dff9eb96c8eb4349a3126e30c645dd0fb97d 62644e0e0515df1db91fce87c05ff5900e53b25681db17fe049c93514743c8fa +lib/codeql/rust/elements/internal/generated/Raw.qll b295dd46979a2d4df840e1bef4ba12e3b4ff58aa886c8a1320281739d36c5a4f 2369cba6d70f0e853acb0e018dfb47e604ee01dca48af7094b484a7e18a46365 lib/codeql/rust/elements/internal/generated/RecordExpr.qll 2131b2cb336caa76170082e69776011bf02576bbfdd34ba68ca84af24209250a 39a2e3ec32352b594c43cc1295e0e8b3f9808173322d3d73cb7d48ef969d5565 lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1 lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0 diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll index 07688d4b6a88..78e78192b7c7 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll @@ -703,6 +703,66 @@ module MakeCfgNodes Input> { int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } } + final private class ParentCastExpr extends ParentAstNode, CastExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A type cast expression. For example: + * ```rust + * value as u64; + * ``` + */ + final class CastExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private CastExpr node; + + CastExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `CastExpr`. */ + CastExpr getCastExpr() { result = node } + + /** + * Gets the `index`th attr of this cast expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this cast expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this cast expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this cast expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the type representation of this cast expression, if it exists. + */ + TypeRepr getTypeRepr() { result = node.getTypeRepr() } + + /** + * Holds if `getTypeRepr()` exists. + */ + predicate hasTypeRepr() { exists(this.getTypeRepr()) } + } + final private class ParentConstBlockPat extends ParentAstNode, ConstBlockPat { override predicate relevantChild(AstNode child) { none() @@ -3255,6 +3315,18 @@ module MakeCfgNodes Input> { cfgNode ) or + pred = "getExpr" and + parent = + any(Nodes::CastExprCfgNode cfgNode, CastExpr astNode | + astNode = cfgNode.getCastExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or pred = "getBlockExpr" and parent = any(Nodes::ConstBlockPatCfgNode cfgNode, ConstBlockPat astNode | diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll index 917ce0aea458..faf80143b548 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll @@ -1,15 +1,45 @@ private import rust private import codeql.dataflow.TaintTracking +private import codeql.rust.controlflow.CfgNodes +private import DataFlowImpl +private import codeql.rust.dataflow.FlowSummary +private import FlowSummaryImpl as FlowSummaryImpl private import DataFlowImpl module RustTaintTracking implements InputSig { predicate defaultTaintSanitizer(Node::Node node) { none() } /** - * Holds if the additional step from `src` to `sink` should be included in all + * Holds if the additional step from `pred` to `succ` should be included in all * global taint flow configurations. */ - predicate defaultAdditionalTaintStep(Node::Node src, Node::Node sink, string model) { none() } + predicate defaultAdditionalTaintStep(Node::Node pred, Node::Node succ, string model) { + model = "" and + ( + exists(BinaryExprCfgNode binary | + binary.getOperatorName() = ["+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>"] and + pred.asExpr() = [binary.getLhs(), binary.getRhs()] and + succ.asExpr() = binary + ) + or + exists(PrefixExprCfgNode prefix | + prefix.getOperatorName() = ["-", "!"] and + pred.asExpr() = prefix.getExpr() and + succ.asExpr() = prefix + ) + or + pred.asExpr() = succ.asExpr().(CastExprCfgNode).getExpr() + or + exists(IndexExprCfgNode index | + index.getIndex() instanceof RangeExprCfgNode and + pred.asExpr() = index.getBase() and + succ.asExpr() = index + ) + ) + or + FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(), + succ.(Node::FlowSummaryNode).getSummaryNode(), false, model) + } /** * Holds if taint flow configurations should allow implicit reads of `c` at sinks diff --git a/rust/ql/lib/codeql/rust/elements/CastExpr.qll b/rust/ql/lib/codeql/rust/elements/CastExpr.qll index f7a892e73992..968a6062a15e 100644 --- a/rust/ql/lib/codeql/rust/elements/CastExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/CastExpr.qll @@ -9,7 +9,7 @@ import codeql.rust.elements.Expr import codeql.rust.elements.TypeRepr /** - * A cast expression. For example: + * A type cast expression. For example: * ```rust * value as u64; * ``` diff --git a/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll index d44836596fb5..b074e7379318 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll @@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.generated.CastExpr module Impl { // the following QLdoc is generated: if you need to edit it, do it in the schema file /** - * A cast expression. For example: + * A type cast expression. For example: * ```rust * value as u64; * ``` diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/CastExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/CastExpr.qll index dda6547fabbc..a3725ff1a45f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/CastExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/CastExpr.qll @@ -17,7 +17,7 @@ import codeql.rust.elements.TypeRepr */ module Generated { /** - * A cast expression. For example: + * A type cast expression. For example: * ```rust * value as u64; * ``` diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll index c6835b8438ec..5a32a8623bc1 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll @@ -1433,7 +1433,7 @@ module Raw { /** * INTERNAL: Do not use. - * A cast expression. For example: + * A type cast expression. For example: * ```rust * value as u64; * ``` diff --git a/rust/ql/test/extractor-tests/generated/.generated_tests.list b/rust/ql/test/extractor-tests/generated/.generated_tests.list index b39bf6b63ee9..2410d9237d0c 100644 --- a/rust/ql/test/extractor-tests/generated/.generated_tests.list +++ b/rust/ql/test/extractor-tests/generated/.generated_tests.list @@ -13,7 +13,7 @@ BlockExpr/gen_block_expr.rs 17b06c726e304e0efcfde8e71afd9c657860312be55436689423 BoxPat/gen_box_pat.rs 1493e24b732370b577ade38c47db17fa157df19f5390606a67a6040e49b501c0 1493e24b732370b577ade38c47db17fa157df19f5390606a67a6040e49b501c0 BreakExpr/gen_break_expr.rs aacdf9df7fc51d19742b9e813835c0bd0913017e8d62765960e06b27d58b9031 aacdf9df7fc51d19742b9e813835c0bd0913017e8d62765960e06b27d58b9031 CallExpr/gen_call_expr.rs 013a7c878996aefb25b94b68eebc4f0b1bb74ccd09e91c491980817a383e2401 013a7c878996aefb25b94b68eebc4f0b1bb74ccd09e91c491980817a383e2401 -CastExpr/gen_cast_expr.rs abd59cc7b92578b56098ac0045cf7de4b15c645cce79e3bdad8d3b6f4657360d abd59cc7b92578b56098ac0045cf7de4b15c645cce79e3bdad8d3b6f4657360d +CastExpr/gen_cast_expr.rs c3892211fbae4fed7cb1f25ff1679fd79d2878bf0bf2bd4b7982af23d00129f5 c3892211fbae4fed7cb1f25ff1679fd79d2878bf0bf2bd4b7982af23d00129f5 ClosureBinder/gen_closure_binder.rs 78d3219bdfc58a22f333e3c82468fc23001e92b1d5acb085de7f48d7d1722244 78d3219bdfc58a22f333e3c82468fc23001e92b1d5acb085de7f48d7d1722244 ClosureExpr/gen_closure_expr.rs 15bd9abdb8aaffabb8bb335f8ebd0571eb5f29115e1dc8d11837aa988702cd80 15bd9abdb8aaffabb8bb335f8ebd0571eb5f29115e1dc8d11837aa988702cd80 Comment/gen_comment.rs 1e1f9f43161a79c096c2056e8b7f5346385ab7addcdec68c2d53b383dd3debe6 1e1f9f43161a79c096c2056e8b7f5346385ab7addcdec68c2d53b383dd3debe6 diff --git a/rust/ql/test/extractor-tests/generated/CastExpr/gen_cast_expr.rs b/rust/ql/test/extractor-tests/generated/CastExpr/gen_cast_expr.rs index 2945c711320a..ba0ed150d0b4 100644 --- a/rust/ql/test/extractor-tests/generated/CastExpr/gen_cast_expr.rs +++ b/rust/ql/test/extractor-tests/generated/CastExpr/gen_cast_expr.rs @@ -1,6 +1,6 @@ // generated by codegen, do not edit fn test_cast_expr() -> () { - // A cast expression. For example: + // A type cast expression. For example: value as u64; } diff --git a/rust/ql/test/library-tests/dataflow/models/main.rs b/rust/ql/test/library-tests/dataflow/models/main.rs index 21cfc10ad2f5..337cec5a220e 100644 --- a/rust/ql/test/library-tests/dataflow/models/main.rs +++ b/rust/ql/test/library-tests/dataflow/models/main.rs @@ -16,6 +16,16 @@ fn test_identify() { sink(identity(s)); // $ hasValueFlow=1 } +// has a flow model +fn coerce(_i: i64) -> i64 { + 0 +} + +fn test_coerce() { + let s = source(14); + sink(coerce(s)); // $ hasTaintFlow=14 +} + enum MyPosEnum { A(i64), B(i64), diff --git a/rust/ql/test/library-tests/dataflow/models/models.expected b/rust/ql/test/library-tests/dataflow/models/models.expected index eeb9301b434e..6ebc72099cae 100644 --- a/rust/ql/test/library-tests/dataflow/models/models.expected +++ b/rust/ql/test/library-tests/dataflow/models/models.expected @@ -1,57 +1,113 @@ models edges | main.rs:15:13:15:21 | source(...) | main.rs:16:19:16:19 | s | provenance | | +| main.rs:15:13:15:21 | source(...) | main.rs:16:19:16:19 | s | provenance | | +| main.rs:16:19:16:19 | s | main.rs:16:10:16:20 | identity(...) | provenance | | | main.rs:16:19:16:19 | s | main.rs:16:10:16:20 | identity(...) | provenance | | -| main.rs:30:13:30:21 | source(...) | main.rs:31:27:31:27 | s | provenance | | -| main.rs:31:14:31:28 | ...::A(...) [A] | main.rs:32:22:32:23 | e1 [A] | provenance | | -| main.rs:31:27:31:27 | s | main.rs:31:14:31:28 | ...::A(...) [A] | provenance | | -| main.rs:32:22:32:23 | e1 [A] | main.rs:32:10:32:24 | get_var_pos(...) | provenance | | -| main.rs:43:13:43:21 | source(...) | main.rs:44:26:44:26 | s | provenance | | -| main.rs:44:14:44:27 | set_var_pos(...) [B] | main.rs:47:9:47:23 | ...::B(...) [B] | provenance | | -| main.rs:44:26:44:26 | s | main.rs:44:14:44:27 | set_var_pos(...) [B] | provenance | | -| main.rs:47:9:47:23 | ...::B(...) [B] | main.rs:47:22:47:22 | i | provenance | | -| main.rs:47:22:47:22 | i | main.rs:47:33:47:33 | i | provenance | | -| main.rs:62:13:62:21 | source(...) | main.rs:63:40:63:40 | s | provenance | | -| main.rs:63:14:63:42 | ...::C {...} [C] | main.rs:64:24:64:25 | e1 [C] | provenance | | -| main.rs:63:40:63:40 | s | main.rs:63:14:63:42 | ...::C {...} [C] | provenance | | -| main.rs:64:24:64:25 | e1 [C] | main.rs:64:10:64:26 | get_var_field(...) | provenance | | -| main.rs:75:13:75:21 | source(...) | main.rs:76:28:76:28 | s | provenance | | -| main.rs:76:14:76:29 | set_var_field(...) [D] | main.rs:79:9:79:37 | ...::D {...} [D] | provenance | | -| main.rs:76:28:76:28 | s | main.rs:76:14:76:29 | set_var_field(...) [D] | provenance | | -| main.rs:79:9:79:37 | ...::D {...} [D] | main.rs:79:35:79:35 | i | provenance | | -| main.rs:79:35:79:35 | i | main.rs:79:47:79:47 | i | provenance | | +| main.rs:25:13:25:22 | source(...) | main.rs:26:17:26:17 | s | provenance | | +| main.rs:26:17:26:17 | s | main.rs:26:10:26:18 | coerce(...) | provenance | | +| main.rs:40:13:40:21 | source(...) | main.rs:41:27:41:27 | s | provenance | | +| main.rs:40:13:40:21 | source(...) | main.rs:41:27:41:27 | s | provenance | | +| main.rs:41:14:41:28 | ...::A(...) [A] | main.rs:42:22:42:23 | e1 [A] | provenance | | +| main.rs:41:14:41:28 | ...::A(...) [A] | main.rs:42:22:42:23 | e1 [A] | provenance | | +| main.rs:41:27:41:27 | s | main.rs:41:14:41:28 | ...::A(...) [A] | provenance | | +| main.rs:41:27:41:27 | s | main.rs:41:14:41:28 | ...::A(...) [A] | provenance | | +| main.rs:42:22:42:23 | e1 [A] | main.rs:42:10:42:24 | get_var_pos(...) | provenance | | +| main.rs:42:22:42:23 | e1 [A] | main.rs:42:10:42:24 | get_var_pos(...) | provenance | | +| main.rs:53:13:53:21 | source(...) | main.rs:54:26:54:26 | s | provenance | | +| main.rs:53:13:53:21 | source(...) | main.rs:54:26:54:26 | s | provenance | | +| main.rs:54:14:54:27 | set_var_pos(...) [B] | main.rs:57:9:57:23 | ...::B(...) [B] | provenance | | +| main.rs:54:14:54:27 | set_var_pos(...) [B] | main.rs:57:9:57:23 | ...::B(...) [B] | provenance | | +| main.rs:54:26:54:26 | s | main.rs:54:14:54:27 | set_var_pos(...) [B] | provenance | | +| main.rs:54:26:54:26 | s | main.rs:54:14:54:27 | set_var_pos(...) [B] | provenance | | +| main.rs:57:9:57:23 | ...::B(...) [B] | main.rs:57:22:57:22 | i | provenance | | +| main.rs:57:9:57:23 | ...::B(...) [B] | main.rs:57:22:57:22 | i | provenance | | +| main.rs:57:22:57:22 | i | main.rs:57:33:57:33 | i | provenance | | +| main.rs:57:22:57:22 | i | main.rs:57:33:57:33 | i | provenance | | +| main.rs:72:13:72:21 | source(...) | main.rs:73:40:73:40 | s | provenance | | +| main.rs:72:13:72:21 | source(...) | main.rs:73:40:73:40 | s | provenance | | +| main.rs:73:14:73:42 | ...::C {...} [C] | main.rs:74:24:74:25 | e1 [C] | provenance | | +| main.rs:73:14:73:42 | ...::C {...} [C] | main.rs:74:24:74:25 | e1 [C] | provenance | | +| main.rs:73:40:73:40 | s | main.rs:73:14:73:42 | ...::C {...} [C] | provenance | | +| main.rs:73:40:73:40 | s | main.rs:73:14:73:42 | ...::C {...} [C] | provenance | | +| main.rs:74:24:74:25 | e1 [C] | main.rs:74:10:74:26 | get_var_field(...) | provenance | | +| main.rs:74:24:74:25 | e1 [C] | main.rs:74:10:74:26 | get_var_field(...) | provenance | | +| main.rs:85:13:85:21 | source(...) | main.rs:86:28:86:28 | s | provenance | | +| main.rs:85:13:85:21 | source(...) | main.rs:86:28:86:28 | s | provenance | | +| main.rs:86:14:86:29 | set_var_field(...) [D] | main.rs:89:9:89:37 | ...::D {...} [D] | provenance | | +| main.rs:86:14:86:29 | set_var_field(...) [D] | main.rs:89:9:89:37 | ...::D {...} [D] | provenance | | +| main.rs:86:28:86:28 | s | main.rs:86:14:86:29 | set_var_field(...) [D] | provenance | | +| main.rs:86:28:86:28 | s | main.rs:86:14:86:29 | set_var_field(...) [D] | provenance | | +| main.rs:89:9:89:37 | ...::D {...} [D] | main.rs:89:35:89:35 | i | provenance | | +| main.rs:89:9:89:37 | ...::D {...} [D] | main.rs:89:35:89:35 | i | provenance | | +| main.rs:89:35:89:35 | i | main.rs:89:47:89:47 | i | provenance | | +| main.rs:89:35:89:35 | i | main.rs:89:47:89:47 | i | provenance | | nodes | main.rs:15:13:15:21 | source(...) | semmle.label | source(...) | +| main.rs:15:13:15:21 | source(...) | semmle.label | source(...) | | main.rs:16:10:16:20 | identity(...) | semmle.label | identity(...) | +| main.rs:16:10:16:20 | identity(...) | semmle.label | identity(...) | +| main.rs:16:19:16:19 | s | semmle.label | s | | main.rs:16:19:16:19 | s | semmle.label | s | -| main.rs:30:13:30:21 | source(...) | semmle.label | source(...) | -| main.rs:31:14:31:28 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | -| main.rs:31:27:31:27 | s | semmle.label | s | -| main.rs:32:10:32:24 | get_var_pos(...) | semmle.label | get_var_pos(...) | -| main.rs:32:22:32:23 | e1 [A] | semmle.label | e1 [A] | -| main.rs:43:13:43:21 | source(...) | semmle.label | source(...) | -| main.rs:44:14:44:27 | set_var_pos(...) [B] | semmle.label | set_var_pos(...) [B] | -| main.rs:44:26:44:26 | s | semmle.label | s | -| main.rs:47:9:47:23 | ...::B(...) [B] | semmle.label | ...::B(...) [B] | -| main.rs:47:22:47:22 | i | semmle.label | i | -| main.rs:47:33:47:33 | i | semmle.label | i | -| main.rs:62:13:62:21 | source(...) | semmle.label | source(...) | -| main.rs:63:14:63:42 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | -| main.rs:63:40:63:40 | s | semmle.label | s | -| main.rs:64:10:64:26 | get_var_field(...) | semmle.label | get_var_field(...) | -| main.rs:64:24:64:25 | e1 [C] | semmle.label | e1 [C] | -| main.rs:75:13:75:21 | source(...) | semmle.label | source(...) | -| main.rs:76:14:76:29 | set_var_field(...) [D] | semmle.label | set_var_field(...) [D] | -| main.rs:76:28:76:28 | s | semmle.label | s | -| main.rs:79:9:79:37 | ...::D {...} [D] | semmle.label | ...::D {...} [D] | -| main.rs:79:35:79:35 | i | semmle.label | i | -| main.rs:79:47:79:47 | i | semmle.label | i | +| main.rs:25:13:25:22 | source(...) | semmle.label | source(...) | +| main.rs:26:10:26:18 | coerce(...) | semmle.label | coerce(...) | +| main.rs:26:17:26:17 | s | semmle.label | s | +| main.rs:40:13:40:21 | source(...) | semmle.label | source(...) | +| main.rs:40:13:40:21 | source(...) | semmle.label | source(...) | +| main.rs:41:14:41:28 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | +| main.rs:41:14:41:28 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | +| main.rs:41:27:41:27 | s | semmle.label | s | +| main.rs:41:27:41:27 | s | semmle.label | s | +| main.rs:42:10:42:24 | get_var_pos(...) | semmle.label | get_var_pos(...) | +| main.rs:42:10:42:24 | get_var_pos(...) | semmle.label | get_var_pos(...) | +| main.rs:42:22:42:23 | e1 [A] | semmle.label | e1 [A] | +| main.rs:42:22:42:23 | e1 [A] | semmle.label | e1 [A] | +| main.rs:53:13:53:21 | source(...) | semmle.label | source(...) | +| main.rs:53:13:53:21 | source(...) | semmle.label | source(...) | +| main.rs:54:14:54:27 | set_var_pos(...) [B] | semmle.label | set_var_pos(...) [B] | +| main.rs:54:14:54:27 | set_var_pos(...) [B] | semmle.label | set_var_pos(...) [B] | +| main.rs:54:26:54:26 | s | semmle.label | s | +| main.rs:54:26:54:26 | s | semmle.label | s | +| main.rs:57:9:57:23 | ...::B(...) [B] | semmle.label | ...::B(...) [B] | +| main.rs:57:9:57:23 | ...::B(...) [B] | semmle.label | ...::B(...) [B] | +| main.rs:57:22:57:22 | i | semmle.label | i | +| main.rs:57:22:57:22 | i | semmle.label | i | +| main.rs:57:33:57:33 | i | semmle.label | i | +| main.rs:57:33:57:33 | i | semmle.label | i | +| main.rs:72:13:72:21 | source(...) | semmle.label | source(...) | +| main.rs:72:13:72:21 | source(...) | semmle.label | source(...) | +| main.rs:73:14:73:42 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:73:14:73:42 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:73:40:73:40 | s | semmle.label | s | +| main.rs:73:40:73:40 | s | semmle.label | s | +| main.rs:74:10:74:26 | get_var_field(...) | semmle.label | get_var_field(...) | +| main.rs:74:10:74:26 | get_var_field(...) | semmle.label | get_var_field(...) | +| main.rs:74:24:74:25 | e1 [C] | semmle.label | e1 [C] | +| main.rs:74:24:74:25 | e1 [C] | semmle.label | e1 [C] | +| main.rs:85:13:85:21 | source(...) | semmle.label | source(...) | +| main.rs:85:13:85:21 | source(...) | semmle.label | source(...) | +| main.rs:86:14:86:29 | set_var_field(...) [D] | semmle.label | set_var_field(...) [D] | +| main.rs:86:14:86:29 | set_var_field(...) [D] | semmle.label | set_var_field(...) [D] | +| main.rs:86:28:86:28 | s | semmle.label | s | +| main.rs:86:28:86:28 | s | semmle.label | s | +| main.rs:89:9:89:37 | ...::D {...} [D] | semmle.label | ...::D {...} [D] | +| main.rs:89:9:89:37 | ...::D {...} [D] | semmle.label | ...::D {...} [D] | +| main.rs:89:35:89:35 | i | semmle.label | i | +| main.rs:89:35:89:35 | i | semmle.label | i | +| main.rs:89:47:89:47 | i | semmle.label | i | +| main.rs:89:47:89:47 | i | semmle.label | i | subpaths testFailures invalidSpecComponent #select | main.rs:16:10:16:20 | identity(...) | main.rs:15:13:15:21 | source(...) | main.rs:16:10:16:20 | identity(...) | $@ | main.rs:15:13:15:21 | source(...) | source(...) | -| main.rs:32:10:32:24 | get_var_pos(...) | main.rs:30:13:30:21 | source(...) | main.rs:32:10:32:24 | get_var_pos(...) | $@ | main.rs:30:13:30:21 | source(...) | source(...) | -| main.rs:47:33:47:33 | i | main.rs:43:13:43:21 | source(...) | main.rs:47:33:47:33 | i | $@ | main.rs:43:13:43:21 | source(...) | source(...) | -| main.rs:64:10:64:26 | get_var_field(...) | main.rs:62:13:62:21 | source(...) | main.rs:64:10:64:26 | get_var_field(...) | $@ | main.rs:62:13:62:21 | source(...) | source(...) | -| main.rs:79:47:79:47 | i | main.rs:75:13:75:21 | source(...) | main.rs:79:47:79:47 | i | $@ | main.rs:75:13:75:21 | source(...) | source(...) | +| main.rs:16:10:16:20 | identity(...) | main.rs:15:13:15:21 | source(...) | main.rs:16:10:16:20 | identity(...) | $@ | main.rs:15:13:15:21 | source(...) | source(...) | +| main.rs:26:10:26:18 | coerce(...) | main.rs:25:13:25:22 | source(...) | main.rs:26:10:26:18 | coerce(...) | $@ | main.rs:25:13:25:22 | source(...) | source(...) | +| main.rs:42:10:42:24 | get_var_pos(...) | main.rs:40:13:40:21 | source(...) | main.rs:42:10:42:24 | get_var_pos(...) | $@ | main.rs:40:13:40:21 | source(...) | source(...) | +| main.rs:42:10:42:24 | get_var_pos(...) | main.rs:40:13:40:21 | source(...) | main.rs:42:10:42:24 | get_var_pos(...) | $@ | main.rs:40:13:40:21 | source(...) | source(...) | +| main.rs:57:33:57:33 | i | main.rs:53:13:53:21 | source(...) | main.rs:57:33:57:33 | i | $@ | main.rs:53:13:53:21 | source(...) | source(...) | +| main.rs:57:33:57:33 | i | main.rs:53:13:53:21 | source(...) | main.rs:57:33:57:33 | i | $@ | main.rs:53:13:53:21 | source(...) | source(...) | +| main.rs:74:10:74:26 | get_var_field(...) | main.rs:72:13:72:21 | source(...) | main.rs:74:10:74:26 | get_var_field(...) | $@ | main.rs:72:13:72:21 | source(...) | source(...) | +| main.rs:74:10:74:26 | get_var_field(...) | main.rs:72:13:72:21 | source(...) | main.rs:74:10:74:26 | get_var_field(...) | $@ | main.rs:72:13:72:21 | source(...) | source(...) | +| main.rs:89:47:89:47 | i | main.rs:85:13:85:21 | source(...) | main.rs:89:47:89:47 | i | $@ | main.rs:85:13:85:21 | source(...) | source(...) | +| main.rs:89:47:89:47 | i | main.rs:85:13:85:21 | source(...) | main.rs:89:47:89:47 | i | $@ | main.rs:85:13:85:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/models/models.ql b/rust/ql/test/library-tests/dataflow/models/models.ql index 080d6b58f5cd..53c3f5de4be3 100644 --- a/rust/ql/test/library-tests/dataflow/models/models.ql +++ b/rust/ql/test/library-tests/dataflow/models/models.ql @@ -25,6 +25,16 @@ private class SummarizedCallableIdentity extends SummarizedCallable::Range { } } +private class SummarizedCallableCoerce extends SummarizedCallable::Range { + SummarizedCallableCoerce() { this = "repo::test::_::crate::coerce" } + + override predicate propagatesFlow(string input, string output, boolean preservesValue) { + input = "Argument[0]" and + output = "ReturnValue" and + preservesValue = false + } +} + private class SummarizedCallableGetVarPos extends SummarizedCallable::Range { SummarizedCallableGetVarPos() { this = "repo::test::_::crate::get_var_pos" } @@ -71,7 +81,7 @@ module CustomConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { DefaultFlowConfig::isSink(sink) } } -import ValueFlowTest +import FlowTest from PathNode source, PathNode sink where flowPath(source, sink) diff --git a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected new file mode 100644 index 000000000000..04b8539a2ee7 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected @@ -0,0 +1,8 @@ +| main.rs:4:5:4:8 | 1000 | main.rs:4:5:4:12 | ... + ... | | +| main.rs:4:12:4:12 | i | main.rs:4:5:4:12 | ... + ... | | +| main.rs:13:10:13:10 | a | main.rs:13:10:13:14 | ... + ... | | +| main.rs:13:14:13:14 | 1 | main.rs:13:10:13:14 | ... + ... | | +| main.rs:18:11:18:11 | a | main.rs:18:10:18:11 | - ... | | +| main.rs:23:13:23:13 | a | main.rs:23:13:23:19 | a as u8 | | +| main.rs:24:10:24:10 | b | main.rs:24:10:24:17 | b as i64 | | +| main.rs:38:23:38:23 | s | main.rs:38:23:38:29 | s[...] | | diff --git a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.ql b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.ql new file mode 100644 index 000000000000..5eebf4b347d1 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.ql @@ -0,0 +1,4 @@ +import codeql.rust.dataflow.DataFlow +import codeql.rust.dataflow.internal.TaintTrackingImpl + +query predicate additionalTaintStep = RustTaintTracking::defaultAdditionalTaintStep/3; diff --git a/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.expected b/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.expected new file mode 100644 index 000000000000..37ea5f51c786 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.expected @@ -0,0 +1,18 @@ +models +edges +| main.rs:12:13:12:22 | source(...) | main.rs:13:10:13:14 | ... + ... | provenance | | +| main.rs:17:13:17:22 | source(...) | main.rs:18:10:18:11 | - ... | provenance | | +| main.rs:22:13:22:22 | source(...) | main.rs:24:10:24:17 | b as i64 | provenance | | +nodes +| main.rs:12:13:12:22 | source(...) | semmle.label | source(...) | +| main.rs:13:10:13:14 | ... + ... | semmle.label | ... + ... | +| main.rs:17:13:17:22 | source(...) | semmle.label | source(...) | +| main.rs:18:10:18:11 | - ... | semmle.label | - ... | +| main.rs:22:13:22:22 | source(...) | semmle.label | source(...) | +| main.rs:24:10:24:17 | b as i64 | semmle.label | b as i64 | +subpaths +testFailures +#select +| main.rs:13:10:13:14 | ... + ... | main.rs:12:13:12:22 | source(...) | main.rs:13:10:13:14 | ... + ... | $@ | main.rs:12:13:12:22 | source(...) | source(...) | +| main.rs:18:10:18:11 | - ... | main.rs:17:13:17:22 | source(...) | main.rs:18:10:18:11 | - ... | $@ | main.rs:17:13:17:22 | source(...) | source(...) | +| main.rs:24:10:24:17 | b as i64 | main.rs:22:13:22:22 | source(...) | main.rs:24:10:24:17 | b as i64 | $@ | main.rs:22:13:22:22 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.ql b/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.ql new file mode 100644 index 000000000000..2929ae90964f --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.ql @@ -0,0 +1,12 @@ +/** + * @kind path-problem + */ + +import rust +import utils.InlineFlowTest +import DefaultFlowTest +import TaintFlow::PathGraph + +from TaintFlow::PathNode source, TaintFlow::PathNode sink +where TaintFlow::flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/rust/ql/test/library-tests/dataflow/taint/main.rs b/rust/ql/test/library-tests/dataflow/taint/main.rs new file mode 100644 index 000000000000..0ce5ba063910 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/taint/main.rs @@ -0,0 +1,50 @@ +// Tests for taint flow. + +fn source(i: i64) -> i64 { + 1000 + i +} + +fn sink(s: i64) { + println!("{}", s); +} + +fn addition() { + let a = source(42); + sink(a + 1); // $ hasTaintFlow=42 +} + +fn negation() { + let a = source(17); + sink(-a); // $ hasTaintFlow=17 +} + +fn cast() { + let a = source(77); + let b = a as u8; + sink(b as i64); // $ hasTaintFlow=77 +} + +mod string { + fn source(i: i64) -> String { + format!("{}", i) + } + + fn sink(s: &str) { + println!("{}", s); + } + + pub fn string_slice() { + let s = source(35); + let sliced = &s[1..3]; + sink(sliced); // $ MISSING: hasTaintFlow=35 + } +} + +use string::*; + +fn main() { + addition(); + negation(); + cast(); + string_slice(); +} diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index 2feff4033f0b..33a837871043 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -450,10 +450,10 @@ class _: """ -@annotate(CastExpr) +@annotate(CastExpr, cfg = True) class _: """ - A cast expression. For example: + A type cast expression. For example: ```rust value as u64; ```