From e3d80f59e29eaea8defae0fa7493da5bbfbef21c Mon Sep 17 00:00:00 2001 From: Kanishk Sachan Date: Fri, 5 Jun 2026 01:25:22 +0100 Subject: [PATCH] fix: reject multiple patterns when -P/--perl-regexp is used GNU grep's PCRE backend supports only a single pattern. Supplying multiple patterns via repeated -e flags, or a pattern string that contains a literal newline, must exit 2 with the message: the -P option only supports a single pattern Add the validation immediately after patterns are collected, before regex-mode selection. Add a test covering: - two separate -e flags with -P - a newline-embedded pattern string with -P - single -e with -P still works normally Closes #34 --- src/lib.rs | 8 ++++++++ tests/test_grep.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0f2b63a..af06840 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,6 +255,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { )); } + // GNU grep's PCRE backend (-P) supports only a single pattern. + if perl_regexp && patterns.len() > 1 { + return Err(USimpleError::new( + 2, + "the -P option only supports a single pattern".to_string(), + )); + } + // Decoded options into enums let regex_mode = if fixed_strings { RegexMode::Fixed diff --git a/tests/test_grep.rs b/tests/test_grep.rs index d061918..e9665ee 100644 --- a/tests/test_grep.rs +++ b/tests/test_grep.rs @@ -170,6 +170,34 @@ fn pcre_features() { .stdout_only("42\n7\n"); } +#[test] +fn perl_regexp_rejects_multiple_patterns() { + // GNU grep's PCRE backend (-P) only supports a single pattern. + // Multiple -e patterns must produce exit 2 and the canonical error message. + // See: https://github.com/uutils/grep/issues/34 + + // Two separate -e flags. + let (_s, mut c) = ucmd(); + c.args(&["-P", "-e", "foo", "-e", "bar"]) + .pipe_in("foo\nbar\n") + .fails_with_code(2) + .stderr_contains("the -P option only supports a single pattern"); + + // A newline inside the pattern string is split into multiple patterns. + let (_s, mut c) = ucmd(); + c.args(&["-P", "-e", "foo\nbar"]) + .pipe_in("foo\nbar\n") + .fails_with_code(2) + .stderr_contains("the -P option only supports a single pattern"); + + // A single pattern with -P must still work normally. + let (_s, mut c) = ucmd(); + c.args(&["-P", "-e", r"\d+"]) + .pipe_in("abc\n42\n") + .succeeds() + .stdout_only("42\n"); +} + #[test] fn posix_character_classes() { let (_s, mut c) = ucmd();