Skip to content

Commit 73b5699

Browse files
authored
Merge pull request #174 from github/escape_file_keys
Escape keys for files and folders
2 parents 1a94fb4 + c37f390 commit 73b5699

1 file changed

Lines changed: 51 additions & 2 deletions

File tree

extractor/src/extractor.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use node_types::{EntryKind, Field, NodeTypeMap, Storage, TypeName};
2+
use std::borrow::Cow;
23
use std::collections::BTreeMap as Map;
34
use std::collections::BTreeSet as Set;
45
use std::fmt;
@@ -190,6 +191,41 @@ pub fn extract(
190191
Ok(Program(visitor.trap_writer.trap_output))
191192
}
192193

194+
/// Escapes a string for use in a TRAP key, by replacing special characters with
195+
/// HTML entities.
196+
fn escape_key<'a, S: Into<Cow<'a, str>>>(key: S) -> Cow<'a, str> {
197+
fn needs_escaping(c: char) -> bool {
198+
match c {
199+
'&' => true,
200+
'{' => true,
201+
'}' => true,
202+
'"' => true,
203+
'@' => true,
204+
'#' => true,
205+
_ => false,
206+
}
207+
}
208+
209+
let key = key.into();
210+
if key.contains(needs_escaping) {
211+
let mut escaped = String::with_capacity(2 * key.len());
212+
for c in key.chars() {
213+
match c {
214+
'&' => escaped.push_str("&amp;"),
215+
'{' => escaped.push_str("&lbrace;"),
216+
'}' => escaped.push_str("&rbrace;"),
217+
'"' => escaped.push_str("&quot;"),
218+
'@' => escaped.push_str("&commat;"),
219+
'#' => escaped.push_str("&num;"),
220+
_ => escaped.push(c),
221+
}
222+
}
223+
Cow::Owned(escaped)
224+
} else {
225+
key
226+
}
227+
}
228+
193229
/// Normalizes the path according the common CodeQL specification. Assumes that
194230
/// `path` has already been canonicalized using `std::fs::canonicalize`.
195231
fn normalize_path(path: &Path) -> String {
@@ -230,11 +266,11 @@ fn normalize_path(path: &Path) -> String {
230266
}
231267

232268
fn full_id_for_file(path: &Path) -> String {
233-
format!("{};sourcefile", normalize_path(path))
269+
format!("{};sourcefile", escape_key(&normalize_path(path)))
234270
}
235271

236272
fn full_id_for_folder(path: &Path) -> String {
237-
format!("{};folder", normalize_path(path))
273+
format!("{};folder", escape_key(&normalize_path(path)))
238274
}
239275

240276
struct ChildNode {
@@ -731,3 +767,16 @@ fn limit_string_test() {
731767
assert_eq!("hi ☹", limit_string(&"hi ☹☹".to_owned(), 6));
732768
assert_eq!("hi ", limit_string(&"hi ☹☹".to_owned(), 5));
733769
}
770+
771+
#[test]
772+
fn escape_key_test() {
773+
assert_eq!("foo!", escape_key("foo!"));
774+
assert_eq!("foo&lbrace;&rbrace;", escape_key("foo{}"));
775+
assert_eq!("&lbrace;&rbrace;", escape_key("{}"));
776+
assert_eq!("", escape_key(""));
777+
assert_eq!("/path/to/foo.rb", escape_key("/path/to/foo.rb"));
778+
assert_eq!(
779+
"/path/to/foo&amp;&lbrace;&rbrace;&quot;&commat;&num;.rb",
780+
escape_key("/path/to/foo&{}\"@#.rb")
781+
);
782+
}

0 commit comments

Comments
 (0)