From: Jarkko Hietaniemi Date: Mon, 30 Jun 2003 08:36:38 +0000 (+0000) Subject: The 'contiguous' test for argv[], envp[] was bogus X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3cb9023dc910d8a9abbd8d44e501f6e492155eb5;p=p5sagit%2Fp5-mst-13.2.git The 'contiguous' test for argv[], envp[] was bogus since those need not be in memory end-to-end, e.g. in Tru64 they are aligned by eight. Loosen the test so that 'contiguousness' is fulfilled if the elements are within PTRSIZE alignment. This makes Tru64 to pass the join.t, too. p4raw-id: //depot/perl@19889 --- diff --git a/ext/threads/t/join.t b/ext/threads/t/join.t index f8b758e..0761a5f 100644 --- a/ext/threads/t/join.t +++ b/ext/threads/t/join.t @@ -91,7 +91,8 @@ ok(1,""); ok(1,""); } -if ($^O eq 'linux') { # We parse ps output so this is OS-dependent. +# We parse ps output so this is OS-dependent. +if ($^O =~ /^(linux|dec_osf)$/) { # First modify $0 in a subthread. print "# mainthread: \$0 = $0\n"; threads->new( sub { @@ -100,7 +101,7 @@ if ($^O eq 'linux') { # We parse ps output so this is OS-dependent. print "# subthread: \$0 = $0\n" } )->join; print "# mainthread: \$0 = $0\n"; print "# pid = $$\n"; - if (open PS, "ps -f |") { # Note: must work in (all) Linux(es). + if (open PS, "ps -f |") { # Note: must work in (all) systems. my ($sawpid, $sawexe); while () { chomp; diff --git a/mg.c b/mg.c index 8182376..1990b96 100644 --- a/mg.c +++ b/mg.c @@ -2372,13 +2372,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) pstat(PSTAT_SETCMD, un, len, 0, 0); } #endif - /* PL_origalen is set in perl_parse() to be the sum - * of the contiguous argv[] elements plus the size of - * the env in case that is contiguous with the argv[]. - * - * This means that in the worst case the area we are able - * to modify is limited to the size of the original argv[0]. - * --jhi */ + /* PL_origalen is set in perl_parse(). */ s = SvPV_force(sv,len); if (len >= (I32)PL_origalen) { /* Longer than original, will be truncated. */ @@ -2392,7 +2386,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) memset(PL_origargv[0] + len + 1, /* Is the space counterintuitive? Yes. * (You were expecting \0?) - * Does it work? Seems to. (In Linux at least.) + * Does it work? Seems to. (In Linux 2.4.20 at least.) * --jhi */ (int)' ', PL_origalen - len - 1); diff --git a/perl.c b/perl.c index 2f07f4c..ef3e205 100644 --- a/perl.c +++ b/perl.c @@ -934,35 +934,52 @@ setuid perl scripts securely.\n"); PL_origargv = argv; { - char *s = PL_origargv[0]; + /* 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]. + * --jhi */ + char *s; int i; - - s += strlen(s); - /* See if all the arguments are contiguous in memory */ + int mask = + ~(PTRSIZE == 4 ? 3 : PTRSIZE == 8 ? 7 : PTRSIZE == 16 ? 15 : 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[]. 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 - ) - { - ++s; - s += strlen(s); /* this one is ok too */ + if (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 - * (in case we later modify it)? */ - if (PL_origenviron - && (PL_origenviron[0] == s + 1)) - { + /* Can we grab env area too to be used as the area for $0? */ + if (PL_origenviron && + PL_origenviron[0] > s && + PL_origenviron[0] <= + INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask)) { + s = PL_origenviron[0]; + while (*s) s++; my_setenv("NoNe SuCh", Nullch); - /* force copy of environment */ - for (i = 0; PL_origenviron[i]; i++) - if (PL_origenviron[i] == s + 1) { - ++s; - s += strlen(s); + /* Force copy of environment. */ + for (i = 1; PL_origenviron[i]; i++) + if (PL_origenviron[i] > s && + PL_origenviron[i] <= + INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask)) { + s = PL_origenviron[i]; + while (*s) s++; } else break;