From 2f3bd412168aabe81c9de886f1a0fe4dbd6a4126 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:50:25 +0100 Subject: [PATCH] Rust: Replace stub calls with actual calls. Note that we lose results (likely a models issue). --- .../query-tests/security/CWE-611/Xxe.expected | 128 ++---------------- .../test/query-tests/security/CWE-611/main.rs | 98 +++++++------- 2 files changed, 63 insertions(+), 163 deletions(-) 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 ea26db0a077..c642f4401b6 100644 --- a/rust/ql/test/query-tests/security/CWE-611/Xxe.expected +++ b/rust/ql/test/query-tests/security/CWE-611/Xxe.expected @@ -1,108 +1,24 @@ #select -| main.rs:70:19:70:26 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:70:19:70:26 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:75:19:75:26 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:75:19:75:26 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:80:19:80:26 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:80:19:80:26 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:85:17:85:29 | user_filename | main.rs:151:25:151:38 | ...::args | main.rs:85:17:85:29 | user_filename | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:151:25:151:38 | ...::args | user-provided value | -| main.rs:90:16:90:23 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:90:16:90:23 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:95:15:95:21 | user_fd | main.rs:152:21:152:39 | ...::open | main.rs:95:15:95:21 | user_fd | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:152:21:152:39 | ...::open | user-provided value | -| main.rs:100:43:100:55 | user_filename | main.rs:151:25:151:38 | ...::args | main.rs:100:43:100:55 | user_filename | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:151:25:151:38 | ...::args | user-provided value | -| main.rs:105:42:105:49 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:105:42:105:49 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:112:9:112:16 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:112:9:112:16 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | -| main.rs:122:19:122:26 | user_xml | main.rs:150:20:150:33 | ...::args | main.rs:122:19:122:26 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:150:20:150:33 | ...::args | user-provided value | +| main.rs:95:25:95:31 | user_fd | main.rs:152:21:152:39 | ...::open | main.rs:95:25:95:31 | user_fd | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:152:21:152:39 | ...::open | user-provided value | edges -| main.rs:68:25:68:38 | ...: ... [&ref] | main.rs:70:19:70:26 | user_xml | provenance | | -| main.rs:73:27:73:40 | ...: ... [&ref] | main.rs:75:19:75:26 | user_xml | provenance | | -| main.rs:78:28:78:41 | ...: ... [&ref] | main.rs:80:19:80:26 | user_xml | provenance | | -| main.rs:83:27:83:45 | ...: ... [&ref] | main.rs:85:17:85:29 | user_filename | provenance | | -| main.rs:88:26:88:39 | ...: ... [&ref] | main.rs:90:16:90:23 | user_xml | provenance | | -| main.rs:93:25:93:36 | ...: i32 [&ref] | main.rs:95:15:95:21 | user_fd | provenance | | -| main.rs:98:32:98:50 | ...: ... [&ref] | main.rs:100:43:100:55 | user_filename | provenance | | -| main.rs:103:31:103:44 | ...: ... [&ref] | main.rs:105:42:105:49 | user_xml | provenance | | -| main.rs:108:34:108:47 | ...: ... [&ref] | main.rs:112:9:112:16 | user_xml | provenance | | -| main.rs:120:29:120:42 | ...: ... [&ref] | main.rs:122:19:122:26 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:155:27:155:34 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:156:29:156:36 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:157:30:157:37 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:159:28:159:35 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:162:33:162:40 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:163:36:163:43 | user_xml | provenance | | -| main.rs:150:9:150:16 | user_xml | main.rs:164:31:164:38 | user_xml | provenance | | -| main.rs:150:20:150:33 | ...::args | main.rs:150:20:150:35 | ...::args(...) [element] | provenance | Src:MaD:2 | -| main.rs:150:20:150:35 | ...::args(...) [element] | main.rs:150:20:150:42 | ... .nth(...) [Some] | provenance | MaD:3 | -| main.rs:150:20:150:42 | ... .nth(...) [Some] | main.rs:150:20:150:62 | ... .unwrap_or_default() | provenance | MaD:6 | -| 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:158:29:158:41 | user_filename | provenance | | -| main.rs:151:9:151:21 | user_filename | main.rs:161:34:161:46 | user_filename | provenance | | -| main.rs:151:25:151:38 | ...::args | main.rs:151:25:151:40 | ...::args(...) [element] | provenance | Src:MaD:2 | -| main.rs:151:25:151:40 | ...::args(...) [element] | main.rs:151:25:151:47 | ... .nth(...) [Some] | provenance | MaD:3 | -| main.rs:151:25:151:47 | ... .nth(...) [Some] | main.rs:151:25:151:67 | ... .unwrap_or_default() | provenance | MaD:6 | -| main.rs:151:25:151:67 | ... .unwrap_or_default() | main.rs:151:9:151:21 | user_filename | provenance | | +| main.rs:93:32:93:43 | ...: i32 [&ref] | main.rs:95:25:95:31 | user_fd | 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:1 | -| main.rs:152:21:152:55 | ...::open(...) [Ok] | main.rs:152:21:152:60 | ... .ok() [Some] | provenance | MaD:7 | +| main.rs:152:21:152:55 | ...::open(...) [Ok] | main.rs:152:21:152:60 | ... .ok() [Some] | provenance | MaD:4 | | 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:160:26:160:32 | 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:4 | -| main.rs:153:19:153:36 | user_file.as_ref() [Some, &ref] | main.rs:153:19:153:72 | ... .map_or(...) [&ref] | provenance | MaD:5 | +| 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:2 | +| main.rs:153:19:153:36 | user_file.as_ref() [Some, &ref] | main.rs:153:19:153:72 | ... .map_or(...) [&ref] | provenance | MaD:3 | | main.rs:153:19:153:72 | ... .map_or(...) [&ref] | main.rs:153:9:153:15 | user_fd [&ref] | provenance | | -| main.rs:155:26:155:34 | &user_xml [&ref] | main.rs:68:25:68:38 | ...: ... [&ref] | provenance | | -| main.rs:155:27:155:34 | user_xml | main.rs:155:26:155:34 | &user_xml [&ref] | provenance | | -| main.rs:156:28:156:36 | &user_xml [&ref] | main.rs:73:27:73:40 | ...: ... [&ref] | provenance | | -| main.rs:156:29:156:36 | user_xml | main.rs:156:28:156:36 | &user_xml [&ref] | provenance | | -| main.rs:157:29:157:37 | &user_xml [&ref] | main.rs:78:28:78:41 | ...: ... [&ref] | provenance | | -| main.rs:157:30:157:37 | user_xml | main.rs:157:29:157:37 | &user_xml [&ref] | provenance | | -| main.rs:158:28:158:41 | &user_filename [&ref] | main.rs:83:27:83:45 | ...: ... [&ref] | provenance | | -| main.rs:158:29:158:41 | user_filename | main.rs:158:28:158:41 | &user_filename [&ref] | provenance | | -| main.rs:159:27:159:35 | &user_xml [&ref] | main.rs:88:26:88:39 | ...: ... [&ref] | provenance | | -| main.rs:159:28:159:35 | user_xml | main.rs:159:27:159:35 | &user_xml [&ref] | provenance | | -| main.rs:160:26:160:32 | user_fd [&ref] | main.rs:93:25:93:36 | ...: i32 [&ref] | provenance | | -| main.rs:161:33:161:46 | &user_filename [&ref] | main.rs:98:32:98:50 | ...: ... [&ref] | provenance | | -| main.rs:161:34:161:46 | user_filename | main.rs:161:33:161:46 | &user_filename [&ref] | provenance | | -| main.rs:162:32:162:40 | &user_xml [&ref] | main.rs:103:31:103:44 | ...: ... [&ref] | provenance | | -| main.rs:162:33:162:40 | user_xml | main.rs:162:32:162:40 | &user_xml [&ref] | provenance | | -| main.rs:163:35:163:43 | &user_xml [&ref] | main.rs:108:34:108:47 | ...: ... [&ref] | provenance | | -| main.rs:163:36:163:43 | user_xml | main.rs:163:35:163:43 | &user_xml [&ref] | provenance | | -| main.rs:164:30:164:38 | &user_xml [&ref] | main.rs:120:29:120:42 | ...: ... [&ref] | provenance | | -| main.rs:164:31:164:38 | user_xml | main.rs:164:30:164:38 | &user_xml [&ref] | provenance | | +| main.rs:161:30:161:36 | user_fd [&ref] | main.rs:93:32:93:43 | ...: i32 [&ref] | provenance | | models | 1 | Source: ::open; ReturnValue.Field[core::result::Result::Ok(0)]; file | -| 2 | Source: std::env::args; ReturnValue.Element; commandargs | -| 3 | Summary: <_ as core::iter::traits::iterator::Iterator>::nth; Argument[self].Reference.Element; ReturnValue.Field[core::option::Option::Some(0)]; value | -| 4 | Summary: ::as_ref; Argument[self].Reference.Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Reference; value | -| 5 | Summary: ::map_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | -| 6 | Summary: ::unwrap_or_default; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | -| 7 | Summary: ::ok; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue.Field[core::option::Option::Some(0)]; value | +| 2 | Summary: ::as_ref; Argument[self].Reference.Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Reference; value | +| 3 | Summary: ::map_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | +| 4 | Summary: ::ok; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue.Field[core::option::Option::Some(0)]; value | nodes -| main.rs:68:25:68:38 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:70:19:70:26 | user_xml | semmle.label | user_xml | -| main.rs:73:27:73:40 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:75:19:75:26 | user_xml | semmle.label | user_xml | -| main.rs:78:28:78:41 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:80:19:80:26 | user_xml | semmle.label | user_xml | -| main.rs:83:27:83:45 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:85:17:85:29 | user_filename | semmle.label | user_filename | -| main.rs:88:26:88:39 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:90:16:90:23 | user_xml | semmle.label | user_xml | -| main.rs:93:25:93:36 | ...: i32 [&ref] | semmle.label | ...: i32 [&ref] | -| main.rs:95:15:95:21 | user_fd | semmle.label | user_fd | -| main.rs:98:32:98:50 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:100:43:100:55 | user_filename | semmle.label | user_filename | -| main.rs:103:31:103:44 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:105:42:105:49 | user_xml | semmle.label | user_xml | -| main.rs:108:34:108:47 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:112:9:112:16 | user_xml | semmle.label | user_xml | -| main.rs:120:29:120:42 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | -| main.rs:122:19:122:26 | user_xml | semmle.label | user_xml | -| 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:93:32:93:43 | ...: i32 [&ref] | semmle.label | ...: i32 [&ref] | +| main.rs:95:25:95:31 | user_fd | semmle.label | user_fd | | 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] | @@ -111,23 +27,5 @@ nodes | 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:155:26:155:34 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:155:27:155:34 | user_xml | semmle.label | user_xml | -| main.rs:156:28:156:36 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:156:29:156:36 | user_xml | semmle.label | user_xml | -| main.rs:157:29:157:37 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:157:30:157:37 | user_xml | semmle.label | user_xml | -| main.rs:158:28:158:41 | &user_filename [&ref] | semmle.label | &user_filename [&ref] | -| main.rs:158:29:158:41 | user_filename | semmle.label | user_filename | -| main.rs:159:27:159:35 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:159:28:159:35 | user_xml | semmle.label | user_xml | -| main.rs:160:26:160:32 | user_fd [&ref] | semmle.label | user_fd [&ref] | -| main.rs:161:33:161:46 | &user_filename [&ref] | semmle.label | &user_filename [&ref] | -| main.rs:161:34:161:46 | user_filename | semmle.label | user_filename | -| main.rs:162:32:162:40 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:162:33:162:40 | user_xml | semmle.label | user_xml | -| main.rs:163:35:163:43 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:163:36:163:43 | user_xml | semmle.label | user_xml | -| main.rs:164:30:164:38 | &user_xml [&ref] | semmle.label | &user_xml [&ref] | -| main.rs:164:31:164:38 | user_xml | semmle.label | user_xml | +| main.rs:161:30:161:36 | user_fd [&ref] | semmle.label | user_fd [&ref] | 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 83f8236d9c2..d06c634319b 100644 --- a/rust/ql/test/query-tests/security/CWE-611/main.rs +++ b/rust/ql/test/query-tests/security/CWE-611/main.rs @@ -1,9 +1,9 @@ use libxml::bindings; use std::os::fd::AsRawFd; +use std::os::raw::{c_char, c_uchar}; // Stub types and constants to simulate libxml2 bindings pub struct XmlDoc; pub struct XmlParserCtxt; - // xmlParserOption constants const XML_PARSE_NOENT: i32 = 2; // substitute entities const XML_PARSE_DTDLOAD: i32 = 4; // load the external subset @@ -65,104 +65,106 @@ fn xmlCtxtUseOptions(_ctxt: *mut XmlParserCtxt, _options: i32) -> i32 { // --- BAD: user-controlled XML with unsafe parser options --- -fn test_xml_parse_noent(user_xml: &str) { +unsafe fn test_xml_parse_noent(user_xml: &str) { // BAD: XML_PARSE_NOENT enables external entity substitution - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", XML_PARSE_NOENT); // $ 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(), XML_PARSE_NOENT); // $ MISSING: Alert[rust/xxe] } -fn test_xml_parse_dtdload(user_xml: &str) { +unsafe fn test_xml_parse_dtdload(user_xml: &str) { // BAD: XML_PARSE_DTDLOAD enables loading of external DTD subsets - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", XML_PARSE_DTDLOAD); // $ 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(), XML_PARSE_DTDLOAD); // $ MISSING: Alert[rust/xxe] } -fn test_xml_parse_combined(user_xml: &str) { +unsafe fn test_xml_parse_combined(user_xml: &str) { // BAD: combining both unsafe options - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // $ 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(), XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // $ MISSING: Alert[rust/xxe] } -fn test_xml_read_file_bad(user_filename: &str) { +unsafe fn test_xml_read_file_bad(user_filename: &str) { // BAD: user-controlled filename with XML_PARSE_NOENT - xmlReadFile(user_filename, "", XML_PARSE_NOENT); // $ Alert[rust/xxe] + bindings::xmlReadFile(user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), XML_PARSE_NOENT); // $ MISSING: Alert[rust/xxe] } -fn test_xml_read_doc_bad(user_xml: &str) { +unsafe fn test_xml_read_doc_bad(user_xml: &str) { // BAD: user-controlled XML document with XML_PARSE_DTDLOAD - xmlReadDoc(user_xml, "", "", XML_PARSE_DTDLOAD); // $ Alert[rust/xxe] + bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), XML_PARSE_DTDLOAD); // $ MISSING: Alert[rust/xxe] } -fn test_xml_read_fd_bad(user_fd: i32) { +unsafe fn test_xml_read_fd_bad(user_fd: i32) { // BAD: user-controlled file descriptor with XML_PARSE_DTDLOAD - xmlReadFd(user_fd, "", "", XML_PARSE_DTDLOAD); // $ Alert[rust/xxe] + bindings::xmlReadFd(user_fd, std::ptr::null_mut(), std::ptr::null_mut(), XML_PARSE_DTDLOAD); // $ Alert[rust/xxe] } -fn test_xml_ctxt_read_file_bad(user_filename: &str) { +unsafe fn test_xml_ctxt_read_file_bad(user_filename: &str) { // BAD: user-controlled filename with XML_PARSE_NOENT via ctxt variant - xmlCtxtReadFile(std::ptr::null_mut(), user_filename, "", XML_PARSE_NOENT); // $ Alert[rust/xxe] + bindings::xmlCtxtReadFile(std::ptr::null_mut(), user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), XML_PARSE_NOENT); // $ MISSING: Alert[rust/xxe] } -fn test_xml_ctxt_read_doc_bad(user_xml: &str) { +unsafe fn test_xml_ctxt_read_doc_bad(user_xml: &str) { // BAD: user-controlled XML with unsafe options via ctxt variant - xmlCtxtReadDoc(std::ptr::null_mut(), user_xml, "", "", XML_PARSE_NOENT); // $ 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(), XML_PARSE_NOENT); // $ MISSING: Alert[rust/xxe] } -fn test_xml_ctxt_read_memory_bad(user_xml: &str) { +unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) { // BAD: user-controlled XML with unsafe options via ctxt variant - xmlCtxtReadMemory( + bindings::xmlCtxtReadMemory( std::ptr::null_mut(), - user_xml, // $ Alert[rust/xxe] + user_xml.as_ptr() as *const c_char, // $ MISSING: Alert[rust/xxe] user_xml.len() as i32, - "", - "", + std::ptr::null_mut(), + std::ptr::null_mut(), XML_PARSE_NOENT, ); } -fn test_integer_literal_bad(user_xml: &str) { +unsafe fn test_integer_literal_bad(user_xml: &str) { // BAD: literal value 2 = XML_PARSE_NOENT - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", 2); // $ 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); // $ MISSING: Alert[rust/xxe] } -fn test_dataflow_bad(user_xml: &str) { +unsafe fn test_dataflow_bad(user_xml: &str) { // BAD: user-controlled XML with unsafe parser options via dataflow let flags = XML_PARSE_NOENT | 1024; - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", flags); // $ 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(), flags); // $ MISSING: Alert[rust/xxe] } // --- GOOD: user-controlled XML with safe parser options --- -fn test_xml_parse_safe_options(user_xml: &str) { +unsafe fn test_xml_parse_safe_options(user_xml: &str) { // GOOD: options = 0 means no entity expansion - xmlReadMemory(user_xml, user_xml.len() as i32, "", "", 0); - xmlReadFile(user_xml, "", 0); - xmlReadDoc(user_xml, "", "", 0); + bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 0); + bindings::xmlReadFile(user_xml.as_ptr() as *const c_char, std::ptr::null_mut(), 0); + bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), 0); } // --- GOOD: hardcoded (non-user-controlled) XML with unsafe parser options --- -fn test_xml_hardcoded_unsafe() { +unsafe fn test_xml_hardcoded_unsafe() { let xml = ""; // GOOD: XML content is not user-controlled - xmlReadMemory(xml, xml.len() as i32, "", "", XML_PARSE_NOENT); - xmlReadFile("trusted/input.xml", "", XML_PARSE_NOENT); + bindings::xmlReadMemory(xml.as_ptr() as *const c_char, xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), XML_PARSE_NOENT); + bindings::xmlReadFile("trusted/input.xml".as_ptr() as *const c_char, std::ptr::null_mut(), XML_PARSE_NOENT); } fn main() { - 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_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(); // $ Source let user_fd = user_file.as_ref().map_or(-1, |file| file.as_raw_fd()); - test_xml_parse_noent(&user_xml); - test_xml_parse_dtdload(&user_xml); - test_xml_parse_combined(&user_xml); - test_xml_read_file_bad(&user_filename); - test_xml_read_doc_bad(&user_xml); - test_xml_read_fd_bad(user_fd); - test_xml_ctxt_read_file_bad(&user_filename); - test_xml_ctxt_read_doc_bad(&user_xml); - test_xml_ctxt_read_memory_bad(&user_xml); - test_integer_literal_bad(&user_xml); - test_dataflow_bad(&user_xml); - test_xml_parse_safe_options(&user_xml); - test_xml_hardcoded_unsafe(); + unsafe { + test_xml_parse_noent(&user_xml); + test_xml_parse_dtdload(&user_xml); + test_xml_parse_combined(&user_xml); + test_xml_read_file_bad(&user_filename); + test_xml_read_doc_bad(&user_xml); + test_xml_read_fd_bad(user_fd); + test_xml_ctxt_read_file_bad(&user_filename); + test_xml_ctxt_read_doc_bad(&user_xml); + test_xml_ctxt_read_memory_bad(&user_xml); + test_integer_literal_bad(&user_xml); + test_dataflow_bad(&user_xml); + test_xml_parse_safe_options(&user_xml); + test_xml_hardcoded_unsafe(); + } }