diff --git a/rust/ql/lib/codeql/rust/frameworks/libxml.model.yml b/rust/ql/lib/codeql/rust/frameworks/libxml.model.yml new file mode 100644 index 00000000000..dbd84b52204 --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/libxml.model.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sinkModel + data: + - ["libxml::bindings::xmlReadFile", "Argument[0].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlCtxtReadFile", "Argument[1].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlReadDoc", "Argument[0].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlCtxtReadDoc", "Argument[1].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlReadFd", "Argument[0]", "xxe", "manual"] + - ["libxml::bindings::xmlCtxtReadFd", "Argument[1]", "xxe", "manual"] + - ["libxml::bindings::xmlReadMemory", "Argument[0].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlCtxtReadMemory", "Argument[1].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlReadIO", "Argument[0].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlCtxtReadIO", "Argument[1].Reference", "xxe", "manual"] + - ["libxml::bindings::xmlParseInNodeContext", "Argument[1].Reference", "xxe", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml index 895ebe98bd6..ed3aef3de6c 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml @@ -126,6 +126,8 @@ extensions: # Str - ["::as_str", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] - ["::as_bytes", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] + - ["::as_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] + - ["::as_mut_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] - ["::parse", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - ["::trim", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] - ["::to_string", "Argument[self].Reference", "ReturnValue", "taint", "manual"] diff --git a/rust/ql/lib/codeql/rust/security/XxeExtensions.qll b/rust/ql/lib/codeql/rust/security/XxeExtensions.qll index 328911da734..749b2ad7c78 100644 --- a/rust/ql/lib/codeql/rust/security/XxeExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/XxeExtensions.qll @@ -8,6 +8,7 @@ private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.FlowBarrier private import codeql.rust.dataflow.FlowSink private import codeql.rust.Concepts +private import codeql.rust.dataflow.internal.Node as Node /** * Provides default sources, sinks and barriers for detecting XML external @@ -38,15 +39,16 @@ module Xxe { private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { } /** - * A libxml2 XML parsing call with unsafe parser options, considered as a - * flow sink. + * A sink for XXE from model data. */ - private class Libxml2XxeSink extends Sink { - Libxml2XxeSink() { - exists(Call call, int xmlArg, int optionsArg | - libxml2ParseCall(call, xmlArg, optionsArg) and - this.asExpr() = call.getPositionalArgument(xmlArg) and - hasXxeOption(call.getPositionalArgument(optionsArg)) + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { + exists(Call call | + // an XML parse call + sinkNode(this, "xxe") and + call = this.(Node::FlowSummaryNode).getSinkElement().getCall() and + // with an unsafe option + hasXxeOption(call.getAnArgument()) ) } } @@ -59,31 +61,6 @@ module Xxe { } } -/** - * Holds if `call` is a call to a `libxml2` XML parsing function, where - * `xmlArg` is the index of the XML content argument and `optionsArg` is the - * index of the parser options argument. - */ -private predicate libxml2ParseCall(Call call, int xmlArg, int optionsArg) { - exists(string fname | call.getStaticTarget().getName().getText() = fname | - fname = "xmlReadFile" and xmlArg = 0 and optionsArg = 2 - or - fname = ["xmlReadDoc", "xmlReadFd"] and xmlArg = 0 and optionsArg = 3 - or - fname = ["xmlCtxtReadFile", "xmlParseInNodeContext"] and xmlArg = 1 and optionsArg = 3 - or - fname = ["xmlCtxtReadDoc", "xmlCtxtReadFd"] and xmlArg = 1 and optionsArg = 4 - or - fname = "xmlReadMemory" and xmlArg = 0 and optionsArg = 4 - or - fname = "xmlCtxtReadMemory" and xmlArg = 1 and optionsArg = 5 - or - fname = "xmlReadIO" and xmlArg = 0 and optionsArg = 5 - or - fname = "xmlCtxtReadIO" and xmlArg = 1 and optionsArg = 6 - ) -} - /** * Holds if `e` is an expression that includes an unsafe `xmlParserOption`, * specifically `XML_PARSE_NOENT` (value 2, enables entity substitution) or @@ -91,7 +68,8 @@ private predicate libxml2ParseCall(Call call, int xmlArg, int optionsArg) { */ private predicate hasXxeOption(Expr e) { // Named constant XML_PARSE_NOENT or XML_PARSE_DTDLOAD - e.(PathExpr).getPath().getText() = ["XML_PARSE_NOENT", "XML_PARSE_DTDLOAD"] + e.(PathExpr).getPath().getText() = + ["xmlParserOption_XML_PARSE_NOENT", "xmlParserOption_XML_PARSE_DTDLOAD"] or // Integer literal with XML_PARSE_NOENT (bit 1) or XML_PARSE_DTDLOAD (bit 2) set exists(int v | diff --git a/rust/ql/src/queries/security/CWE-611/Xxe.ql b/rust/ql/src/queries/security/CWE-611/Xxe.ql index cd00f141816..384af3eb3ef 100644 --- a/rust/ql/src/queries/security/CWE-611/Xxe.ql +++ b/rust/ql/src/queries/security/CWE-611/Xxe.ql @@ -32,6 +32,12 @@ module XxeConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + // we need flow through casts as a *value* step, not just the default taint step, + // to get flow on reference content when the pointer itself is cast. + pred.asExpr() = succ.asExpr().(CastExpr).getExpr() + } + predicate observeDiffInformedIncrementalMode() { any() } } diff --git a/rust/ql/test/query-tests/security/CWE-611/Xxe.expected b/rust/ql/test/query-tests/security/CWE-611/Xxe.expected index 58f42bec0c8..852039e7ff6 100644 --- a/rust/ql/test/query-tests/security/CWE-611/Xxe.expected +++ b/rust/ql/test/query-tests/security/CWE-611/Xxe.expected @@ -1,4 +1,206 @@ #select +| main.rs:70:5:70:27 | ...::xmlReadMemory | main.rs:150:20:150:33 | ...::args | main.rs:70:5:70:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:75:5:75:27 | ...::xmlReadMemory | main.rs:150:20:150:33 | ...::args | main.rs:75:5:75:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:80:5:80:27 | ...::xmlReadMemory | main.rs:150:20:150:33 | ...::args | main.rs:80:5:80:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:85:5:85:25 | ...::xmlReadFile | main.rs:151:25:151:38 | ...::args | main.rs:85:5:85:25 | ...::xmlReadFile | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:151:25:151:38 | ...::args | user-provided value | +| main.rs:90:5:90:24 | ...::xmlReadDoc | main.rs:150:20:150:33 | ...::args | main.rs:90:5:90:24 | ...::xmlReadDoc | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:95:5:95:23 | ...::xmlReadFd | main.rs:152:21:152:39 | ...::open | main.rs:95:5:95:23 | ...::xmlReadFd | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:152:21:152:39 | ...::open | user-provided value | +| main.rs:100:5:100:29 | ...::xmlCtxtReadFile | main.rs:151:25:151:38 | ...::args | main.rs:100:5:100:29 | ...::xmlCtxtReadFile | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:151:25:151:38 | ...::args | user-provided value | +| main.rs:105:5:105:28 | ...::xmlCtxtReadDoc | main.rs:150:20:150:33 | ...::args | main.rs:105:5:105:28 | ...::xmlCtxtReadDoc | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:110:5:110:31 | ...::xmlCtxtReadMemory | main.rs:150:20:150:33 | ...::args | main.rs:110:5:110:31 | ...::xmlCtxtReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:122:5:122:27 | ...::xmlReadMemory | main.rs:150:20:150:33 | ...::args | main.rs:122:5:122:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | edges +| main.rs:68:32:68:45 | ...: ... [&ref] | main.rs:70:29:70:36 | user_xml [&ref] | provenance | | +| main.rs:70:29:70:36 | user_xml [&ref] | main.rs:70:29:70:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:70:29:70:45 | user_xml.as_ptr() [&ref] | main.rs:70:29:70:62 | ... as ... | provenance | | +| main.rs:70:29:70:45 | user_xml.as_ptr() [&ref] | main.rs:70:29:70:62 | ... as ... | provenance | Config | +| main.rs:70:29:70:62 | ... as ... | main.rs:70:5:70:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 | +| main.rs:73:34:73:47 | ...: ... [&ref] | main.rs:75:29:75:36 | user_xml [&ref] | provenance | | +| main.rs:75:29:75:36 | user_xml [&ref] | main.rs:75:29:75:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:75:29:75:45 | user_xml.as_ptr() [&ref] | main.rs:75:29:75:62 | ... as ... | provenance | | +| main.rs:75:29:75:45 | user_xml.as_ptr() [&ref] | main.rs:75:29:75:62 | ... as ... | provenance | Config | +| main.rs:75:29:75:62 | ... as ... | main.rs:75:5:75:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 | +| main.rs:78:35:78:48 | ...: ... [&ref] | main.rs:80:29:80:36 | user_xml [&ref] | provenance | | +| main.rs:80:29:80:36 | user_xml [&ref] | main.rs:80:29:80:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:80:29:80:45 | user_xml.as_ptr() [&ref] | main.rs:80:29:80:62 | ... as ... | provenance | | +| main.rs:80:29:80:45 | user_xml.as_ptr() [&ref] | main.rs:80:29:80:62 | ... as ... | provenance | Config | +| main.rs:80:29:80:62 | ... as ... | main.rs:80:5:80:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 | +| main.rs:83:34:83:52 | ...: ... [&ref] | main.rs:85:27:85:39 | user_filename [&ref] | provenance | | +| main.rs:85:27:85:39 | user_filename [&ref] | main.rs:85:27:85:48 | user_filename.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:85:27:85:48 | user_filename.as_ptr() [&ref] | main.rs:85:27:85:65 | ... as ... | provenance | | +| main.rs:85:27:85:48 | user_filename.as_ptr() [&ref] | main.rs:85:27:85:65 | ... as ... | provenance | Config | +| main.rs:85:27:85:65 | ... as ... | main.rs:85:5:85:25 | ...::xmlReadFile | provenance | MaD:6 Sink:MaD:6 | +| main.rs:88:33:88:46 | ...: ... [&ref] | main.rs:90:26:90:33 | user_xml [&ref] | provenance | | +| main.rs:90:26:90:33 | user_xml [&ref] | main.rs:90:26:90:42 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:90:26:90:42 | user_xml.as_ptr() [&ref] | main.rs:90:26:90:60 | ... as ... | provenance | | +| main.rs:90:26:90:42 | user_xml.as_ptr() [&ref] | main.rs:90:26:90:60 | ... as ... | provenance | Config | +| main.rs:90:26:90:60 | ... as ... | main.rs:90:5:90:24 | ...::xmlReadDoc | provenance | MaD:4 Sink:MaD:4 | +| main.rs:93:32:93:43 | ...: i32 [&ref] | main.rs:95:25:95:31 | user_fd [&ref] | provenance | | +| main.rs:95:25:95:31 | user_fd [&ref] | main.rs:95:5:95:23 | ...::xmlReadFd | provenance | MaD:5 Sink:MaD:5 | +| main.rs:98:39:98:57 | ...: ... [&ref] | main.rs:100:53:100:65 | user_filename [&ref] | provenance | | +| main.rs:100:53:100:65 | user_filename [&ref] | main.rs:100:53:100:74 | user_filename.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:100:53:100:74 | user_filename.as_ptr() [&ref] | main.rs:100:53:100:91 | ... as ... | provenance | | +| main.rs:100:53:100:74 | user_filename.as_ptr() [&ref] | main.rs:100:53:100:91 | ... as ... | provenance | Config | +| main.rs:100:53:100:91 | ... as ... | main.rs:100:5:100:29 | ...::xmlCtxtReadFile | provenance | MaD:2 Sink:MaD:2 | +| main.rs:103:38:103:51 | ...: ... [&ref] | main.rs:105:52:105:59 | user_xml [&ref] | provenance | | +| main.rs:105:52:105:59 | user_xml [&ref] | main.rs:105:52:105:68 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:105:52:105:68 | user_xml.as_ptr() [&ref] | main.rs:105:52:105:86 | ... as ... | provenance | | +| main.rs:105:52:105:68 | user_xml.as_ptr() [&ref] | main.rs:105:52:105:86 | ... as ... | provenance | Config | +| main.rs:105:52:105:86 | ... as ... | main.rs:105:5:105:28 | ...::xmlCtxtReadDoc | provenance | MaD:1 Sink:MaD:1 | +| main.rs:108:41:108:54 | ...: ... [&ref] | main.rs:112:9:112:16 | user_xml [&ref] | provenance | | +| main.rs:112:9:112:16 | user_xml [&ref] | main.rs:112:9:112:25 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:112:9:112:25 | user_xml.as_ptr() [&ref] | main.rs:112:9:112:42 | ... as ... | provenance | | +| main.rs:112:9:112:25 | user_xml.as_ptr() [&ref] | main.rs:112:9:112:42 | ... as ... | provenance | Config | +| main.rs:112:9:112:42 | ... as ... | main.rs:110:5:110:31 | ...::xmlCtxtReadMemory | provenance | MaD:3 Sink:MaD:3 | +| main.rs:120:36:120:49 | ...: ... [&ref] | main.rs:122:29:122:36 | user_xml [&ref] | provenance | | +| main.rs:122:29:122:36 | user_xml [&ref] | main.rs:122:29:122:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 | +| main.rs:122:29:122:45 | user_xml.as_ptr() [&ref] | main.rs:122:29:122:62 | ... as ... | provenance | | +| main.rs:122:29:122:45 | user_xml.as_ptr() [&ref] | main.rs:122:29:122:62 | ... as ... | provenance | Config | +| main.rs:122:29:122:62 | ... as ... | main.rs:122:5:122:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 | +| main.rs:150:9:150:16 | user_xml | main.rs:156:31:156:38 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:157:33:157:40 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:158:34:158:41 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:160:32:160:39 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:163:37:163:44 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:164:40:164:47 | user_xml | provenance | | +| main.rs:150:9:150:16 | user_xml | main.rs:165:35:165:42 | user_xml | provenance | | +| main.rs:150:20:150:33 | ...::args | main.rs:150:20:150:35 | ...::args(...) [element] | provenance | Src:MaD:9 | +| main.rs:150:20:150:35 | ...::args(...) [element] | main.rs:150:20:150:42 | ... .nth(...) [Some] | provenance | MaD:10 | +| main.rs:150:20:150:42 | ... .nth(...) [Some] | main.rs:150:20:150:62 | ... .unwrap_or_default() | provenance | MaD:13 | +| main.rs:150:20:150:62 | ... .unwrap_or_default() | main.rs:150:9:150:16 | user_xml | provenance | | +| main.rs:151:9:151:21 | user_filename | main.rs:159:33:159:45 | user_filename | provenance | | +| main.rs:151:9:151:21 | user_filename | main.rs:162:38:162:50 | user_filename | provenance | | +| main.rs:151:25:151:38 | ...::args | main.rs:151:25:151:40 | ...::args(...) [element] | provenance | Src:MaD:9 | +| main.rs:151:25:151:40 | ...::args(...) [element] | main.rs:151:25:151:47 | ... .nth(...) [Some] | provenance | MaD:10 | +| main.rs:151:25:151:47 | ... .nth(...) [Some] | main.rs:151:25:151:67 | ... .unwrap_or_default() | provenance | MaD:13 | +| main.rs:151:25:151:67 | ... .unwrap_or_default() | main.rs:151:9:151:21 | user_filename | provenance | | +| main.rs:152:9:152:17 | user_file [Some] | main.rs:153:19:153:27 | user_file [Some] | provenance | | +| main.rs:152:21:152:39 | ...::open | main.rs:152:21:152:55 | ...::open(...) [Ok] | provenance | Src:MaD:8 | +| main.rs:152:21:152:55 | ...::open(...) [Ok] | main.rs:152:21:152:60 | ... .ok() [Some] | provenance | MaD:14 | +| main.rs:152:21:152:60 | ... .ok() [Some] | main.rs:152:9:152:17 | user_file [Some] | provenance | | +| main.rs:153:9:153:15 | user_fd [&ref] | main.rs:161:30:161:36 | user_fd [&ref] | provenance | | +| main.rs:153:19:153:27 | user_file [Some] | main.rs:153:19:153:36 | user_file.as_ref() [Some, &ref] | provenance | MaD:11 | +| main.rs:153:19:153:36 | user_file.as_ref() [Some, &ref] | main.rs:153:19:153:72 | ... .map_or(...) [&ref] | provenance | MaD:12 | +| main.rs:153:19:153:72 | ... .map_or(...) [&ref] | main.rs:153:9:153:15 | user_fd [&ref] | provenance | | +| main.rs:156:30:156:38 | &user_xml [&ref] | main.rs:68:32:68:45 | ...: ... [&ref] | provenance | | +| main.rs:156:31:156:38 | user_xml | main.rs:156:30:156:38 | &user_xml [&ref] | provenance | | +| main.rs:157:32:157:40 | &user_xml [&ref] | main.rs:73:34:73:47 | ...: ... [&ref] | provenance | | +| main.rs:157:33:157:40 | user_xml | main.rs:157:32:157:40 | &user_xml [&ref] | provenance | | +| main.rs:158:33:158:41 | &user_xml [&ref] | main.rs:78:35:78:48 | ...: ... [&ref] | provenance | | +| main.rs:158:34:158:41 | user_xml | main.rs:158:33:158:41 | &user_xml [&ref] | provenance | | +| main.rs:159:32:159:45 | &user_filename [&ref] | main.rs:83:34:83:52 | ...: ... [&ref] | provenance | | +| main.rs:159:33:159:45 | user_filename | main.rs:159:32:159:45 | &user_filename [&ref] | provenance | | +| main.rs:160:31:160:39 | &user_xml [&ref] | main.rs:88:33:88:46 | ...: ... [&ref] | provenance | | +| main.rs:160:32:160:39 | user_xml | main.rs:160:31:160:39 | &user_xml [&ref] | provenance | | +| main.rs:161:30:161:36 | user_fd [&ref] | main.rs:93:32:93:43 | ...: i32 [&ref] | provenance | | +| main.rs:162:37:162:50 | &user_filename [&ref] | main.rs:98:39:98:57 | ...: ... [&ref] | provenance | | +| main.rs:162:38:162:50 | user_filename | main.rs:162:37:162:50 | &user_filename [&ref] | provenance | | +| main.rs:163:36:163:44 | &user_xml [&ref] | main.rs:103:38:103:51 | ...: ... [&ref] | provenance | | +| main.rs:163:37:163:44 | user_xml | main.rs:163:36:163:44 | &user_xml [&ref] | provenance | | +| main.rs:164:39:164:47 | &user_xml [&ref] | main.rs:108:41:108:54 | ...: ... [&ref] | provenance | | +| main.rs:164:40:164:47 | user_xml | main.rs:164:39:164:47 | &user_xml [&ref] | provenance | | +| main.rs:165:34:165:42 | &user_xml [&ref] | main.rs:120:36:120:49 | ...: ... [&ref] | provenance | | +| main.rs:165:35:165:42 | user_xml | main.rs:165:34:165:42 | &user_xml [&ref] | provenance | | +models +| 1 | Sink: libxml::bindings::xmlCtxtReadDoc; Argument[1].Reference; xxe | +| 2 | Sink: libxml::bindings::xmlCtxtReadFile; Argument[1].Reference; xxe | +| 3 | Sink: libxml::bindings::xmlCtxtReadMemory; Argument[1].Reference; xxe | +| 4 | Sink: libxml::bindings::xmlReadDoc; Argument[0].Reference; xxe | +| 5 | Sink: libxml::bindings::xmlReadFd; Argument[0]; xxe | +| 6 | Sink: libxml::bindings::xmlReadFile; Argument[0].Reference; xxe | +| 7 | Sink: libxml::bindings::xmlReadMemory; Argument[0].Reference; xxe | +| 8 | Source: ::open; ReturnValue.Field[core::result::Result::Ok(0)]; file | +| 9 | Source: std::env::args; ReturnValue.Element; commandargs | +| 10 | Summary: <_ as core::iter::traits::iterator::Iterator>::nth; Argument[self].Reference.Element; ReturnValue.Field[core::option::Option::Some(0)]; value | +| 11 | Summary: ::as_ref; Argument[self].Reference.Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Reference; value | +| 12 | Summary: ::map_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | +| 13 | Summary: ::unwrap_or_default; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | +| 14 | Summary: ::ok; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue.Field[core::option::Option::Some(0)]; value | +| 15 | Summary: ::as_ptr; Argument[self].Reference; ReturnValue.Reference; taint | nodes +| main.rs:68:32:68:45 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:70:5:70:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory | +| main.rs:70:29:70:36 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:70:29:70:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:70:29:70:62 | ... as ... | semmle.label | ... as ... | +| main.rs:73:34:73:47 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:75:5:75:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory | +| main.rs:75:29:75:36 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:75:29:75:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:75:29:75:62 | ... as ... | semmle.label | ... as ... | +| main.rs:78:35:78:48 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:80:5:80:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory | +| main.rs:80:29:80:36 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:80:29:80:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:80:29:80:62 | ... as ... | semmle.label | ... as ... | +| main.rs:83:34:83:52 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:85:5:85:25 | ...::xmlReadFile | semmle.label | ...::xmlReadFile | +| main.rs:85:27:85:39 | user_filename [&ref] | semmle.label | user_filename [&ref] | +| main.rs:85:27:85:48 | user_filename.as_ptr() [&ref] | semmle.label | user_filename.as_ptr() [&ref] | +| main.rs:85:27:85:65 | ... as ... | semmle.label | ... as ... | +| main.rs:88:33:88:46 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:90:5:90:24 | ...::xmlReadDoc | semmle.label | ...::xmlReadDoc | +| main.rs:90:26:90:33 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:90:26:90:42 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:90:26:90:60 | ... as ... | semmle.label | ... as ... | +| main.rs:93:32:93:43 | ...: i32 [&ref] | semmle.label | ...: i32 [&ref] | +| main.rs:95:5:95:23 | ...::xmlReadFd | semmle.label | ...::xmlReadFd | +| main.rs:95:25:95:31 | user_fd [&ref] | semmle.label | user_fd [&ref] | +| main.rs:98:39:98:57 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:100:5:100:29 | ...::xmlCtxtReadFile | semmle.label | ...::xmlCtxtReadFile | +| main.rs:100:53:100:65 | user_filename [&ref] | semmle.label | user_filename [&ref] | +| main.rs:100:53:100:74 | user_filename.as_ptr() [&ref] | semmle.label | user_filename.as_ptr() [&ref] | +| main.rs:100:53:100:91 | ... as ... | semmle.label | ... as ... | +| main.rs:103:38:103:51 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:105:5:105:28 | ...::xmlCtxtReadDoc | semmle.label | ...::xmlCtxtReadDoc | +| main.rs:105:52:105:59 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:105:52:105:68 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:105:52:105:86 | ... as ... | semmle.label | ... as ... | +| main.rs:108:41:108:54 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:110:5:110:31 | ...::xmlCtxtReadMemory | semmle.label | ...::xmlCtxtReadMemory | +| main.rs:112:9:112:16 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:112:9:112:25 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:112:9:112:42 | ... as ... | semmle.label | ... as ... | +| main.rs:120:36:120:49 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:122:5:122:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory | +| main.rs:122:29:122:36 | user_xml [&ref] | semmle.label | user_xml [&ref] | +| main.rs:122:29:122:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] | +| main.rs:122:29:122:62 | ... as ... | semmle.label | ... as ... | +| main.rs:150:9:150:16 | user_xml | semmle.label | user_xml | +| main.rs:150:20:150:33 | ...::args | semmle.label | ...::args | +| main.rs:150:20:150:35 | ...::args(...) [element] | semmle.label | ...::args(...) [element] | +| main.rs:150:20:150:42 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] | +| main.rs:150:20:150:62 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | +| main.rs:151:9:151:21 | user_filename | semmle.label | user_filename | +| main.rs:151:25:151:38 | ...::args | semmle.label | ...::args | +| main.rs:151:25:151:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] | +| main.rs:151:25:151:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] | +| main.rs:151:25:151:67 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | +| main.rs:152:9:152:17 | user_file [Some] | semmle.label | user_file [Some] | +| main.rs:152:21:152:39 | ...::open | semmle.label | ...::open | +| main.rs:152:21:152:55 | ...::open(...) [Ok] | semmle.label | ...::open(...) [Ok] | +| main.rs:152:21:152:60 | ... .ok() [Some] | semmle.label | ... .ok() [Some] | +| main.rs:153:9:153:15 | user_fd [&ref] | semmle.label | user_fd [&ref] | +| main.rs:153:19:153:27 | user_file [Some] | semmle.label | user_file [Some] | +| main.rs:153:19:153:36 | user_file.as_ref() [Some, &ref] | semmle.label | user_file.as_ref() [Some, &ref] | +| main.rs:153:19:153:72 | ... .map_or(...) [&ref] | semmle.label | ... .map_or(...) [&ref] | +| main.rs:156:30:156:38 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:156:31:156:38 | user_xml | semmle.label | user_xml | +| main.rs:157:32:157:40 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:157:33:157:40 | user_xml | semmle.label | user_xml | +| main.rs:158:33:158:41 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:158:34:158:41 | user_xml | semmle.label | user_xml | +| main.rs:159:32:159:45 | &user_filename [&ref] | semmle.label | &user_filename [&ref] | +| main.rs:159:33:159:45 | user_filename | semmle.label | user_filename | +| main.rs:160:31:160:39 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:160:32:160:39 | user_xml | semmle.label | user_xml | +| main.rs:161:30:161:36 | user_fd [&ref] | semmle.label | user_fd [&ref] | +| main.rs:162:37:162:50 | &user_filename [&ref] | semmle.label | &user_filename [&ref] | +| main.rs:162:38:162:50 | user_filename | semmle.label | user_filename | +| main.rs:163:36:163:44 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:163:37:163:44 | user_xml | semmle.label | user_xml | +| main.rs:164:39:164:47 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:164:40:164:47 | user_xml | semmle.label | user_xml | +| main.rs:165:34:165:42 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | +| main.rs:165:35:165:42 | user_xml | semmle.label | user_xml | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-611/main.rs b/rust/ql/test/query-tests/security/CWE-611/main.rs index d4e768b87dd..2cc19d3494c 100644 --- a/rust/ql/test/query-tests/security/CWE-611/main.rs +++ b/rust/ql/test/query-tests/security/CWE-611/main.rs @@ -67,49 +67,49 @@ use std::os::raw::{c_char, c_uchar}; unsafe fn test_xml_parse_noent(user_xml: &str) { // BAD: XML_PARSE_NOENT enables external entity substitution - bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_parse_dtdload(user_xml: &str) { // BAD: XML_PARSE_DTDLOAD enables loading of external DTD subsets - bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_parse_combined(user_xml: &str) { // BAD: combining both unsafe options - bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32 | bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32 | bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_read_file_bad(user_filename: &str) { // BAD: user-controlled filename with XML_PARSE_NOENT - bindings::xmlReadFile(user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadFile(user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_read_doc_bad(user_xml: &str) { // BAD: user-controlled XML document with XML_PARSE_DTDLOAD - bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_read_fd_bad(user_fd: i32) { // BAD: user-controlled file descriptor with XML_PARSE_DTDLOAD - bindings::xmlReadFd(user_fd, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadFd(user_fd, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_ctxt_read_file_bad(user_filename: &str) { // BAD: user-controlled filename with XML_PARSE_NOENT via ctxt variant - bindings::xmlCtxtReadFile(std::ptr::null_mut(), user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlCtxtReadFile(std::ptr::null_mut(), user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_ctxt_read_doc_bad(user_xml: &str) { // BAD: user-controlled XML with unsafe options via ctxt variant - bindings::xmlCtxtReadDoc(std::ptr::null_mut(), user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ MISSING: Alert[rust/xxe] + bindings::xmlCtxtReadDoc(std::ptr::null_mut(), user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe] } unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) { // BAD: user-controlled XML with unsafe options via ctxt variant - bindings::xmlCtxtReadMemory( + bindings::xmlCtxtReadMemory( // $ Alert[rust/xxe] std::ptr::null_mut(), - user_xml.as_ptr() as *const c_char, // $ MISSING: Alert[rust/xxe] + user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), @@ -119,7 +119,7 @@ unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) { unsafe fn test_integer_literal_bad(user_xml: &str) { // BAD: literal value 2 = XML_PARSE_NOENT - bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 2); // $ MISSING: Alert[rust/xxe] + bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 2); // $ Alert[rust/xxe] } unsafe fn test_dataflow_bad(user_xml: &str) { @@ -147,9 +147,9 @@ unsafe fn test_xml_hardcoded_unsafe() { } fn main() { - let user_xml = std::env::args().nth(1).unwrap_or_default(); // $ MISSING: Source - let user_filename = std::env::args().nth(2).unwrap_or_default(); // $ MISSING: Source - let user_file = std::fs::File::open(&user_filename).ok(); // $ MISSING: Source + let user_xml = std::env::args().nth(1).unwrap_or_default(); // $ Source + let user_filename = std::env::args().nth(2).unwrap_or_default(); // $ Source + let user_file = std::fs::File::open(&user_filename).ok(); // $ Source let user_fd = user_file.as_ref().map_or(-1, |file| file.as_raw_fd()); unsafe {