X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl.c;h=73f3273c0dbfded4d56568aed5906638b3532272;hb=43c32782ed6d18ddfca58337454582a388bfa6f8;hp=69d7084096a15c8c11e69a34bf4a353d5a8bcb4b;hpb=9d40e17d44e193330835b996e62e268e9aa05d1b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perl.c b/perl.c index 69d7084..73f3273 100644 --- a/perl.c +++ b/perl.c @@ -933,6 +933,92 @@ setuid perl scripts securely.\n"); PL_origargc = argc; PL_origargv = argv; + { + /* Set PL_origalen be the sum of the contiguous argv[] + * elements plus the size of the env in case that it is + * contiguous with the argv[]. This is used in mg.c:mg_set() + * as the maximum modifiable length of $0. In the worst case + * the area we are able to modify is limited to the size of + * the original argv[0]. (See below for 'contiguous', though.) + * --jhi */ + char *s; + int i; + UV mask = + ~(UV)(PTRSIZE == 4 ? 3 : PTRSIZE == 8 ? 7 : PTRSIZE == 16 ? 15 : 0); + /* Do the mask check only if the args seem like aligned. */ + UV aligned = + (mask < ~(UV)0) && ((PTR2UV(argv[0]) & mask) == PTR2UV(argv[0])); + + /* See if all the arguments are contiguous in memory. Note + * that 'contiguous' is a loose term because some platforms + * align the argv[] and the envp[]. If the arguments look + * like non-aligned, assume that they are 'strictly' or + * 'traditionally' contiguous. If the arguments look like + * aligned, we just check that they are within aligned + * PTRSIZE bytes. As long as no system has something bizarre + * like the argv[] interleaved with some other data, we are + * fine. (Did I just evoke Murphy's Law?) --jhi */ + s = PL_origargv[0]; + while (*s) s++; + for (i = 1; i < PL_origargc; i++) { + if ((PL_origargv[i] == s + 1 +#ifdef OS2 + || PL_origargv[i] == s + 2 +#endif + ) + || + (aligned && + (PL_origargv[i] > s && + PL_origargv[i] <= + INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask))) + ) + { + s = PL_origargv[i]; + while (*s) s++; + } + else + break; + } + /* Can we grab env area too to be used as the area for $0? */ + if (PL_origenviron) { + if ((PL_origenviron[0] == s + 1 +#ifdef OS2 + || (PL_origenviron[0] == s + 9 && (s += 8)) +#endif + ) + || + (aligned && + (PL_origenviron[0] > s && + PL_origenviron[0] <= + INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask))) + ) + { +#ifndef OS2 + s = PL_origenviron[0]; + while (*s) s++; +#endif + my_setenv("NoNe SuCh", Nullch); + /* Force copy of environment. */ + for (i = 1; PL_origenviron[i]; i++) { + if (PL_origenviron[i] == s + 1 + || + (aligned && + (PL_origenviron[i] > s && + PL_origenviron[i] <= + INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask))) + ) + { + s = PL_origenviron[i]; + while (*s) s++; + } + else + break; + } + } + } + PL_origalen = s - PL_origargv[0]; + } + if (PL_do_undump) { /* Come here if running an undumped a.out. */ @@ -2196,6 +2282,40 @@ NULL PerlIO_printf(PerlIO_stdout(), "\n %s", *p++); } +/* convert a string of -D options (or digits) into an int. + * sets *s to point to the char after the options */ + +#ifdef DEBUGGING +int +Perl_get_debug_opts(pTHX_ char **s) +{ + int i = 0; + if (isALPHA(**s)) { + /* if adding extra options, remember to update DEBUG_MASK */ + static char debopts[] = "psltocPmfrxu HXDSTRJvC"; + + for (; isALNUM(**s); (*s)++) { + char *d = strchr(debopts,**s); + if (d) + i |= 1 << (d - debopts); + else if (ckWARN_d(WARN_DEBUGGING)) + Perl_warner(aTHX_ packWARN(WARN_DEBUGGING), + "invalid option -D%c\n", **s); + } + } + else { + i = atoi(*s); + for (; isALNUM(**s); (*s)++) ; + } +# ifdef EBCDIC + if ((i & DEBUG_p_FLAG) && ckWARN_d(WARN_DEBUGGING)) + Perl_warner(aTHX_ packWARN(WARN_DEBUGGING), + "-Dp not implemented on this platform\n"); +# endif + return i; +} +#endif + /* This routine handles any switches that can be given during run */ char * @@ -2295,24 +2415,8 @@ Perl_moreswitches(pTHX_ char *s) { #ifdef DEBUGGING forbid_setid("-D"); - if (isALPHA(s[1])) { - /* if adding extra options, remember to update DEBUG_MASK */ - static char debopts[] = "psltocPmfrxu HXDSTRJvC"; - char *d; - - for (s++; *s && (d = strchr(debopts,*s)); s++) - PL_debug |= 1 << (d - debopts); - } - else { - PL_debug = atoi(s+1); - for (s++; isDIGIT(*s); s++) ; - } -#ifdef EBCDIC - if (DEBUG_p_TEST_ && ckWARN_d(WARN_DEBUGGING)) - Perl_warner(aTHX_ packWARN(WARN_DEBUGGING), - "-Dp not implemented on this platform\n"); -#endif - PL_debug |= DEBUG_TOP_FLAG; + s++; + PL_debug = get_debug_opts(&s) | DEBUG_TOP_FLAG; #else /* !DEBUGGING */ if (ckWARN_d(WARN_DEBUGGING)) Perl_warner(aTHX_ packWARN(WARN_DEBUGGING), @@ -3333,7 +3437,15 @@ S_init_ids(pTHX) bool Perl_doing_taint(int argc, char *argv[], char *envp[]) { - dTHX; +#ifndef PERL_IMPLICIT_SYS + /* If we have PERL_IMPLICIT_SYS we can't call getuid() et alia + * before we have an interpreter-- and the whole point of this + * function is to be called at such an early stage. If you are on + * a system with PERL_IMPLICIT_SYS but you do have a concept of + * "tainted because running with altered effective ids', you'll + * have to add your own checks somewhere in here. The two most + * known samples of 'implicitness' are Win32 and NetWare, neither + * of which has much of concept of 'uids'. */ int uid = PerlProc_getuid(); int euid = PerlProc_geteuid(); int gid = PerlProc_getgid(); @@ -3345,6 +3457,7 @@ Perl_doing_taint(int argc, char *argv[], char *envp[]) #endif if (uid && (euid != uid || egid != gid)) return 1; +#endif /* !PERL_IMPLICIT_SYS */ /* This is a really primitive check; environment gets ignored only * if -T are the first chars together; otherwise one gets * "Too late" message. */