paste: handle list ending with unescaped backslash

This commit is contained in:
Daniel Hofstetter 2022-06-22 09:37:16 +02:00
parent b33986de86
commit c254900db9
2 changed files with 42 additions and 3 deletions

View file

@ -12,7 +12,7 @@ use std::fmt::Display;
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};
use uucore::{format_usage, help_about, help_usage};
const ABOUT: &str = help_about!("paste.md");
@ -129,6 +129,16 @@ fn paste(
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<char> = unescape(delimiters).chars().collect();
let mut delim_count = 0;
let mut delim_length = 1;
@ -222,10 +232,8 @@ fn paste(
}
// 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('\\', "")
}

View file

@ -156,6 +156,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 {