View Issue Details

IDProjectCategoryView StatusLast Update
00020021003.1(2024)/Issue8System Interfacespublic2026-11-10 06:05
Reporterstephane Assigned To 
PrioritynormalSeverityObjectionTypeEnhancement Request
Status NewResolutionOpen 
NameStephane Chazelas
Organization
User Reference
Sectionhttps://pubs.opengroup.org/onlinepubs/9799919799/functions/execl.html
Page Numberhttps://pubs.opengroup.org/onlinepubs/9799919799/functions/execl.html
Line Numberhttps://pubs.opengroup.org/onlinepubs/9799919799/functions/execl.html
Interp Status
Final Accepted Text
Summary0002002: execlp() / execvp() and commands starting with - or +
DescriptionSimilar to 0001440, related to 0001600

https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/execl.html has:

"""
In the cases where the other members of the exec family of functions would fail and set errno to [ENOEXEC], the execlp() and execvp() functions shall execute a command interpreter and the environment of the executed command shall be as if the process invoked the sh utility using execl() as follows:

execl(<shell path>, <name>, file, <args>, (char *)0);


where <shell path> is an unspecified pathname for the sh utility, <name> is an unspecified string, file is the process image file, and where <args> is zero or more parameters corresponding to any initial non-null arguments passed after arg0 for execlp() or to any initial non-null members of argv starting at argv[1] for execvp().
"""

"file is the process image file" should probably be "file is the pathname to the process image file", but also, if that pathname starts with - or +, such as when invoked as execlp("-dir-/cmd",...) or execlp("+x",...) and +x was found in the current directory because $PATH contains an empty component, then that path will be taken as an option by sh instead of the path to the file being executed.

There's a similar problem in the resolution of 0001600 where

#! /path/to/sh
${0##*/} "$@"


Should be:

#! /path/to/sh --
"${0##*/}" "$@"


(leaving that ${0##*/} unquoted to request split+glob also doesn't make sense here)

Desired ActionFor execlp/execvp, change to:

"""
execl(<shell path>, <name>, "--", file, <args>, (char *)0);


where <shell path> is an unspecified pathname for the sh utility, <name> is an unspecified string, file is the pathname of the process image file, and where <args> is zero or more parameters corresponding to any initial non-null arguments passed after arg0 for execlp() or to any initial non-null members of argv starting at argv[1] for execvp().
"""

Apparently Solaris/Illumos prefix the path with ./ if it starts with - (not +) instead (https://github.com/illumos/illumos-gate/blob/7bbcc14f12e8a235cc9668f76da6d2c9ecf14cd4/usr/src/lib/libc/port/gen/execvp.c#L156-L158). We may want to also allow that even if that means that changes the value of `$0` in the shell script.

For the builtins (0001600 resolution):

#! /path/to/sh --
"${0##*/}" "$@"


Using a single dash as in:

#! /path/to/sh -
"${0##*/}" "$@"


May be more canonical as that's what was done for the Bourne shell.
Tagsissue9

Relationships

related to 0001600 Closed 1003.1(2016/18)/Issue7+TC2 Problems with the suggested single-line shell script: $0 "$@" 

Activities

nick

2026-11-09 17:29

manager   bugnote:0007552

Last edited: 2026-11-09 17:30

Interpretation response
------------------------
The standard clearly states the behavior of execvp and execlp , and conforming implementations must conform to this.

Rationale:
-------------
The behavior specified by the standard contains dangers that users may not realize, and there is no appropriate warning.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------

Page 867, after line 29504 add a following new sentence:

If the file argument starts with a + or a -, the resulting behavior is undefined.


Page 874, after line 29802, add a new paragraph:

Note for the execlp() and execvp() functions, if the file argument has a leading '+' or '-' character and the file found does not have appropriate execute permission, the shell that is invoked may use this argument as option settings, and run a different script than was intended. Some implementations add a "--" argument to resolve this, but this is not required. Thus, the behavior in this case is undefined.

stephane

2026-11-10 05:46

reporter   bugnote:0007557

Thanks, that's a step in the right direction in my opinion as at least it raises awareness to the potential issue, but some issues remain:

It doesn't address my:

  > "file is the process image file" should probably be "file is the pathname to the process image file"

And that "if the file argument" in the proposed change makes me realise the problem in the original text is that in

  execl(<shell path>, <name>, file, <args>, (char *)0);

That "file" incorrectly refers to the "file" argument passed in:

  execlp(const char *file, const char *arg0, ... /*, (char *)0 */);

It should rather be:

   execl(<shell path>, <name>, <resolved_pathname>, <args>, (char *)0);

Where <resolved_pathname> is the pathname to file resolved as per above (with behaviour undefined if that pathname (not file) starts with - or +). For example:

% PATH=~/bin:/bin ltrace -e execvp env zzz blah
env->execvp("zzz", ["zzz", "blah"] <no return ...>
--- Called exec() ---
+++ exited (status 0) +++
% PATH=~/bin:/bin strace -qqe execve env zzz blah
execve("/bin/env", ["env", "zzz", "blah"], 0x7fffc2ccc440 /* 55 vars */) = 0
execve("/home/chazelas/bin/zzz", ["zzz", "blah"], 0x7ffc48cf3368 /* 55 vars */) = -1 ENOEXEC (Exec format error)
execve("/bin/sh", ["/bin/sh", "/home/chazelas/bin/zzz", "blah"], 0x7ffc48cf3368 /* 55 vars */) = 0


It's the pathname resolved from a $PATH lookup (/home/chazelas/bin/zzz) that was passed as argument to /bin/sh, not zzz (the "file" argument to execvp()).

And:

$ PATH=+dir+:/bin strace -qqe execve env zzz blah
execve("/bin/env", ["env", "zzz", "blah"], 0x7fffe38a6820 /* 55 vars */) = 0
execve("+dir+/zzz", ["zzz", "blah"], 0x7ffda17ab848 /* 55 vars */) = -1 ENOEXEC (Exec format error)
execve("/bin/sh", ["/bin/sh", "+dir+/zzz", "blah"], 0x7ffda17ab848 /* 55 vars */) = 0
/bin/sh: 0: Illegal option -d


(as that execvp() implementation fails to pass the -- option delimiter).

Note that I'm aware of Solaris/Illumos prepending "./" to that pathname when it starts with - (not + in Illumos at least which would be an overlook) as already noted, I don't know if there are any that add the "--" delimiter (or "-" which is more idiomatic for sh as was supported by the Bourne shell).

stephane

2026-11-10 05:49

reporter   bugnote:0007558

The proposed resolution also doesn't address the missing -- / - in

#! /path/to/sh --
"${0##*/}" "$@"

stephane

2026-11-10 06:05

reporter   bugnote:0007559

Also, it is not about "and the file found does not have appropriate execute permission".

If the file does not have appropriate permission, execlp() / execvp() must fail with the appropriate error code (EACESS / EPERM...).

"sh" is only invoked for files that have appropriate execute permission and for which execve() returns ENOEXEC (an executable format not recognised by the system).

Issue History

Date Modified Username Field Change
2026-10-28 18:50 stephane New Issue
2026-11-02 16:30 msbrown Relationship added related to 0001600
2026-11-09 17:28 msbrown Tag Attached: issue9
2026-11-09 17:29 nick Note Added: 0007552
2026-11-09 17:30 nick Note Edited: 0007552
2026-11-10 05:46 stephane Note Added: 0007557
2026-11-10 05:49 stephane Note Added: 0007558
2026-11-10 06:05 stephane Note Added: 0007559