Skip to content

Commit 0113e30

Browse files
authored
mcookie - fix providing /dev/random or /dev/urandom as file leads to infinite loop (#274)
* Update mcookie.rs * edit doc * fmt * fix for unix and non-unix build * add test case * refactor * fmt * fix
1 parent 36b3af0 commit 0113e30

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/uu/mcookie/src/mcookie.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
#[cfg(unix)]
7+
use std::os::unix::fs::FileTypeExt;
68
use std::{fs::File, io::Read};
79

810
use clap::{crate_version, Arg, ArgAction, Command};
@@ -57,7 +59,22 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5759
let mut handle = f.take(*max_bytes);
5860
handle.read_to_end(&mut buffer)?;
5961
} else {
60-
f.read_to_end(&mut buffer)?;
62+
#[cfg(unix)]
63+
{
64+
const DEFAULT_SEED_READ_BYTES: u64 = 1024;
65+
let metadata = f.metadata()?;
66+
67+
if metadata.file_type().is_char_device() {
68+
let mut handle = f.take(DEFAULT_SEED_READ_BYTES);
69+
handle.read_to_end(&mut buffer)?;
70+
} else {
71+
f.read_to_end(&mut buffer)?;
72+
}
73+
}
74+
#[cfg(not(unix))]
75+
{
76+
f.read_to_end(&mut buffer)?;
77+
}
6178
}
6279

6380
if verbose {

tests/by-util/test_mcookie.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,31 @@ fn test_seed_files_and_max_size_raw() {
6464
));
6565
}
6666

67+
#[test]
68+
#[cfg(unix)] // Character devices like /dev/zero are a Unix concept
69+
fn test_char_device_input() {
70+
let res_no_limit = new_ucmd!().arg("-f").arg("/dev/zero").succeeds();
71+
72+
let stdout_no_limit = res_no_limit.no_stderr().stdout_str().trim_end();
73+
assert_eq!(stdout_no_limit.len(), 32);
74+
assert!(stdout_no_limit.chars().all(|c| c.is_ascii_hexdigit()));
75+
76+
let res_verbose = new_ucmd!()
77+
.arg("--verbose")
78+
.arg("-f")
79+
.arg("/dev/zero")
80+
.succeeds();
81+
82+
res_verbose.stderr_contains("Got 1024 bytes from /dev/zero");
83+
res_verbose.stderr_contains("Got 128 bytes from randomness source"); // Ensure internal randomness is still added
84+
85+
let stdout_verbose = res_verbose.stdout_str().trim_end();
86+
assert_eq!(stdout_verbose.len(), 32);
87+
assert!(stdout_verbose.chars().all(|c| c.is_ascii_hexdigit()));
88+
89+
assert_ne!(stdout_no_limit, stdout_verbose);
90+
}
91+
6792
#[test]
6893
fn test_seed_files_and_max_size_human_readable() {
6994
let mut file = NamedTempFile::new().unwrap();

0 commit comments

Comments
 (0)