The 'contiguous' test for argv[], envp[] was bogus
Jarkko Hietaniemi [Mon, 30 Jun 2003 08:36:38 +0000 (08:36 +0000)]
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

ext/threads/t/join.t
mg.c
perl.c

index f8b758e..0761a5f 100644 (file)
@@ -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 (<PS>) {
       chomp;
diff --git a/mg.c b/mg.c
index 8182376..1990b96 100644 (file)
--- 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 (file)
--- 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;