diff --git a/MANIFEST b/MANIFEST index d276691d8b21..635dd727c669 100644 --- a/MANIFEST +++ b/MANIFEST @@ -6166,6 +6166,7 @@ t/re/uniprops09.t Test unicode \p{} regex constructs t/re/uniprops10.t Test unicode \p{} regex constructs t/re/user_prop_race_thr.t Test races in user-defined \p{} under threads t/README Instructions for regression tests +t/run/argv_free.t Ensure no conflicts between @ARGV and <>. t/run/cloexec.t Test close-on-exec. t/run/dtrace.pl For dtrace.t t/run/dtrace.t Test for DTrace probes diff --git a/pp_ctl.c b/pp_ctl.c index 44289bbd689d..b378ead7e375 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -972,17 +972,29 @@ PP(pp_grepstart) dSP; SV *src; - if (PL_stack_base + TOPMARK == SP) { + int count = SP - (PL_stack_base + TOPMARK); + + if (count == 0) { (void)POPMARK; if (GIMME_V == G_SCALAR) XPUSHs(&PL_sv_zero); RETURNOP(PL_op->op_next->op_next); } + PL_stack_sp = PL_stack_base + TOPMARK + 1; Perl_pp_pushmark(aTHX); /* push dst */ Perl_pp_pushmark(aTHX); /* push src */ ENTER_with_name("grep"); /* enter outer scope */ + /* This prevents the map/grep arguments from disappearing midstream. + (e.g., map { @foo = () } @foo) + */ + for (int i=0; i 67 ); +plan( tests => 68 ); { my @lol = ([qw(a b c)], [], [qw(1 2 3)]); @@ -238,3 +238,10 @@ pass 'no double frees with grep/map { undef *_ }'; my @a = map { 1; "$_" } 1,2; is("@a", "1 2", "PADTMP"); } + +{ + # Ensure that the map args list doesn't disappear midstream: + my @foo = qw(1 2 3 4 5 6 7); + my @foo2 = map { @foo = (); $_ } @foo; + is("@foo2", "1 2 3 4 5 6 7", 'map preserves args list'); +} diff --git a/t/run/argv_free.t b/t/run/argv_free.t new file mode 100644 index 000000000000..ca474fefcf51 --- /dev/null +++ b/t/run/argv_free.t @@ -0,0 +1,13 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + @INC = '../lib'; + require './test.pl'; + skip_all_without_config('d_fcntl'); +} + +system $^X, '-e', 'close STDIN; map <>, @ARGV', 1, 2; +is($?, 0, '@ARGV does not conflict with <>'); + +done_testing;