Rust: Convert sinks to Models As Data, fixing in the process.

This commit is contained in:
Geoffrey White
2026-06-24 13:58:13 +01:00
parent a322744ee2
commit ae5896416e
6 changed files with 252 additions and 48 deletions

View File

@@ -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"]

View File

@@ -126,6 +126,8 @@ extensions:
# Str
- ["<core::str>::as_str", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
- ["<core::str>::as_bytes", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
- ["<core::str>::as_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
- ["<core::str>::as_mut_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
- ["<core::str>::parse", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
- ["<core::str>::trim", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
- ["<core::str>::to_string", "Argument[self].Reference", "ReturnValue", "taint", "manual"]

View File

@@ -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 |

View File

@@ -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() }
}

View File

@@ -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: <std::fs::File>::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: <core::option::Option>::as_ref; Argument[self].Reference.Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Reference; value |
| 12 | Summary: <core::option::Option>::map_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
| 13 | Summary: <core::option::Option>::unwrap_or_default; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
| 14 | Summary: <core::result::Result>::ok; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue.Field[core::option::Option::Some(0)]; value |
| 15 | Summary: <core::str>::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

View File

@@ -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 {