From c7b43b3abfb24af324100667932b168f0ef566e3 Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Fri, 23 Jun 2023 16:29:42 +0200 Subject: [PATCH] Truncate builtin arguments on NUL This restores the status quo where builtins are like external commands in that they can't see anything after a 0x00, because that's the c-style string terminator. --- fish-rust/src/builtins/shared.rs | 11 ++++++++++- tests/checks/nuls.fish | 7 ++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/fish-rust/src/builtins/shared.rs b/fish-rust/src/builtins/shared.rs index 7052716ca..983a3b523 100644 --- a/fish-rust/src/builtins/shared.rs +++ b/fish-rust/src/builtins/shared.rs @@ -153,7 +153,16 @@ fn rust_run_builtin( status_code: &mut i32, ) -> bool { let storage: Vec = cpp_args.from_ffi(); - let mut args: Vec<&wstr> = storage.iter().map(|s| s.as_utfstr()).collect(); + let mut args: Vec<&wstr> = storage + .iter() + .map(|s| match s.chars().position(|c| c == '\0') { + // We truncate on NUL for backwards-compatibility reasons. + // This used to be passed as c-strings (`wchar_t *`), + // and so we act like it for now. + Some(pos) => &s[..pos], + None => &s[..], + }) + .collect(); let streams = &mut io_streams_t::new(streams); match run_builtin(parser.unpin(), streams, args.as_mut_slice(), builtin) { diff --git a/tests/checks/nuls.fish b/tests/checks/nuls.fish index 76a0ded71..fa2194787 100644 --- a/tests/checks/nuls.fish +++ b/tests/checks/nuls.fish @@ -1,7 +1,12 @@ #RUN: %fish %s # NUL-handling +# This one actually prints a NUL +echo (printf '%s\x00' foo bar | string escape) +# CHECK: foo\x00bar\x00 +# This one is truncated echo foo\x00bar | string escape -# CHECK: foo\x00bar +# CHECK: foo +# This one is just escaped echo foo\\x00bar | string escape # CHECK: foo\\x00bar