summaryrefslogtreecommitdiff
path: root/perl.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2003-06-30 08:36:38 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2003-06-30 08:36:38 +0000
commit3cb9023dc910d8a9abbd8d44e501f6e492155eb5 (patch)
treeb6e1589a07fc36b3023e7493649f21049543cb91 /perl.c
parentf9cbb277dec3cb2700132dedd25b05ea72cda45a (diff)
downloadperl-3cb9023dc910d8a9abbd8d44e501f6e492155eb5.tar.gz
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
Diffstat (limited to 'perl.c')
-rw-r--r--perl.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/perl.c b/perl.c
index 2f07f4cb80..ef3e205784 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;