Skip to content

Commit ad73a92

Browse files
johnynekOscar Boykin
and
Oscar Boykin
authored
Avoid creating bad CDATA sections (#1082)
* Avoid creating bad CDATA sections * remove unused import * format * address another clippy lint --------- Co-authored-by: Oscar Boykin <[email protected]>
1 parent f4f699b commit ad73a92

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

bazelfe-core/src/bep_junit/junit_xml_error_writer.rs

+80-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl XmlWritable for TestSuite {
4040
.attr("tests", tests.as_str())
4141
.attr("failures", failures.as_str());
4242

43-
writer.write(e).unwrap();
43+
writer.write(e)?;
4444

4545
for s in self.testcases.iter() {
4646
s.write_xml(writer)?;
@@ -93,11 +93,32 @@ impl XmlWritable for Failure {
9393

9494
writer.write(e)?;
9595

96-
writer.write(XmlEvent::CData(self.value.as_str()))?;
96+
let msg = self.value.as_str();
97+
if contains_disallowed_xml_chars(msg) || msg.contains("]]>") {
98+
// CDATA can't have escapes inside so here we use normal character data and
99+
// let the library escape
100+
writer.write(XmlEvent::Characters(msg))?;
101+
} else {
102+
// we should just be able to use a raw CData here without bothering to escape
103+
// which is easier to inspect
104+
writer.write(XmlEvent::CData(msg))?;
105+
}
97106
writer.write(XmlEvent::end_element())
98107
}
99108
}
100109

110+
fn contains_disallowed_xml_chars(input: &str) -> bool {
111+
input.chars().any(|c| {
112+
let u = c as u32;
113+
// Convert character to its Unicode code point
114+
// Check for disallowed characters:
115+
// - Control characters except tab (U+0009), line feed (U+000A), and carriage return (U+000D)
116+
// - Null character (U+0000)
117+
// - Characters in the range U+007F to U+009F
118+
(u <= 0x001F && u != 0x0009 && u != 0x000A && u != 0x000D) || (0x007F..=0x009F).contains(&u)
119+
})
120+
}
121+
101122
#[cfg(test)]
102123
mod tests {
103124

@@ -119,6 +140,63 @@ mod tests {
119140
);
120141
}
121142

143+
#[test]
144+
fn test_failure_with_control_serialization() {
145+
let f = Failure {
146+
message: "Failed to build".to_string(),
147+
tpe_name: "BuildFailure".to_string(),
148+
value: "System failed to build\u{0000}".to_string(),
149+
};
150+
151+
assert_eq!(
152+
xml_writable_to_string(&f),
153+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><failure message=\"Failed to build\" type=\"BuildFailure\">System failed to build\0</failure>".to_string()
154+
);
155+
156+
let f1 = Failure {
157+
message: "Failed to build".to_string(),
158+
tpe_name: "BuildFailure".to_string(),
159+
value: "System failed to build]]>".to_string(),
160+
};
161+
162+
assert_eq!(
163+
xml_writable_to_string(&f1),
164+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><failure message=\"Failed to build\" type=\"BuildFailure\">System failed to build]]></failure>".to_string()
165+
);
166+
167+
let f2 = Failure {
168+
message: "Failed to build".to_string(),
169+
tpe_name: "BuildFailure".to_string(),
170+
value: "System failed to build <sometag>".to_string(),
171+
};
172+
173+
assert_eq!(
174+
xml_writable_to_string(&f2),
175+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><failure message=\"Failed to build\" type=\"BuildFailure\"><![CDATA[System failed to build <sometag>]]></failure>".to_string()
176+
);
177+
178+
let f3 = Failure {
179+
message: "Failed to build".to_string(),
180+
tpe_name: "BuildFailure".to_string(),
181+
value: "System failed to build <sometag> and ]]>".to_string(),
182+
};
183+
184+
assert_eq!(
185+
xml_writable_to_string(&f3),
186+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><failure message=\"Failed to build\" type=\"BuildFailure\">System failed to build &lt;sometag> and ]]></failure>".to_string()
187+
);
188+
let f4 = Failure {
189+
message: "Failed to build".to_string(),
190+
tpe_name: "BuildFailure".to_string(),
191+
value: "System failed to build \u{009F}".to_string(),
192+
};
193+
194+
assert_eq!(
195+
xml_writable_to_string(&f4),
196+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><failure message=\"Failed to build\" type=\"BuildFailure\">System failed to build \u{9F}</failure>".to_string()
197+
);
198+
}
199+
122200
#[test]
123201
fn test_testsuites_serialization() {
124202
let f = Failure {

0 commit comments

Comments
 (0)