This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: CvFILE corruption under ithreads
[perl5.git] / util.c
diff --git a/util.c b/util.c
index 7a8b815..1cab029 100644 (file)
--- a/util.c
+++ b/util.c
@@ -56,14 +56,14 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT];
 #  define FD_CLOEXEC 1                 /* NeXT needs this */
 #endif
 
-/* paranoid version of system's malloc() */
-
 /* NOTE:  Do not call the next three routines directly.  Use the macros
  * in handy.h, so that we can easily redefine everything to do tracking of
  * allocated hunks back to the original New to track down any memory leaks.
  * XXX This advice seems to be widely ignored :-(   --AD  August 1996.
  */
 
+/* paranoid version of system's malloc() */
+
 Malloc_t
 Perl_safesysmalloc(MEM_SIZE size)
 {
@@ -742,7 +742,7 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
  */
 
 /* If SvTAIL is actually due to \Z or \z, this gives false positives
-   if PL_multiline.  In fact if !PL_multiline the autoritative answer
+   if PL_multiline.  In fact if !PL_multiline the authoritative answer
    is not supported yet. */
 
 char *
@@ -781,8 +781,14 @@ Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift
     /* The value of pos we can stop at: */
     stop_pos = SvCUR(bigstr) - end_shift - (SvCUR(littlestr) - 1 - previous);
     if (previous + start_shift > stop_pos) {
+/*
+  stop_pos does not include SvTAIL in the count, so this check is incorrect
+  (I think) - see [ID 20010618.006] and t/op/study.t. HVDS 2001/06/19
+*/
+#if 0
        if (previous + start_shift == stop_pos + 1) /* A fake '\n'? */
            goto check_tail;
+#endif
        return Nullch;
     }
     while (pos < previous + start_shift) {
@@ -1454,7 +1460,7 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
 
 #ifdef USE_ENVIRON_ARRAY
        /* VMS' and EPOC's my_setenv() is in vms.c and epoc.c */
-#if !defined(WIN32)
+#if !defined(WIN32) && !defined(NETWARE)
 void
 Perl_my_setenv(pTHX_ char *nam, char *val)
 {
@@ -1508,7 +1514,7 @@ Perl_my_setenv(pTHX_ char *nam, char *val)
 #endif  /* PERL_USE_SAFE_PUTENV */
 }
 
-#else /* WIN32 */
+#else /* WIN32 || NETWARE */
 
 void
 Perl_my_setenv(pTHX_ char *nam,char *val)
@@ -1525,7 +1531,7 @@ Perl_my_setenv(pTHX_ char *nam,char *val)
     Safefree(envstr);
 }
 
-#endif /* WIN32 */
+#endif /* WIN32 || NETWARE */
 
 I32
 Perl_setenv_getix(pTHX_ char *nam)
@@ -1786,7 +1792,7 @@ VTOH(vtohl,long)
 PerlIO *
 Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)
 {
-#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(OS2) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL)
+#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(OS2) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) && !defined(NETWARE)
     int p[2];
     register I32 This, that;
     register Pid_t pid;
@@ -2283,7 +2289,7 @@ Perl_my_pclose(pTHX_ PerlIO *ptr)
 }
 #endif /* !DOSISH */
 
-#if  (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL)
+#if  (!defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(NETWARE)) && !defined(MACOS_TRADITIONAL)
 I32
 Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
 {
@@ -2345,7 +2351,7 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
     }
 #endif
 }
-#endif /* !DOSISH || OS2 || WIN32 */
+#endif /* !DOSISH || OS2 || WIN32 || NETWARE */
 
 void
 /*SUPPRESS 590*/
