From a322744ee2e27b279c720d742c7e0f6b0d4c2df6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:57:47 +0100 Subject: [PATCH] Rust: Unstub the constants as well. --- .../query-tests/security/CWE-611/Xxe.expected | 27 ---------------- .../test/query-tests/security/CWE-611/main.rs | 32 +++++++++---------- 2 files changed, 16 insertions(+), 43 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 c642f4401b6..58f42bec0c8 100644 --- a/rust/ql/test/query-tests/security/CWE-611/Xxe.expected +++ b/rust/ql/test/query-tests/security/CWE-611/Xxe.expected @@ -1,31 +1,4 @@ #select -| 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: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: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: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: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 | 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: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] | -| 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: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 72300b67299..d4e768b87dd 100644 --- a/rust/ql/test/query-tests/security/CWE-611/main.rs +++ b/rust/ql/test/query-tests/security/CWE-611/main.rs @@ -4,9 +4,9 @@ use std::os::raw::{c_char, c_uchar}; -// xmlParserOption constants -const XML_PARSE_NOENT: i32 = 2; // substitute entities -const XML_PARSE_DTDLOAD: i32 = 4; // load the external subset + + + @@ -67,42 +67,42 @@ const XML_PARSE_DTDLOAD: i32 = 4; // load the external subset 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(), XML_PARSE_NOENT); // $ 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); // $ MISSING: 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(), XML_PARSE_DTDLOAD); // $ 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); // $ MISSING: 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(), XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // $ 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); // $ MISSING: 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(), XML_PARSE_NOENT); // $ 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); // $ MISSING: 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(), XML_PARSE_DTDLOAD); // $ 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); // $ MISSING: 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(), XML_PARSE_DTDLOAD); // $ Alert[rust/xxe] + bindings::xmlReadFd(user_fd, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ MISSING: 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(), XML_PARSE_NOENT); // $ 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); // $ MISSING: 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(), XML_PARSE_NOENT); // $ 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); // $ MISSING: Alert[rust/xxe] } unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) { @@ -113,7 +113,7 @@ unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) { user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), - XML_PARSE_NOENT, + bindings::xmlParserOption_XML_PARSE_NOENT as i32, ); } @@ -124,7 +124,7 @@ unsafe fn test_integer_literal_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; + let flags = bindings::xmlParserOption_XML_PARSE_NOENT as i32 | 1024; 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] } @@ -142,14 +142,14 @@ unsafe fn test_xml_parse_safe_options(user_xml: &str) { unsafe fn test_xml_hardcoded_unsafe() { let xml = ""; // GOOD: XML content is not user-controlled - 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); + bindings::xmlReadMemory(xml.as_ptr() as *const c_char, xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); + bindings::xmlReadFile("trusted/input.xml".as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); } 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(); // $ Source + let user_file = std::fs::File::open(&user_filename).ok(); // $ MISSING: Source let user_fd = user_file.as_ref().map_or(-1, |file| file.as_raw_fd()); unsafe {