From 0fe5f39b74f338177853b2ba960e85eb10ce944c Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 10 Jan 2024 10:46:03 +0100 Subject: [PATCH 01/13] Bump console from 0.15.7 to 0.15.8 --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9190d1be352..6f83430b68d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,15 +320,15 @@ checksum = "120133d4db2ec47efe2e26502ee984747630c67f51974fca0b6c1340cf2368d3" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] From d29adfcb095b6dc28d0b21574ff4df69f6e39d97 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 10 Jan 2024 10:47:20 +0100 Subject: [PATCH 02/13] Bump mio from 0.8.6 to 0.8.10 --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f83430b68d..0e4a271dfe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1293,14 +1293,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] From 4754e071d40c27d91d42855753f86f507abb294d Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 10 Jan 2024 10:48:50 +0100 Subject: [PATCH 03/13] deny.toml: update comment for windows-sys --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index df970c2c6e8..986c2b26970 100644 --- a/deny.toml +++ b/deny.toml @@ -62,7 +62,7 @@ skip = [ { name = "linux-raw-sys", version = "0.3.8" }, # terminal_size { name = "rustix", version = "0.37.26" }, - # various crates + # notify { name = "windows-sys", version = "0.45.0" }, # various crates { name = "windows-sys", version = "0.48.0" }, From e948d2e8e5e5403dc8afcb505ad86f98a7b159f3 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 10 Jan 2024 15:14:12 +0100 Subject: [PATCH 04/13] ci: install mingw-w64-x86_64-gcc for windows-gnu --- .github/workflows/CICD.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index ea369e4ef6f..89022bbef35 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -615,6 +615,8 @@ jobs: arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; aarch64-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; *-redox*) sudo apt-get -y update ; sudo apt-get -y install fuse3 libfuse-dev ;; + # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368 + x86_64-pc-windows-gnu) C:/msys64/usr/bin/pacman.exe -Syu --needed mingw-w64-x86_64-gcc --noconfirm ; echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH ;; esac case '${{ matrix.job.os }}' in macos-latest) brew install coreutils ;; # needed for testing @@ -984,6 +986,10 @@ jobs: echo "foo" > /home/runner/.plan ;; esac + case '${{ matrix.job.os }}' in + # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368 + windows-latest) C:/msys64/usr/bin/pacman.exe -Syu --needed mingw-w64-x86_64-gcc --noconfirm ; echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH ;; + esac - name: Initialize toolchain-dependent workflow variables id: dep_vars shell: bash From 7d32e49fb907f3fd9e9a1bbb1e152a4083d1b9a5 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 10 Jan 2024 18:19:56 +0100 Subject: [PATCH 05/13] printf: %c prints the first byte of its argument --- src/uucore/src/lib/features/format/argument.rs | 2 +- tests/by-util/test_printf.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/format/argument.rs b/src/uucore/src/lib/features/format/argument.rs index 92d6c1603fb..ef81fc3533b 100644 --- a/src/uucore/src/lib/features/format/argument.rs +++ b/src/uucore/src/lib/features/format/argument.rs @@ -45,7 +45,7 @@ impl<'a, T: Iterator> ArgumentIter<'a> for T { }; match next { FormatArgument::Char(c) => *c, - FormatArgument::Unparsed(s) => s.chars().next().unwrap_or('\0'), + FormatArgument::Unparsed(s) => s.bytes().next().map_or('\0', char::from), _ => '\0', } } diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 48fc1e6ace2..c3527710669 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -639,3 +639,8 @@ fn partial_char() { "printf: warning: bc: character(s) following character constant have been ignored\n", ); } + +#[test] +fn char_as_byte() { + new_ucmd!().args(&["%c", "🙃"]).succeeds().stdout_only("ð"); +} From 47e908bc6cbd40c9a937ed8f78dc384c83ff2b42 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 10 Jan 2024 18:59:33 +0100 Subject: [PATCH 06/13] printf: output of double-quote should not be escaped This is obtained by escaping the sequence `\"` as `"`. --- src/uucore/src/lib/features/format/escape.rs | 1 + tests/by-util/test_printf.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/uucore/src/lib/features/format/escape.rs b/src/uucore/src/lib/features/format/escape.rs index d20da3e7e38..9420507f3e3 100644 --- a/src/uucore/src/lib/features/format/escape.rs +++ b/src/uucore/src/lib/features/format/escape.rs @@ -108,6 +108,7 @@ pub fn parse_escape_code(rest: &mut &[u8]) -> EscapedChar { *rest = new_rest; match c { b'\\' => EscapedChar::Byte(b'\\'), + b'"' => EscapedChar::Byte(b'"'), b'a' => EscapedChar::Byte(b'\x07'), b'b' => EscapedChar::Byte(b'\x08'), b'c' => EscapedChar::End, diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 48fc1e6ace2..a288d7c0842 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -36,6 +36,11 @@ fn escaped_slash() { .stdout_only("hello\\ world"); } +#[test] +fn unescaped_double_quote() { + new_ucmd!().args(&["\\\""]).succeeds().stdout_only("\""); +} + #[test] fn escaped_hex() { new_ucmd!().args(&["\\x41"]).succeeds().stdout_only("A"); From 2aa8a3502fd049a3ce13164aa8b289daf2940e04 Mon Sep 17 00:00:00 2001 From: Sudhakar Verma Date: Fri, 12 Jan 2024 16:08:47 +0530 Subject: [PATCH 07/13] printf : no infinite loop --- src/uu/printf/src/printf.rs | 10 +++++++++- tests/by-util/test_printf.rs | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/uu/printf/src/printf.rs b/src/uu/printf/src/printf.rs index ad42e38941f..64a3a35a7af 100644 --- a/src/uu/printf/src/printf.rs +++ b/src/uu/printf/src/printf.rs @@ -11,7 +11,7 @@ use std::ops::ControlFlow; use clap::{crate_version, Arg, ArgAction, Command}; use uucore::error::{UResult, UUsageError}; -use uucore::format::{parse_spec_and_escape, FormatArgument}; +use uucore::format::{parse_spec_and_escape, FormatArgument, FormatItem}; use uucore::{format_usage, help_about, help_section, help_usage}; const VERSION: &str = "version"; @@ -46,6 +46,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }; } + // See #5815 - We don't need to iter on args if no format string seen + let format_seen = parse_spec_and_escape(format_string.as_ref()) + .into_iter() + .any(|r| matches!(r, Ok(FormatItem::Spec(_)))); + if !format_seen { + return Ok(()); + } + while args.peek().is_some() { for item in parse_spec_and_escape(format_string.as_ref()) { match item?.write(stdout(), &mut args)? { diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 4f2e1dc10e6..411285a0cd2 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -649,3 +649,8 @@ fn partial_char() { fn char_as_byte() { new_ucmd!().args(&["%c", "🙃"]).succeeds().stdout_only("ð"); } + +#[test] +fn no_infinite_loop() { + new_ucmd!().args(&["a", "b"]).succeeds().stdout_only("a"); +} From 4e5a65ee41372ca9bd35501e251b1b7bf799665e Mon Sep 17 00:00:00 2001 From: Sudhakar Verma Date: Fri, 12 Jan 2024 16:23:38 +0530 Subject: [PATCH 08/13] printf: fix clippy warnings --- src/uu/printf/src/printf.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/uu/printf/src/printf.rs b/src/uu/printf/src/printf.rs index 64a3a35a7af..b0988f7b45f 100644 --- a/src/uu/printf/src/printf.rs +++ b/src/uu/printf/src/printf.rs @@ -47,9 +47,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } // See #5815 - We don't need to iter on args if no format string seen - let format_seen = parse_spec_and_escape(format_string.as_ref()) - .into_iter() - .any(|r| matches!(r, Ok(FormatItem::Spec(_)))); + let format_seen = + parse_spec_and_escape(format_string.as_ref()).any(|r| matches!(r, Ok(FormatItem::Spec(_)))); if !format_seen { return Ok(()); } From cd4568f5d9862ab28dda351c7692c0bd95dcdda7 Mon Sep 17 00:00:00 2001 From: Sudhakar Verma Date: Fri, 12 Jan 2024 17:12:30 +0530 Subject: [PATCH 09/13] printf: simplify loop --- src/uu/printf/src/printf.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/uu/printf/src/printf.rs b/src/uu/printf/src/printf.rs index b0988f7b45f..c98bb59a1e4 100644 --- a/src/uu/printf/src/printf.rs +++ b/src/uu/printf/src/printf.rs @@ -38,17 +38,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { None => vec![], }; + let mut format_seen = false; let mut args = values.iter().peekable(); for item in parse_spec_and_escape(format_string.as_ref()) { + if let Ok(FormatItem::Spec(_)) = item { + format_seen = true; + } match item?.write(stdout(), &mut args)? { ControlFlow::Continue(()) => {} ControlFlow::Break(()) => return Ok(()), }; } - // See #5815 - We don't need to iter on args if no format string seen - let format_seen = - parse_spec_and_escape(format_string.as_ref()).any(|r| matches!(r, Ok(FormatItem::Spec(_)))); + // Without format specs in the string, the iter would not consume any args, + // leading to an infinite loop. Thus, we exit early. if !format_seen { return Ok(()); } From 19e1f26e3d9aa7a4749ed4c21293d111afc41846 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 13 Jan 2024 14:01:38 +0100 Subject: [PATCH 10/13] fuzz: with pipe, also capture stderr --- fuzz/fuzz_targets/fuzz_common.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fuzz/fuzz_targets/fuzz_common.rs b/fuzz/fuzz_targets/fuzz_common.rs index f0de0b6052f..e8cac8d4048 100644 --- a/fuzz/fuzz_targets/fuzz_common.rs +++ b/fuzz/fuzz_targets/fuzz_common.rs @@ -232,7 +232,10 @@ pub fn run_gnu_cmd( let output = if let Some(input_str) = pipe_input { // We have an pipe input - command.stdin(Stdio::piped()).stdout(Stdio::piped()); + command + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); let mut child = command.spawn().expect("Failed to execute command"); let child_stdin = child.stdin.as_mut().unwrap(); From 563df4b79d972c27551055e5bf1eb4af02f6955f Mon Sep 17 00:00:00 2001 From: Atomei Alexandru <118962363+Ato2207@users.noreply.github.com> Date: Sat, 13 Jan 2024 15:43:36 +0200 Subject: [PATCH 11/13] Made cksum return an error if used on a directory. (#5822) * Made cksum to return an error if it is used on a directory regardless of the algorithm * Added one more test for cksum on folders and deleted an old one that expected it to succeed instead of fail * Made cksum work on more than one item if it fails and added a test for this case --- src/uu/cksum/src/cksum.rs | 19 ++++++------- tests/by-util/test_cksum.rs | 55 +++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index a3e6dfd9e1a..458177e8a7c 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -15,8 +15,8 @@ use std::io::{self, stdin, stdout, BufReader, Read, Write}; use std::iter; use std::path::Path; use uucore::{ - error::{FromIo, UError, UResult}, - format_usage, help_about, help_section, help_usage, + error::{FromIo, UError, UResult, USimpleError}, + format_usage, help_about, help_section, help_usage, show, sum::{ div_ceil, Blake2b, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Sm3, BSD, CRC, SYSV, @@ -174,7 +174,13 @@ where }); let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits) .map_err_context(|| "failed to read input".to_string())?; - + if filename.is_dir() { + show!(USimpleError::new( + 1, + format!("{}: Is a directory", filename.display()) + )); + continue; + } if options.raw { let bytes = match options.algo_name { ALGORITHM_OPTIONS_CRC => sum.parse::().unwrap().to_be_bytes().to_vec(), @@ -214,13 +220,6 @@ where (ALGORITHM_OPTIONS_CRC, true) => println!("{sum} {sz}"), (ALGORITHM_OPTIONS_CRC, false) => println!("{sum} {sz} {}", filename.display()), (ALGORITHM_OPTIONS_BLAKE2B, _) if !options.untagged => { - if filename.is_dir() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("{}: Is a directory", filename.display()), - ) - .into()); - } if let Some(length) = options.length { // Multiply by 8 here, as we want to print the length in bits. println!("BLAKE2b-{} ({}) = {sum}", length * 8, filename.display()); diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index b3db0bf0a02..80cfc749931 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -80,18 +80,6 @@ fn test_nonexisting_file() { .stderr_contains(format!("cksum: {file_name}: No such file or directory")); } -#[test] -fn test_folder() { - let (at, mut ucmd) = at_and_ucmd!(); - - let folder_name = "a_folder"; - at.mkdir(folder_name); - - ucmd.arg(folder_name) - .succeeds() - .stdout_only(format!("4294967295 0 {folder_name}\n")); -} - // Make sure crc is correct for files larger than 32 bytes // but <128 bytes (1 fold pclmul) // spell-checker:disable-line #[test] @@ -312,15 +300,52 @@ fn test_raw_multiple_files() { } #[test] -fn test_blake2b_fail_on_directory() { +fn test_fail_on_folder() { let (at, mut ucmd) = at_and_ucmd!(); let folder_name = "a_folder"; at.mkdir(folder_name); - ucmd.arg("--algorithm=blake2b") - .arg(folder_name) + ucmd.arg(folder_name) .fails() .no_stdout() .stderr_contains(format!("cksum: {folder_name}: Is a directory")); } + +#[test] +fn test_all_algorithms_fail_on_folder() { + let scene = TestScenario::new(util_name!()); + + let at = &scene.fixtures; + + let folder_name = "a_folder"; + at.mkdir(folder_name); + + for algo in ALGOS { + scene + .ucmd() + .arg(format!("--algorithm={algo}")) + .arg(folder_name) + .fails() + .no_stdout() + .stderr_contains(format!("cksum: {folder_name}: Is a directory")); + } +} + +#[test] +fn test_folder_and_file() { + let scene = TestScenario::new(util_name!()); + + let at = &scene.fixtures; + + let folder_name = "a_folder"; + at.mkdir(folder_name); + + scene + .ucmd() + .arg(folder_name) + .arg("lorem_ipsum.txt") + .fails() + .stderr_contains(format!("cksum: {folder_name}: Is a directory")) + .stdout_is_fixture("crc_single_file.expected"); +} From c63b5b2a5d919ffd5b98741035c64c9ab83cf508 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 13 Jan 2024 13:57:26 +0000 Subject: [PATCH 12/13] chore(deps): update rust crate tempfile to 3.9.0 --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e4a271dfe0..bf83d9accd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2045,15 +2045,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.4.0", "rustix 0.38.28", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f45d0b2f4e9..a01fcdd2d39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -319,7 +319,7 @@ self_cell = "1.0.3" selinux = "0.4" signal-hook = "0.3.17" smallvec = { version = "1.11", features = ["union"] } -tempfile = "3.8.1" +tempfile = "3.9.0" uutils_term_grid = "0.3" terminal_size = "0.3.0" textwrap = { version = "0.16.0", features = ["terminal_size"] } From bc51b8d2169896ab5c513edb441a6d041a0449f6 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 13 Jan 2024 15:09:08 +0100 Subject: [PATCH 13/13] cut: allow the same option to be passed multiple times --- src/uu/cut/src/cut.rs | 1 + tests/by-util/test_cut.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/uu/cut/src/cut.rs b/src/uu/cut/src/cut.rs index 0d5f79b35c1..2a3196d002e 100644 --- a/src/uu/cut/src/cut.rs +++ b/src/uu/cut/src/cut.rs @@ -510,6 +510,7 @@ pub fn uu_app() -> Command { .about(ABOUT) .after_help(AFTER_HELP) .infer_long_args(true) + .args_override_self(true) .arg( Arg::new(options::BYTES) .short('b') diff --git a/tests/by-util/test_cut.rs b/tests/by-util/test_cut.rs index 112dc0fd3e5..57e6666d304 100644 --- a/tests/by-util/test_cut.rs +++ b/tests/by-util/test_cut.rs @@ -255,3 +255,13 @@ fn test_equal_as_delimiter3() { .succeeds() .stdout_only_bytes("abZcd\n"); } + +#[test] +fn test_multiple() { + let result = new_ucmd!() + .args(&["-f2", "-d:", "-d="]) + .pipe_in("a=b\n") + .succeeds(); + assert_eq!(result.stdout_str(), "b\n"); + assert_eq!(result.stderr_str(), ""); +}