diff --git a/src/uu/ptx/locales/en-US.ftl b/src/uu/ptx/locales/en-US.ftl index 402b2702b47..c7362122447 100644 --- a/src/uu/ptx/locales/en-US.ftl +++ b/src/uu/ptx/locales/en-US.ftl @@ -28,3 +28,4 @@ ptx-error-dumb-format = There is no dumb format with GNU extensions disabled ptx-error-not-implemented = { $feature } not implemented yet ptx-error-write-failed = write failed ptx-error-extra-operand = extra operand { $operand } +ptx-invalid-regular-expression = invalid regular expression: { $error } diff --git a/src/uu/ptx/src/ptx.rs b/src/uu/ptx/src/ptx.rs index 28d19cdbdfd..0a96dc6c6f8 100644 --- a/src/uu/ptx/src/ptx.rs +++ b/src/uu/ptx/src/ptx.rs @@ -19,7 +19,7 @@ use clap::{Arg, ArgAction, Command}; use regex::Regex; use thiserror::Error; use uucore::display::Quotable; -use uucore::error::{FromIo, UError, UResult, UUsageError}; +use uucore::error::{FromIo, UError, UResult, USimpleError, UUsageError}; use uucore::format_usage; use uucore::translate; @@ -301,9 +301,15 @@ fn read_input(input_files: &[OsString]) -> std::io::Result { } /// Go through every lines in the input files and record each match occurrence as a `WordRef`. -fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) -> BTreeSet { - let reg = Regex::new(&filter.word_regex).unwrap(); - let ref_reg = Regex::new(&config.context_regex).unwrap(); +fn create_word_set( + config: &Config, + filter: &WordFilter, + file_map: &FileMap, +) -> UResult> { + let reg = Regex::new(&filter.word_regex) + .map_err(|e| USimpleError::new(1, translate!("ptx-invalid-regular-expression", "error" => e)))?; + let ref_reg = Regex::new(&config.context_regex) + .map_err(|e| USimpleError::new(1, translate!("ptx-invalid-regular-expression", "error" => e)))?; let mut word_set: BTreeSet = BTreeSet::new(); for (file, lines) in file_map { let mut count: usize = 0; @@ -342,7 +348,7 @@ fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) -> count += 1; } } - word_set + Ok(word_set) } fn get_reference(config: &Config, word_ref: &WordRef, line: &str, context_reg: &Regex) -> String { @@ -884,7 +890,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let word_filter = WordFilter::new(&matches, &config)?; let file_map = read_input(&input_files).map_err_context(String::new)?; - let word_set = create_word_set(&config, &word_filter, &file_map); + let word_set = create_word_set(&config, &word_filter, &file_map)?; write_traditional_output(&mut config, &file_map, &word_set, &output_file) } diff --git a/tests/by-util/test_ptx.rs b/tests/by-util/test_ptx.rs index c9ecb5c22e2..7859f9bcc79 100644 --- a/tests/by-util/test_ptx.rs +++ b/tests/by-util/test_ptx.rs @@ -301,3 +301,19 @@ fn test_unicode_truncation_alignment() { .succeeds() .stdout_only(" / bar\n föö/\n"); } + +#[test] +fn test_invalid_regex_word_trailing_backslash() { + new_ucmd!() + .args(&["-W", "bar\\"]) + .fails_with_code(1) + .stderr_contains("ptx: invalid regular expression"); +} + +#[test] +fn test_invalid_regex_word_unclosed_group() { + new_ucmd!() + .args(&["-W", "(wrong"]) + .fails_with_code(1) + .stderr_contains("ptx: invalid regular expression"); +} \ No newline at end of file