diff options
author | Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> | 2017-10-18 17:04:57 +0100 |
---|---|---|
committer | Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> | 2017-10-18 17:04:57 +0100 |
commit | dc280c2b67516b7246d304d3e555b7b6dbc9f907 (patch) | |
tree | 04177f5123652c5852e56d82d62303e720c37041 | |
parent | 317b515c14bcc4830f53c56c444c43122589ebad (diff) | |
parent | 44246694c4a6d3dc854478b59c8b5ee8e0e886ae (diff) | |
download | perl-dc280c2b67516b7246d304d3e555b7b6dbc9f907.tar.gz |
Merge branch 'smoke-me/ilmari/exec-empty-argv' into blead
-rw-r--r-- | doio.c | 13 | ||||
-rw-r--r-- | pod/perldelta.pod | 6 | ||||
-rw-r--r-- | t/op/exec.t | 17 | ||||
-rw-r--r-- | vms/vms.c | 16 |
4 files changed, 37 insertions, 15 deletions
@@ -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"); @@ -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() */ |