From 282fc0b3cc2439f69587d980b62bef7f5d5bdfef Mon Sep 17 00:00:00 2001 From: Zefram Date: Wed, 6 Dec 2017 21:27:15 +0000 Subject: make exec keep its argument list more reliably Bits of exec code were putting the constructed commands into globals PL_Argv and PL_Cmd, which could then be clobbered by reentrancy. These are only global in order to manage their freeing, but that's better managed by using the scope stack. So replace them with automatic variables, with ENTER/SAVEFREEPV/LEAVE to free the memory. Also copy the strings acquired from SVs, to avoid magic clobbering the buffers of SVs already read. Fixes [perl #129888]. --- doio.c | 77 ++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'doio.c') diff --git a/doio.c b/doio.c index 9b713e1507..c98a5f5e44 100644 --- a/doio.c +++ b/doio.c @@ -1992,56 +1992,53 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp, Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system"); #else assert(sp >= mark); + ENTER; { - const char **a; + const char **argv, **a; const char *tmps = NULL; - Newx(PL_Argv, sp - mark + 1, const char*); - a = PL_Argv; + Newx(argv, sp - mark + 1, const char*); + SAVEFREEPV(argv); + a = argv; while (++mark <= sp) { - if (*mark) - *a++ = SvPV_nolen_const(*mark); - else + if (*mark) { + char *arg = savepv(SvPV_nolen_const(*mark)); + SAVEFREEPV(arg); + *a++ = arg; + } else *a++ = ""; } *a = NULL; - if (really) - tmps = SvPV_nolen_const(really); - if ((!really && PL_Argv[0] && *PL_Argv[0] != '/') || + if (really) { + tmps = savepv(SvPV_nolen_const(really)); + SAVEFREEPV(tmps); + } + if ((!really && argv[0] && *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 if (PL_Argv[0]) { - PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv)); + PerlProc_execvp(tmps,EXEC_ARGV_CAST(argv)); + } else if (argv[0]) { + PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv)); } else { SETERRNO(ENOENT,RMS_FNF); } PERL_FPU_POST_EXEC - S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0] ? PL_Argv[0] : ""), fd, do_report); + S_exec_failed(aTHX_ (really ? tmps : argv[0] ? argv[0] : ""), fd, do_report); } - do_execfree(); + LEAVE; #endif return FALSE; } -void -Perl_do_execfree(pTHX) -{ - Safefree(PL_Argv); - PL_Argv = NULL; - Safefree(PL_Cmd); - PL_Cmd = NULL; -} - #ifdef PERL_DEFAULT_DO_EXEC3_IMPLEMENTATION bool Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) { dVAR; - const char **a; + const char **argv, **a; char *s; char *buf; char *cmd; @@ -2050,7 +2047,9 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) PERL_ARGS_ASSERT_DO_EXEC3; + ENTER; Newx(buf, cmdlen, char); + SAVEFREEPV(buf); cmd = buf; memcpy(cmd, incmd, cmdlen); @@ -2086,8 +2085,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) PERL_FPU_POST_EXEC *s = '\''; S_exec_failed(aTHX_ PL_cshname, fd, do_report); - Safefree(buf); - return FALSE; + goto leave; } } } @@ -2134,15 +2132,16 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL); PERL_FPU_POST_EXEC S_exec_failed(aTHX_ PL_sh_path, fd, do_report); - Safefree(buf); - return FALSE; + goto leave; } } - Newx(PL_Argv, (s - cmd) / 2 + 2, const char*); - PL_Cmd = savepvn(cmd, s-cmd); - a = PL_Argv; - for (s = PL_Cmd; *s;) { + Newx(argv, (s - cmd) / 2 + 2, const char*); + SAVEFREEPV(argv); + cmd = savepvn(cmd, s-cmd); + SAVEFREEPV(cmd); + a = argv; + for (s = cmd; *s;) { while (isSPACE(*s)) s++; if (*s) @@ -2153,18 +2152,16 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) *s++ = '\0'; } *a = NULL; - if (PL_Argv[0]) { + if (argv[0]) { PERL_FPU_PRE_EXEC - PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv)); + PerlProc_execvp(argv[0],EXEC_ARGV_CAST(argv)); PERL_FPU_POST_EXEC - if (errno == ENOEXEC) { /* for system V NIH syndrome */ - do_execfree(); + if (errno == ENOEXEC) /* for system V NIH syndrome */ goto doshell; - } - S_exec_failed(aTHX_ PL_Argv[0], fd, do_report); + S_exec_failed(aTHX_ argv[0], fd, do_report); } - do_execfree(); - Safefree(buf); +leave: + LEAVE; return FALSE; } -- cgit v1.2.1