From 8ee29749e634d2be44eb3fd688da5f6504757b7f Mon Sep 17 00:00:00 2001 From: Sichen Date: Thu, 24 Sep 2026 23:01:26 -0400 Subject: [PATCH] compiler: report an unterminated s or y command instead of aborting The substitution and transliteration compilers read the delimiter with ScriptCharProvider::current() even when the command letter was the last character on the line. This indexed past the end of the line and aborted. Check for the end of the line first and report an unterminated command, as GNU sed does. Scripts such as `s`, `1y`, and `p;s` now exit 1 with a diagnostic instead of aborting. The address-parser aborts from #570 were fixed separately in #578. --- src/sed/compiler.rs | 8 ++++++++ tests/by-util/test_sed.rs | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/sed/compiler.rs b/src/sed/compiler.rs index 02184fb2..4a59eeb5 100644 --- a/src/sed/compiler.rs +++ b/src/sed/compiler.rs @@ -841,6 +841,10 @@ fn compile_subst_command( ) -> UResult { line.advance(); // move past 's' + if line.eol() { + return compilation_error(lines, line, "unterminated `s' command"); + } + let delimiter = line.current(); if delimiter == '\0' || delimiter == '\\' { return compilation_error( @@ -907,6 +911,10 @@ fn compile_trans_command( ) -> UResult { line.advance(); // move past 'y' + if line.eol() { + return compilation_error(lines, line, "unterminated `y' command"); + } + let delimiter = line.current(); if delimiter == '\0' || delimiter == '\\' { return compilation_error( diff --git a/tests/by-util/test_sed.rs b/tests/by-util/test_sed.rs index 12f7f265..7216d4e0 100644 --- a/tests/by-util/test_sed.rs +++ b/tests/by-util/test_sed.rs @@ -2937,6 +2937,25 @@ fn test_comma_without_second_address() { } } +#[test] +fn test_unterminated_s_or_y_command() { + for (script, column, command) in [ + ("s", 2, 's'), + ("1s", 3, 's'), + ("p;s", 4, 's'), + ("y", 2, 'y'), + ("{y", 3, 'y'), + ] { + new_ucmd!() + .args(&[script]) + .fails() + .code_is(1) + .stderr_is(format!( + "sed: