From d4ccc5e1d71bf8e031288e595af10d75e4798212 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 22 Jun 2022 09:37:16 +0200 Subject: [PATCH] paste: handle list ending with unescaped backslash --- src/uu/paste/src/paste.rs | 14 +++++++++++--- tests/by-util/test_paste.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/uu/paste/src/paste.rs b/src/uu/paste/src/paste.rs index 682e66a5da9..bd9f0a10f81 100644 --- a/src/uu/paste/src/paste.rs +++ b/src/uu/paste/src/paste.rs @@ -11,7 +11,7 @@ use clap::{crate_version, Arg, Command}; use std::fs::File; use std::io::{stdin, stdout, BufRead, BufReader, Read, Write}; use std::path::Path; -use uucore::error::{FromIo, UResult}; +use uucore::error::{FromIo, UResult, USimpleError}; static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each FILE, separated by TABs, to standard output."; @@ -89,6 +89,16 @@ fn paste(filenames: Vec, serial: bool, delimiters: &str) -> UResult<()> files.push(file); } + if delimiters.ends_with('\\') && !delimiters.ends_with("\\\\") { + return Err(USimpleError::new( + 1, + format!( + "delimiter list ends with an unescaped backslash: {}", + delimiters + ), + )); + } + let delimiters: Vec = unescape(delimiters).chars().collect(); let mut delim_count = 0; let stdout = stdout(); @@ -152,10 +162,8 @@ fn paste(filenames: Vec, serial: bool, delimiters: &str) -> UResult<()> } // Unescape all special characters -// TODO: this will need work to conform to GNU implementation fn unescape(s: &str) -> String { s.replace("\\n", "\n") .replace("\\t", "\t") .replace("\\\\", "\\") - .replace('\\', "") } diff --git a/tests/by-util/test_paste.rs b/tests/by-util/test_paste.rs index 6d539e45e52..0da730982e2 100644 --- a/tests/by-util/test_paste.rs +++ b/tests/by-util/test_paste.rs @@ -103,6 +103,37 @@ fn test_multi_stdin() { } } +#[test] +fn test_delimiter_list_ending_with_escaped_backslash() { + for d in ["-d", "--delimiters"] { + let (at, mut ucmd) = at_and_ucmd!(); + let mut ins = vec![]; + for (i, _in) in ["a\n", "b\n"].iter().enumerate() { + let file = format!("in{}", i); + at.write(&file, _in); + ins.push(file); + } + ucmd.args(&[d, "\\\\"]) + .args(&ins) + .succeeds() + .stdout_is("a\\b\n"); + } +} + +#[test] +fn test_delimiter_list_ending_with_unescaped_backslash() { + for d in ["-d", "--delimiters"] { + new_ucmd!() + .args(&[d, "\\"]) + .fails() + .stderr_contains("delimiter list ends with an unescaped backslash: \\"); + new_ucmd!() + .args(&[d, "_\\"]) + .fails() + .stderr_contains("delimiter list ends with an unescaped backslash: _\\"); + } +} + #[test] fn test_data() { for example in EXAMPLE_DATA {