Skip to content

Malformed scripts abort instead of reporting a compilation error #570

Description

@SichenLiang

Several malformed or truncated scripts make uutils sed abort while it is
compiling the script, instead of reporting a compilation error and exiting 1
the way GNU sed does.

Reproduced with GNU sed 4.10 and uutils sed built from c46dd6da, both under
LC_ALL=C. The transcripts below omit the varying thread id and the shell's
job control lines.

The script reaching the end of the line after an address separator:

$ printf 'a\nb\n' | sed -n '2,'
sed: -e expression #1, char 2: unexpected ','
$ echo $?
1
$ printf 'a\nb\n' | ./target/release/sed -n '2,'
thread 'main' panicked at src/sed/script_char_provider.rs:45:29:
index out of bounds: the len is 2 but the index is 2
Aborted (core dumped)
$ echo $?
134

1,, 0,, $,, /a/,, 1~ and 2, followed by spaces do the same.

An invalid address after a separator reaches a different panic:

$ printf 'a\nb\n' | sed -n '2,d'
sed: -e expression #1, char 3: unexpected ','
$ echo $?
1
$ printf 'a\nb\n' | ./target/release/sed -n '2,d'
thread 'main' panicked at src/sed/compiler.rs:498:14:
invalid context address
Aborted (core dumped)
$ echo $?
134

So do 2,p, /a/,d, 2,{p}, 2 , d, 1,,2p and 1,}p.

A missing s or y delimiter:

$ printf 'a\nb\n' | sed -n 's'
sed: -e expression #1, char 1: unterminated 's' command
$ echo $?
1
$ printf 'a\nb\n' | ./target/release/sed -n 's'
thread 'main' panicked at src/sed/script_char_provider.rs:45:29:
index out of bounds: the len is 1 but the index is 1
Aborted (core dumped)
$ echo $?
134

So do y, 1s, {s and 1,2y.

The last form is different, because GNU accepts the script and runs it:

$ printf 'abc\n' | sed '1~p'
abc
abc
$ echo $?
0
$ printf 'abc\n' | ./target/release/sed '1~p'
thread 'main' panicked at src/sed/compiler.rs:498:14:
invalid context address
Aborted (core dumped)
$ echo $?
134

1,~p behaves the same way.

All of this happens while the script is being compiled. It also happens when
the script comes from -f, with or without a trailing newline, and when no
input operand is given at all. Exit status 134 is the release profile, where
Cargo.toml sets panic = "abort"; a debug build of the same code exits 101.

Neighbouring scripts are reported cleanly and exit 1: 2,3, 2,$, 2,/a/,
2,+, 2,~, ,3, ,, 2, s/, s/x/ and 1,~; 2,3d runs normally.
This is about the forms listed above rather than about incomplete scripts in
general.

There are two panic sites. src/sed/script_char_provider.rs:45 is current(),
which indexes the line directly, so its callers have to know they are not at
the end of the line. src/sed/compiler.rs:498 is the last arm of the address
parser, panic!("invalid context address"); the same function already returns
compilation_error(lines, line, "expected context address") for the
end-of-line case a few lines above.

I have a fix for all four paths and will open a PR. One limitation: with it,
1~p returns a compilation error rather than running the way GNU does.
Supporting it requires defining the meaning of an empty step, which I have
left for a separate change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions