Skip to content

Commit

Permalink
Merged PR 5078953: Work around Sexp crate issue with handling quotes
Browse files Browse the repository at this point in the history
Work around Sexp crate issue with handling quotes

The sexp crate has a bug around handling quoted strings that makes it
impossible to differentiate between a quoted and an unquoted string.

cgaebel/sexp#2

The short version is that quotes are added on output strings based on
heuristics that include the presence of quotes in the original string,
so giving a quoted string to sexp yields a doubly quoted string, and
giving an unquoted string yields an unquoted string, resulting in no
way to generate a Sexp structure that will output a quoted string with
the Display trait, unless that string meets one of the following
criteria:

1. Contains a quote
2. Contains whitespace
3. Is a number

For CIL filecon statements, we need to include quoted strings, which
meet none of these criteria.

The sexp crate project appears to be abandoned, so a PR will not be
fruitful.  Rather than higher level of effort approaches such as forking
the project or migrating to a different sexp crate, this commit simply
works around the issue by adding a simple new display function that does
no quote special handling.  This requires us to manage quotes
internally, but that's really what we want anyways."
dburgener committed Sep 16, 2021
1 parent 3343b77 commit e030518
Showing 2 changed files with 50 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ pub mod error;
mod functions;
mod internal_rep;
mod obj_class;
mod sexp_internal;

use error::{HLLErrorItem, HLLErrors};
use lalrpop_util::ParseError;
@@ -48,7 +49,7 @@ fn parse_policy<'a>(

fn generate_cil(v: Vec<sexp::Sexp>) -> String {
v.iter()
.map(|s| s.to_string())
.map(|s| sexp_internal::display_cil(s))
.collect::<Vec<String>>()
.join("\n")
}
48 changes: 48 additions & 0 deletions src/sexp_internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use sexp::*;

// the sexp crate doesn't treat foo and "foo" as separate strings, which we need
// The quoting behavior in the sexp crate automatically handles quoting in situations where the
// string contains a quote or a space, so we need to avoid those in order for this to work, but 1.
// We want to avoid those anyways and 2. The default behavior makes actually inserting a quoted
// string that wouldn't be automatically quoted impossible.
// https://github.com/cgaebel/sexp/issues/2
pub fn display_cil(expr: &sexp::Sexp) -> String {
match expr {
Sexp::List(l) => {
format!(
"({})",
l.iter()
.map(|s| display_cil(s))
.collect::<Vec<String>>()
.join(" ")
)
}
Sexp::Atom(a) => match a {
Atom::S(s) => s.to_string(),
_ => a.to_string(),
},
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_display_cil() {
let cil = parse("(foo)").unwrap();
assert_eq!(display_cil(&cil), cil.to_string());

let cil = parse("(foo (bar baz))").unwrap();
assert_eq!(display_cil(&cil), cil.to_string());

let cil = parse("foo").unwrap();
assert_eq!(display_cil(&cil), cil.to_string());

let cil = parse("32").unwrap();
assert_eq!(display_cil(&cil), cil.to_string());

let cil = atom_s("\"/bin\"");
assert_eq!(display_cil(&cil), "\"/bin\"".to_string());
}
}

0 comments on commit e030518

Please sign in to comment.