@@ -2790,7 +2796,7 @@ Perl_condpair_magic(pTHX_ SV *sv)
 {
     MAGIC *mg;
 
-    SvUPGRADE(sv, SVt_PVMG);
+    (void)SvUPGRADE(sv, SVt_PVMG);
     mg = mg_find(sv, PERL_MAGIC_mutex);
     if (!mg) {
        condpair_t *cp;
@@ -3598,33 +3604,39 @@ Fill the sv with current working directory
  *     because you might chdir out of a directory that you can't chdir
  *     back into. */
 
-/* XXX: this needs more porting #ifndef HAS_GETCWD */
 int
 Perl_sv_getcwd(pTHX_ register SV *sv)
 {
 #ifndef PERL_MICRO
 
-#ifndef HAS_GETCWD
+#ifdef HAS_GETCWD
+    {
+       char buf[MAXPATHLEN];
+
+        /* Some getcwd()s automatically allocate a buffer of the given
+        * size from the heap if they are given a NULL buffer pointer.
+        * The problem is that this behaviour is not portable. */
+        if (getcwd(buf, sizeof(buf) - 1)) {
+            STRLEN len = strlen(buf);
+            sv_setpvn(sv, buf, len);
+            return TRUE;
+        }
+        else {
+            sv_setsv(sv, &PL_sv_undef);
+            return FALSE;
+        }
+    }
+
+#else
+
     struct stat statbuf;
     int orig_cdev, orig_cino, cdev, cino, odev, oino, tdev, tino;
     int namelen, pathlen=0;
     DIR *dir;
     Direntry_t *dp;
-#endif
 
     (void)SvUPGRADE(sv, SVt_PV);
 
-#ifdef HAS_GETCWD
-
-    SvGROW(sv, 128);
-    while ((getcwd(SvPVX(sv), SvLEN(sv)-1) == NULL) && errno == ERANGE) {
-        SvGROW(sv, SvLEN(sv) + 128);
-    }
-    SvCUR_set(sv, strlen(SvPVX(sv)));
-    SvPOK_only(sv);
-
-#else
-
     if (PerlLIO_lstat(".", &statbuf) < 0) {
         SV_CWD_RETURN_UNDEF;
     }
@@ -3681,6 +3693,10 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
             SV_CWD_RETURN_UNDEF;
         }
 
+        if (pathlen + namelen + 1 >= MAXPATHLEN) {
+            SV_CWD_RETURN_UNDEF;
+       }
+
         SvGROW(sv, pathlen + namelen + 1);
 
         if (pathlen) {
@@ -3702,12 +3718,14 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 #endif
     }
 
-    SvCUR_set(sv, pathlen);
-    *SvEND(sv) = '\0';
-    SvPOK_only(sv);
+    if (pathlen) {
+        SvCUR_set(sv, pathlen);
+        *SvEND(sv) = '\0';
+        SvPOK_only(sv);
 
-    if (PerlDir_chdir(SvPVX(sv)) < 0) {
-        SV_CWD_RETURN_UNDEF;
+       if (PerlDir_chdir(SvPVX(sv)) < 0) {
+            SV_CWD_RETURN_UNDEF;
+        }
     }
     if (PerlLIO_stat(".", &statbuf) < 0) {
         SV_CWD_RETURN_UNDEF;
@@ -3728,166 +3746,3 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 #endif
 }
 
-/*
-=for apidoc sv_realpath
-
-Wrap or emulate realpath(3).
-
-=cut
- */
-int
-Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
-{
-#ifndef PERL_MICRO
-    char name[MAXPATHLEN] = { 0 }, *s;
-    STRLEN pathlen, namelen;
-
-    /* Don't use strlen() to avoid running off the end. */
-    s = memchr(path, '\0', MAXPATHLEN);
-    pathlen = s ? s - path : MAXPATHLEN;
-
-#ifdef HAS_REALPATH
-
-    /* Be paranoid about the use of realpath(),
-     * it is an infamous source of buffer overruns. */
-
-    /* Is the source buffer too long? */
-    if (pathlen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* Here goes nothing. */
-    if (realpath(path, name) == NULL) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %s",
-                  path, Strerror(errno));
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* Is the destination buffer too long?
-     * Don't use strlen() to avoid running off the end. */
-    s = memchr(name, '\0', MAXPATHLEN);
-    namelen = s ? s - name : MAXPATHLEN;
-    if (namelen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* The coast is clear? */
-    sv_setpvn(sv, name, namelen);
-    SvPOK_only(sv);
-
-    return TRUE;
-#else
-    {
-    DIR *parent;
-    Direntry_t *dp;
-    char dotdots[MAXPATHLEN] = { 0 };
-    struct stat cst, pst, tst;
-
-    if (PerlLIO_stat(path, &cst) < 0) {
-        Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s",
-                  path, Strerror(errno));
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    (void)SvUPGRADE(sv, SVt_PV);
-
-    if (!len) {
-        len = strlen(path);
-    }
-    Copy(path, dotdots, len, char);
-
-    for (;;) {
-        strcat(dotdots, "/..");
-        StructCopy(&cst, &pst, struct stat);
-
-        if (PerlLIO_stat(dotdots, &cst) < 0) {
-            Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s",
-                      dotdots, Strerror(errno));
-            SV_CWD_RETURN_UNDEF;
-        }
-
-        if (pst.st_dev == cst.st_dev && pst.st_ino == cst.st_ino) {
-            /* We've reached the root: previous is same as current */
-            break;
-        } else {
-            STRLEN dotdotslen = strlen(dotdots);
-
-            /* Scan through the dir looking for name of previous */
-            if (!(parent = PerlDir_open(dotdots))) {
-                Perl_warn(aTHX_ "sv_realpath: opendir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-
-            SETERRNO(0,SS$_NORMAL); /* for readdir() */
-            while ((dp = PerlDir_read(parent)) != NULL) {
-                if (SV_CWD_ISDOT(dp)) {
-                    continue;
-                }
-
-                Copy(dotdots, name, dotdotslen, char);
-                name[dotdotslen] = '/';
-#ifdef DIRNAMLEN
-                namelen = dp->d_namlen;
-#else
-                namelen = strlen(dp->d_name);
-#endif
-                Copy(dp->d_name, name + dotdotslen + 1, namelen, char);
-                name[dotdotslen + 1 + namelen] = 0;
-
-                if (PerlLIO_lstat(name, &tst) < 0) {
-                    PerlDir_close(parent);
-                    Perl_warn(aTHX_ "sv_realpath: lstat(\"%s\"): %s",
-                              name, Strerror(errno));
-                    SV_CWD_RETURN_UNDEF;
-                }
-
-                if (tst.st_dev == pst.st_dev && tst.st_ino == pst.st_ino)
-                    break;
-
-                SETERRNO(0,SS$_NORMAL); /* for readdir() */
-            }
-
-            if (!dp && errno) {
-                Perl_warn(aTHX_ "sv_realpath: readdir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-
-            SvGROW(sv, pathlen + namelen + 1);
-            if (pathlen) {
-                /* shift down */
-                Move(SvPVX(sv), SvPVX(sv) + namelen + 1, pathlen, char);
-            }
-
-            *SvPVX(sv) = '/';
-            Move(dp->d_name, SvPVX(sv)+1, namelen, char);
-            pathlen += (namelen + 1);
-
-#ifdef VOID_CLOSEDIR
-            PerlDir_close(parent);
-#else
-            if (PerlDir_close(parent) < 0) {
-                Perl_warn(aTHX_ "sv_realpath: closedir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-#endif
-        }
-    }
-
-    SvCUR_set(sv, pathlen);
-    SvPOK_only(sv);
-
-    return TRUE;
-    }
-#endif
-#else
-    return FALSE;
-#endif
-}
-