Upgrade to CPAN-1.87_62
[p5sagit/p5-mst-13.2.git] / util.c
diff --git a/util.c b/util.c
index 07dd4d4..44ff36f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -882,8 +882,8 @@ Perl_savepv(pTHX_ const char *pv)
     else {
        char *newaddr;
        const STRLEN pvlen = strlen(pv)+1;
-       Newx(newaddr,pvlen,char);
-       return memcpy(newaddr,pv,pvlen);
+       Newx(newaddr, pvlen, char);
+       return (char*)memcpy(newaddr, pv, pvlen);
     }
 }
 
@@ -939,7 +939,7 @@ Perl_savesharedpv(pTHX_ const char *pv)
     if (!newaddr) {
        return write_no_mem();
     }
-    return memcpy(newaddr,pv,pvlen);
+    return (char*)memcpy(newaddr, pv, pvlen);
 }
 
 /*
@@ -1537,8 +1537,10 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
     const MEM_SIZE len_wanted = sizeof(STRLEN) + size;
     PERL_UNUSED_CONTEXT;
 
-    buffer = specialWARN(buffer) ? PerlMemShared_malloc(len_wanted)
-       : PerlMemShared_realloc(buffer, len_wanted);
+    buffer = (STRLEN*)
+       (specialWARN(buffer) ?
+        PerlMemShared_malloc(len_wanted) :
+        PerlMemShared_realloc(buffer, len_wanted));
     buffer[0] = size;
     Copy(bits, (buffer + 1), size, char);
     return buffer;
@@ -1555,8 +1557,7 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
    *(s+(nlen+1+vlen)) = '\0'
 
 #ifdef USE_ENVIRON_ARRAY
-       /* VMS' my_setenv() is in vms.c */
-#if !defined(WIN32) && !defined(NETWARE)
+/* VMS' my_setenv() is in vms.c */
 void
 Perl_my_setenv(pTHX_ const char *nam, const char *val)
 {
@@ -1568,47 +1569,53 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
   {
 #ifndef PERL_USE_SAFE_PUTENV
     if (!PL_use_safe_putenv) {
-    /* most putenv()s leak, so we manipulate environ directly */
-    register I32 i=setenv_getix(nam);          /* where does it go? */
-    int nlen, vlen;
-
-    if (environ == PL_origenviron) {   /* need we copy environment? */
-       I32 j;
-       I32 max;
-       char **tmpenv;
-
-       max = i;
-       while (environ[max])
-           max++;
-       tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
-       for (j=0; j<max; j++) {         /* copy environment */
-           const int len = strlen(environ[j]);
-           tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
-           Copy(environ[j], tmpenv[j], len+1, char);
-       }
-       tmpenv[max] = NULL;
-       environ = tmpenv;               /* tell exec where it is now */
-    }
-    if (!val) {
-       safesysfree(environ[i]);
-       while (environ[i]) {
-           environ[i] = environ[i+1];
-           i++;
+       /* The excuse for this code was that many putenv()s used to
+        * leak, so we manipulate environ directly -- but the claim is
+        * somewhat doubtful, since manipulating environment CANNOT be
+        * made in a safe way, the env API and the whole concept are
+        * fundamentally broken. */
+       register I32 i = setenv_getix(nam);             /* where does it go? */
+       int nlen, vlen;
+
+       if (i >= 0) {
+           if (environ == PL_origenviron) {    /* need we copy environment? */
+               I32 j;
+               I32 max;
+               char **tmpenv;
+           
+               max = i;
+               while (environ[max])
+                   max++;
+               tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
+               for (j=0; j<max; j++) {         /* copy environment */
+                   const int len = strlen(environ[j]);
+                   tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
+                   Copy(environ[j], tmpenv[j], len+1, char);
+               }
+               tmpenv[max] = NULL;
+               environ = tmpenv;               /* tell exec where it is now */
+           }
+           if (!val) {
+               safesysfree(environ[i]);
+               while (environ[i]) {
+                   environ[i] = environ[i+1];
+                   i++;
+               }
+               return;
+           }
+           if (!environ[i]) {                  /* does not exist yet */
+               environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
+               environ[i+1] = NULL;    /* make sure it's null terminated */
+           }
+           else
+               safesysfree(environ[i]);
+           nlen = strlen(nam);
+           vlen = strlen(val);
+           
+           environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
+           /* all that work just for this */
+           my_setenv_format(environ[i], nam, nlen, val, vlen);
        }
-       return;
-    }
-    if (!environ[i]) {                 /* does not exist yet */
-       environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
-       environ[i+1] = NULL;    /* make sure it's null terminated */
-    }
-    else
-       safesysfree(environ[i]);
-       nlen = strlen(nam);
-       vlen = strlen(val);
-
-       environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
-       /* all that work just for this */
-       my_setenv_format(environ[i], nam, nlen, val, vlen);
     } else {
 # endif
 #   if defined(__CYGWIN__) || defined(EPOC) || defined(__SYMBIAN32__) || defined(__riscos__)
@@ -1653,36 +1660,46 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
   }
 }
 
-#else /* WIN32 || NETWARE */
+#else /* USE_ENVIRON_ARRAY */
 
 void
 Perl_my_setenv(pTHX_ const char *nam, const char *val)
 {
     dVAR;
-    register char *envstr;
-    const int nlen = strlen(nam);
-    int vlen;
+#if !(defined(WIN32) || defined(NETWARE))
+# ifdef USE_ITHREADS
+    /* only parent thread can modify process environment */
+    if (PL_curinterp == aTHX)
+# endif
+#endif
+    {
+       register char *envstr;
+       const int nlen = strlen(nam);
+       int vlen;
 
-    if (!val) {
-       val = "";
+       if (!val) {
+           val = "";
+       }
+       vlen = strlen(val);
+       Newx(envstr, nlen+vlen+2, char);
+       my_setenv_format(envstr, nam, nlen, val, vlen);
+       (void)PerlEnv_putenv(envstr);
+       Safefree(envstr);
     }
-    vlen = strlen(val);
-    Newx(envstr, nlen+vlen+2, char);
-    my_setenv_format(envstr, nam, nlen, val, vlen);
-    (void)PerlEnv_putenv(envstr);
-    Safefree(envstr);
 }
 
-#endif /* WIN32 || NETWARE */
+#endif /* USE_ENVIRON_ARRAY */
+
+#if !defined(VMS)
 
-#ifndef PERL_MICRO
 I32
 Perl_setenv_getix(pTHX_ const char *nam)
 {
-    register I32 i;
+    register I32 i = -1;
     register const I32 len = strlen(nam);
     PERL_UNUSED_CONTEXT;
 
+#ifdef USE_ENVIRON_ARRAY
     for (i = 0; environ[i]; i++) {
        if (
 #ifdef WIN32
@@ -1693,11 +1710,12 @@ Perl_setenv_getix(pTHX_ const char *nam)
            && environ[i][len] == '=')
            break;                      /* strnEQ must come first to avoid */
     }                                  /* potential SEGV's */
+#endif /* USE_ENVIRON_ARRAY */
+
     return i;
 }
-#endif /* !PERL_MICRO */
 
-#endif /* !VMS && !EPOC*/
+#endif /* !PERL_VMS */
 
 #ifdef UNLINK_ALL_VERSIONS
 I32
@@ -3022,7 +3040,7 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch,
            if ((strlen(tmpbuf) + strlen(scriptname)
                 + MAX_EXT_LEN) >= sizeof tmpbuf)
                continue;       /* don't search dir with too-long name */
-           strcat(tmpbuf, scriptname);
+           my_strlcat(tmpbuf, scriptname, sizeof(tmpbuf));
 #else  /* !VMS */
 
 #ifdef DOSISH
@@ -3054,11 +3072,11 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch,
                len = strlen(scriptname);
                if (len+MAX_EXT_LEN+1 >= sizeof(tmpbuf))
                    break;
-               /* FIXME? Convert to memcpy  */
-               cur = strcpy(tmpbuf, scriptname);
+               my_strlcpy(tmpbuf, scriptname, sizeof(tmpbuf));
+               cur = tmpbuf;
            }
        } while (extidx >= 0 && ext[extidx]     /* try an extension? */
-                && strcpy(tmpbuf+len, ext[extidx++]));
+                && my_strlcpy(tmpbuf+len, ext[extidx++], sizeof(tmpbuf) - len));
 #endif
     }
 #endif
