Bug 278653 - sh: fix sh -c -e cmd as per POSIX
Summary: sh: fix sh -c -e cmd as per POSIX
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-standards (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-29 15:07 UTC by Christian Weisgerber
Modified: 2024-04-30 21:03 UTC (History)
3 users (show)

See Also:


Attachments
fix sh -c -e cmd as per POSIX (2.18 KB, text/plain)
2024-04-29 15:07 UTC, Christian Weisgerber
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Christian Weisgerber freebsd_committer freebsd_triage 2024-04-29 15:07:27 UTC
Created attachment 250294 [details]
fix sh -c -e cmd as per POSIX

POSIX requires sh(1) to handle -c like an option that does not take an argument. We already handle the special case of attached options after -c...

$ sh -ce 'echo hello world'
hello world

... but these fail:

$ sh -c -e 'echo hello world'
echo hello world: -e: not found
$ sh -c -- 'echo hello world'
echo hello world: --: not found

NetBSD fixed this 21 years ago. With their fix:

$ sh -c -e 'echo hello world'
hello world
$ sh -c -- 'echo hello world'
hello world
$ sh -c -e 'echo hello; false; echo world'
hello

Patch attached. I also added a minimal regression test.
I have only tested this on 14-STABLE, but there are no relevant changes between 14-STABLE and 15-CURRENT in sh.
Comment 1 Benjamin Takacs 2024-04-30 07:33:51 UTC
this needs to fix system(3) as well as popen(3) too, as currently they call  sh -c <command>  with this change, that is no longer safe and needs to call  sh -c -- <command>

See also: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274650 (should that bug depend on this one?)
Comment 2 Bob Bishop 2024-04-30 08:50:09 UTC
(In reply to Benjamin Takacs from comment #1)

Also probably the examples in su(1) where there is a `-c' minefield.
Comment 3 Bob Bishop 2024-04-30 09:03:27 UTC
And actually this affects any code that calls `sh -c ....' directly. This is getting dangerously close to a POLA violation, POSIX notwithstanding.
Comment 4 Benjamin Takacs 2024-04-30 10:27:43 UTC
(In reply to Bob Bishop from comment #2)
(In reply to Bob Bishop from comment #3)

This being such a footgun is why I argue in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274650#c1 for just documenting our sh to be *not* posix compatible on some stuff and leave -c alone.
Comment 5 Christian Weisgerber freebsd_committer freebsd_triage 2024-04-30 12:14:49 UTC
It doesn't break any realistic existing usage of sh -c cmd.
Comment 6 Benjamin Takacs 2024-04-30 12:33:18 UTC
(In reply to Christian Weisgerber from comment #5)

I just listed two that became incorrect. system(3) and popen(3). How do you know I don't use - as prefix to mark internal commands and build commandlines run them via system, popen or sh -c?
Comment 7 Jilles Tjoelker freebsd_committer freebsd_triage 2024-04-30 20:20:00 UTC
The patch in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=220587 has more test cases.

Another thing that will break with the fixed -c is the ruby ports (not because of the upstream code but because of scripting in the port itself): https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222872 .
Comment 8 Christian Weisgerber freebsd_committer freebsd_triage 2024-04-30 21:03:26 UTC
(In reply to Benjamin Takacs from comment #6)
That takes me to my starting point, which was a discussion about shell scripting where somebody was bending over backwards to use POSIX-ly correct code that handled all corner cases, so he used "sh -c --" and was quite astonished when I pointed out that this breaks on FreeBSD.

Obviously system(3) and popen(3) will need to be fixed accordingly.