summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-10-18 17:04:57 +0100
committerDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-10-18 17:04:57 +0100
commitdc280c2b67516b7246d304d3e555b7b6dbc9f907 (patch)
tree04177f5123652c5852e56d82d62303e720c37041
parent317b515c14bcc4830f53c56c444c43122589ebad (diff)
parent44246694c4a6d3dc854478b59c8b5ee8e0e886ae (diff)
downloadperl-dc280c2b67516b7246d304d3e555b7b6dbc9f907.tar.gz
Merge branch 'smoke-me/ilmari/exec-empty-argv' into blead
-rw-r--r--doio.c13
-rw-r--r--pod/perldelta.pod6
-rw-r--r--t/op/exec.t17
-rw-r--r--vms/vms.c16
4 files changed, 37 insertions, 15 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
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index c0beb063ee..d93050733f 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -362,7 +362,11 @@ files in F<ext/> and F<lib/> are best summarized in L</Modules and Pragmata>.
=item *
-XXX
+Calling L<exec PROGRAM LIST|perlfunc/exec PROGRAM LIST> with an empty C<LIST>
+has been fixed. This should call C<execvp()> with an empty C<argv> array
+(containing only the terminating C<NULL> pointer), but was instead just
+returning false (and not setting L<C<$!>|perlvar/$!>).
+L<[perl #131730]|https://rt.perl.org/Public/Bug/Display.html?id=131730>
=back
diff --git a/t/op/exec.t b/t/op/exec.t
index 11554395b9..5a0f7b5601 100644
--- a/t/op/exec.t
+++ b/t/op/exec.t
@@ -36,7 +36,7 @@ $ENV{LANGUAGE} = 'C'; # Ditto in GNU.
my $Is_VMS = $^O eq 'VMS';
my $Is_Win32 = $^O eq 'MSWin32';
-plan(tests => 25);
+plan(tests => 29);
my $Perl = which_perl();
@@ -156,6 +156,21 @@ TODO: {
"exec failure doesn't terminate process");
}
+{
+ local $! = 0;
+ ok !exec(), 'empty exec LIST fails';
+ ok $! == 2 || $! =~ qr/\bno\b.*\bfile\b/i, 'errno = ENOENT'
+ or printf "# \$! eq %d, '%s'\n", $!, $!;
+
+}
+{
+ local $! = 0;
+ my $err = $!;
+ ok !(exec {""} ()), 'empty exec PROGRAM LIST fails';
+ ok $! == 2 || $! =~ qr/\bno\b.*\bfile\b/, 'errno = ENOENT'
+ or printf "# \$! eq %d, '%s'\n", $!, $!;
+}
+
my $test = curr_test();
exec $Perl, '-le', qq{${quote}print 'ok $test - exec PROG, LIST'${quote}};
fail("This should never be reached if the exec() worked");
diff --git a/vms/vms.c b/vms/vms.c
index 5ca4d7c0e3..df0aed85b7 100644
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -10953,16 +10953,16 @@ Perl_vms_do_aexec(pTHX_ SV *really,SV **mark,SV **sp)
bool exec_sts;
char * cmd;
- if (sp > mark) {
- if (vfork_called) { /* this follows a vfork - act Unixish */
- vfork_called--;
- if (vfork_called < 0) {
- Perl_warn(aTHX_ "Internal inconsistency in tracking vforks");
- vfork_called = 0;
- }
- else return do_aexec(really,mark,sp);
+ if (vfork_called) { /* this follows a vfork - act Unixish */
+ vfork_called--;
+ if (vfork_called < 0) {
+ Perl_warn(aTHX_ "Internal inconsistency in tracking vforks");
+ vfork_called = 0;
}
+ else return do_aexec(really,mark,sp);
+ }
/* no vfork - act VMSish */
+ if (sp > mark) {
cmd = setup_argstr(aTHX_ really,mark,sp);
exec_sts = vms_do_exec(cmd);
Safefree(cmd); /* Clean up from setup_argstr() */