Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = expand_num_shorthand(args);
let matches = uucore::clap_localization::handle_clap_result_with_exit_code(uu_app(), args, 2)?;

let grep_color = std::env::var("GREP_COLOR").unwrap_or_default();
// GNU grep ignores a malformed legacy match color without a warning.
let grep_color = std::env::var("GREP_COLOR")
.ok()
.filter(|value| is_color_value(value))
.unwrap_or_default();
let grep_colors = std::env::var("GREP_COLORS").unwrap_or_default();

let patterns_or_files: Vec<_> = matches
Expand Down Expand Up @@ -996,6 +1000,10 @@ impl GlobSet {
}
}

fn is_color_value(value: &str) -> bool {
value.bytes().all(|b| b.is_ascii_digit() || b == b';')
}

impl<'a> ColorConfig<'a> {
fn from_env(grep_color: &'a str, grep_colors: &'a str) -> Self {
let mut config = Self {
Expand All @@ -1016,8 +1024,13 @@ impl<'a> ColorConfig<'a> {
config.matched_context = grep_color;
}

// GNU grep retains prior settings and stops at an empty assignment key
// or invalid value.
for item in grep_colors.split(':') {
if let Some((key, value)) = item.split_once('=') {
if key.is_empty() || !is_color_value(value) {
break;
}
match key {
// `mt` sets matched text in any line; equivalent to ms + mc.
"mt" => {
Expand Down
21 changes: 21 additions & 0 deletions tests/test_grep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,16 @@ fn grep_color_env_no_warning_without_color() {
.stdout_only("foo\n");
}

#[test]
fn grep_color_env_malformed_value_is_ignored() {
let (_s, mut c) = ucmd();
c.env("GREP_COLOR", "4x2")
.args(&["--color=always", "foo"])
.pipe_in("foo\n")
.succeeds()
.stdout_only("\x1b[01;31m\x1b[Kfoo\x1b[m\x1b[K\n");
}

#[test]
fn color_line_number_uses_green() {
let (_s, mut c) = ucmd();
Expand Down Expand Up @@ -1387,6 +1397,17 @@ fn grep_colors_env_overrides() {
.stdout_contains("\x1b[34m\x1b[K1\x1b[m\x1b[K");
}

#[test]
fn grep_colors_env_stops_at_malformed_value() {
let (_s, mut c) = ucmd();
c.env("GREP_COLORS", "fn=4x2:ms=33")
.args(&["--color=always", "-H", "foo"])
.pipe_in("foo\n")
.succeeds()
.stdout_contains("\x1b[35m\x1b[K(standard input)\x1b[m\x1b[K")
.stdout_contains("\x1b[01;31m\x1b[Kfoo\x1b[m\x1b[K");
}

#[test]
fn legacy_grep_color_env() {
// uutests clears the environment by default,
Expand Down
Loading