summaryrefslogtreecommitdiff
path: root/doio.c
diff options
context:
space:
mode:
authorDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-07-22 19:32:40 +0100
committerDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-10-18 11:44:17 +0100
commit2fcab33080eaee2f4f7ee329a3769df17bb5ca3f (patch)
tree3df7773ab159557730b8497a4a1afbe033954244 /doio.c
parent317b515c14bcc4830f53c56c444c43122589ebad (diff)
downloadperl-2fcab33080eaee2f4f7ee329a3769df17bb5ca3f.tar.gz
[perl #131730] Fix exec PROGRAM LIST with empty LIST
This should call execvp() with an empty argv array (containing only the terminating NULL pointer), but was instead just returning false (and not setting $!). Executing a program with an empty argv array is valid ISO C: it merely requires argc to be nonnegative and argv[argc] to be NULL. POSIX states that that argv[0] "should point to a filename string that is associated with the process being started", but "should" only applies to applications claiming strict POSIX conformance. Perl does not, and certainly should not impose it on perl programs. This also requires handling the case where both PROGRAM and LIST are empty, to avoid calling execvp(NULL, …), which _is_ invalid. I've made it return ENOENT, which it the error POSIX specifies for execvp("", …).
Diffstat (limited to 'doio.c')
-rw-r--r--doio.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/doio.c b/doio.c
index 7b6c43531b..a12f8dc8a9 100644
--- a/doio.c
+++ b/doio.c
@@ -1924,7 +1924,8 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp,
#if defined(__SYMBIAN32__) || defined(__LIBCATAMOUNT__)
Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
#else
- if (sp > mark) {
+ assert(sp >= mark);
+ {
const char **a;
const char *tmps = NULL;
Newx(PL_Argv, sp - mark + 1, const char*);
@@ -1939,17 +1940,19 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp,
*a = NULL;
if (really)
tmps = SvPV_nolen_const(really);
- if ((!really && *PL_Argv[0] != '/') ||
+ if ((!really && PL_Argv[0] && *PL_Argv[0] != '/') ||
(really && *tmps != '/')) /* will execvp use PATH? */
TAINT_ENV(); /* testing IFS here is overkill, probably */
PERL_FPU_PRE_EXEC
if (really && *tmps) {
PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
- } else {
+ } else if (PL_Argv[0]) {
PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
- }
+ } else {
+ SETERRNO(ENOENT,RMS_FNF);
+ }
PERL_FPU_POST_EXEC
- S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0]), fd, do_report);
+ S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0] ? PL_Argv[0] : ""), fd, do_report);
}
do_execfree();
#endif