@@ -3118,13 +3136,7 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch,
            if (len == 2 && tmpbuf[0] == '.')
                seen_dot = 1;
 #endif
-#ifdef HAS_STRLCAT
-           (void)strlcpy(tmpbuf + len, scriptname, sizeof(tmpbuf) - len);
-#else
-           /* FIXME? Convert to memcpy by storing previous strlen(scriptname)
-            */
-           (void)strcpy(tmpbuf + len, scriptname);
-#endif /* #ifdef HAS_STRLCAT */
+           (void)my_strlcpy(tmpbuf + len, scriptname, sizeof(tmpbuf) - len);
 #endif  /* !VMS */
 
 #ifdef SEARCH_EXTS
@@ -3141,7 +3153,7 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch,
 #ifdef SEARCH_EXTS
            } while (  retval < 0               /* not there */
                    && extidx>=0 && ext[extidx] /* try an extension? */
-                   && strcpy(tmpbuf+len, ext[extidx++])
+                   && my_strlcpy(tmpbuf+len, ext[extidx++], sizeof(tmpbuf) - len)
                );
 #endif
            if (retval < 0)
@@ -3440,7 +3452,8 @@ Perl_report_evil_fh(pTHX_ const GV *gv, const IO *io, I32 op)
 
     if (op == OP_phoney_OUTPUT_ONLY || op == OP_phoney_INPUT_ONLY) {
        if (ckWARN(WARN_IO)) {
-           const char * const direction = (op == OP_phoney_INPUT_ONLY) ? "in" : "out";
+           const char * const direction =
+               (const char *)((op == OP_phoney_INPUT_ONLY) ? "in" : "out");
            if (name && *name)
                Perl_warner(aTHX_ packWARN(WARN_IO),
                            "Filehandle %s opened only for %sput",
@@ -3464,15 +3477,19 @@ Perl_report_evil_fh(pTHX_ const GV *gv, const IO *io, I32 op)
        }
 
        if (ckWARN(warn_type)) {
-           const char * const pars = OP_IS_FILETEST(op) ? "" : "()";
+           const char * const pars =
+               (const char *)(OP_IS_FILETEST(op) ? "" : "()");
            const char * const func =
-               op == OP_READLINE   ? "readline"  :     /* "<HANDLE>" not nice */
-               op == OP_LEAVEWRITE ? "write" :         /* "write exit" not nice */
-               op < 0              ? "" :              /* handle phoney cases */
-               PL_op_desc[op];
-           const char * const type = OP_IS_SOCKET(op)
-                   || (gv && io && IoTYPE(io) == IoTYPE_SOCKET)
-                       ?  "socket" : "filehandle";
+               (const char *)
+               (op == OP_READLINE   ? "readline"  :    /* "<HANDLE>" not nice */
+                op == OP_LEAVEWRITE ? "write" :                /* "write exit" not nice */
+                op < 0              ? "" :              /* handle phoney cases */
+                PL_op_desc[op]);
+           const char * const type =
+               (const char *)
+               (OP_IS_SOCKET(op) ||
+                (gv && io && IoTYPE(io) == IoTYPE_SOCKET) ?
+                "socket" : "filehandle");
            if (name && *name) {
                Perl_warner(aTHX_ packWARN(warn_type),
                            "%s%s on %s %s %s", func, pars, vile, type, name);
@@ -5231,7 +5248,7 @@ Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t
        {
            const STRLEN len =
                my_snprintf(buf,
-                           PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+                           sizeof(buf),
 #  ifdef PERL_MEM_LOG_TIMESTAMP
                            "%10d.%06d: "
 # endif
@@ -5276,7 +5293,7 @@ Perl_mem_log_realloc(const UV n, const UV typesize, const char *typename, Malloc
        {
            const STRLEN len =
                my_snprintf(buf,
-                           PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+                           sizeof(buf),
 #  ifdef PERL_MEM_LOG_TIMESTAMP
                            "%10d.%06d: "
 # endif
@@ -5322,7 +5339,7 @@ Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber,
        {
            const STRLEN len =
                my_snprintf(buf,
-                           PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+                           sizeof(buf),
 #  ifdef PERL_MEM_LOG_TIMESTAMP
                            "%10d.%06d: "
 # endif
@@ -5393,7 +5410,7 @@ Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...)
 #endif
     va_end(ap);
     /* vsnprintf() shows failure with >= len, vsprintf() with < 0 */
-    if (retval < 0 || (len > 0 && retval >= len))
+    if (retval < 0 || (len > 0 && (Size_t)retval >= len))
        Perl_croak(aTHX_ "panic: my_snprintf buffer overflow");
     return retval;
 }
@@ -5430,7 +5447,7 @@ Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap
 # endif
 #endif /* #ifdef NEED_VA_COPY */
     /* vsnprintf() shows failure with >= len, vsprintf() with < 0 */
-    if (retval < 0 || (len > 0 && retval >= len))
+    if (retval < 0 || (len > 0 && (Size_t)retval >= len))
        Perl_croak(aTHX_ "panic: my_vsnprintf buffer overflow");
     return retval;
 }
@@ -5464,17 +5481,17 @@ Perl_my_clearenv(pTHX)
     (void)clearenv();
 #        elif defined(HAS_UNSETENV)
     int bsiz = 80; /* Most envvar names will be shorter than this. */
-    char *buf = (char*)safesysmalloc(bsiz * sizeof(char));
+    int bufsiz = bsiz * sizeof(char); /* sizeof(char) paranoid? */
+    char *buf = (char*)safesysmalloc(bufsiz);
     while (*environ != NULL) {
       char *e = strchr(*environ, '=');
       int l = e ? e - *environ : strlen(*environ);
       if (bsiz < l + 1) {
         (void)safesysfree(buf);
-        bsiz = l + 1;
-        buf = (char*)safesysmalloc(bsiz * sizeof(char));
+        bsiz = l + 1; /* + 1 for the \0. */
+        buf = (char*)safesysmalloc(bufsiz);
       } 
-      strncpy(buf, *environ, l);
-      *(buf + l) = '\0';
+      my_strlcpy(buf, *environ, l + 1);
       (void)unsetenv(buf);
     }
     (void)safesysfree(buf);
@@ -5530,6 +5547,39 @@ Perl_my_cxt_init(pTHX_ int *index, size_t size)
 }
 #endif
 
+#ifndef HAS_STRLCAT
+Size_t
+Perl_my_strlcat(char *dst, const char *src, Size_t size)
+{
+    Size_t used, length, copy;
+
+    used = strlen(dst);
+    length = strlen(src);
+    if (size > 0 && used < size - 1) {
+        copy = (length >= size - used) ? size - used - 1 : length;
+        memcpy(dst + used, src, copy);
+        dst[used + copy] = '\0';
+    }
+    return used + length;
+}
+#endif
+
+#ifndef HAS_STRLCPY
+Size_t
+Perl_my_strlcpy(char *dst, const char *src, Size_t size)
+{
+    Size_t length, copy;
+
+    length = strlen(src);
+    if (size > 0) {
+        copy = (length >= size) ? size - 1 : length;
+        memcpy(dst, src, copy);
+        dst[copy] = '\0';
+    }
+    return length;
+}
+#endif
+
 /*
  * Local variables:
  * c-indentation-style: bsd