diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-25T11·23+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-03T00·47+0000 |
commit | 39b01c302937fe3e91c15758b520c3ecc5379c7b (patch) | |
tree | cff95e288671533056fcea8a62e3fe620b77ef6d /tvix/eval/src/value/string.rs | |
parent | 265393301e2b59659a0a5db15e42bc668d0c7c68 (diff) |
fix(tvix/eval): correctly escape `${` in strings r/4607
Without this escape, it is possible for Nix to produce escaped representations which are not literal Nix values again. This was fixed in upstream Nix in https://github.com/NixOS/nix/pull/4012 (though only for eval, not in the REPL) and the updated test is picked from upstream after that commit. Because we run the C++ Nix tests against our test suite as well, this also bumps our custom Nix 2.3 to a commit that includes the cherry-picked fix from the PR above. Change-Id: I478547ade65f655c606ec46f7143932064192283 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6271 Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/value/string.rs')
-rw-r--r-- | tvix/eval/src/value/string.rs | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs index f352281be36a..51b0f0345457 100644 --- a/tvix/eval/src/value/string.rs +++ b/tvix/eval/src/value/string.rs @@ -90,13 +90,14 @@ impl NixString { } } -fn nix_escape_char(ch: char) -> Option<&'static str> { - match ch { - '\\' => Some("\\\\"), - '"' => Some("\\\""), - '\n' => Some("\\n"), - '\t' => Some("\\t"), - '\r' => Some("\\r"), +fn nix_escape_char(ch: char, next: Option<&char>) -> Option<&'static str> { + match (ch, next) { + ('\\', _) => Some("\\\\"), + ('"', _) => Some("\\\""), + ('\n', _) => Some("\\n"), + ('\t', _) => Some("\\t"), + ('\r', _) => Some("\\r"), + ('$', Some('{')) => Some("\\$"), _ => None, } } @@ -106,14 +107,17 @@ fn nix_escape_char(ch: char) -> Option<&'static str> { // // Note that this does not add the outer pair of surrounding quotes. fn nix_escape_string(input: &str) -> Cow<str> { - for (i, c) in input.chars().enumerate() { - if let Some(esc) = nix_escape_char(c) { + let mut iter = input.chars().enumerate().peekable(); + + while let Some((i, c)) = iter.next() { + if let Some(esc) = nix_escape_char(c, iter.peek().map(|(_, c)| c)) { let mut escaped = String::with_capacity(input.len()); escaped.push_str(&input[..i]); escaped.push_str(esc); - for c in input[i + 1..].chars() { - match nix_escape_char(c) { + let mut inner_iter = input[i + 1..].chars().peekable(); + while let Some(c) = inner_iter.next() { + match nix_escape_char(c, inner_iter.peek()) { Some(esc) => escaped.push_str(esc), None => escaped.push(c), } |