fix(tvix/eval): correctly escape ${ in strings
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
This commit is contained in:
parent
265393301e
commit
39b01c3029
4 changed files with 19 additions and 14 deletions
|
|
@ -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),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue