This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fcntl receiving -1 from fileno, fcntl failing.
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index c4726c4..8480a5d 100644 (file)
--- a/perl.c
+++ b/perl.c
 #include "perl.h"
 #include "patchlevel.h"                        /* for local_patches */
 #include "XSUB.h"
+#include "charclass_invlists.h"
 
 #ifdef NETWARE
 #include "nwutil.h"    
 #endif
 
-#ifdef USE_KERN_PROC_PATHNAME
-#  include <sys/sysctl.h>
-#endif
-
-#ifdef USE_NSGETEXECUTABLEPATH
-#  include <mach-o/dyld.h>
-#endif
-
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
 #  ifdef I_SYSUIO
 #    include <sys/uio.h>
@@ -144,7 +137,7 @@ Perl_sys_init3(int* argc, char*** argv, char*** env)
 }
 
 void
-Perl_sys_term()
+Perl_sys_term(void)
 {
     dVAR;
     if (!PL_veto_cleanup) {
@@ -262,6 +255,12 @@ perl_construct(pTHXx)
     STATUS_ALL_SUCCESS;
 
     init_i18nl10n(1);
+
+    /* Keep LC_NUMERIC in the C locale for backwards compatibility for XS
+     * modules.  (Core operations that need the underlying locale change to it
+     * temporarily).  An explicit call to POSIX::setlocale() still will cause
+     * XS module failures, but this is how it has been for a long time [perl
+     * #121317] */
     SET_NUMERIC_STANDARD();
 
 #if defined(LOCAL_PATCH_COUNT)
@@ -388,6 +387,24 @@ perl_construct(pTHXx)
     /* Start with 1 bucket, for DFS.  It's unlikely we'll need more.  */
     HvMAX(PL_registered_mros) = 0;
 
+    PL_XPosix_ptrs[_CC_ASCII] = _new_invlist_C_array(ASCII_invlist);
+    PL_XPosix_ptrs[_CC_ALPHANUMERIC] = _new_invlist_C_array(XPosixAlnum_invlist);
+    PL_XPosix_ptrs[_CC_ALPHA] = _new_invlist_C_array(XPosixAlpha_invlist);
+    PL_XPosix_ptrs[_CC_BLANK] = _new_invlist_C_array(XPosixBlank_invlist);
+    PL_XPosix_ptrs[_CC_CASED] =  _new_invlist_C_array(Cased_invlist);
+    PL_XPosix_ptrs[_CC_CNTRL] = _new_invlist_C_array(XPosixCntrl_invlist);
+    PL_XPosix_ptrs[_CC_DIGIT] = _new_invlist_C_array(XPosixDigit_invlist);
+    PL_XPosix_ptrs[_CC_GRAPH] = _new_invlist_C_array(XPosixGraph_invlist);
+    PL_XPosix_ptrs[_CC_LOWER] = _new_invlist_C_array(XPosixLower_invlist);
+    PL_XPosix_ptrs[_CC_PRINT] = _new_invlist_C_array(XPosixPrint_invlist);
+    PL_XPosix_ptrs[_CC_PUNCT] = _new_invlist_C_array(XPosixPunct_invlist);
+    PL_XPosix_ptrs[_CC_SPACE] = _new_invlist_C_array(XPerlSpace_invlist);
+    PL_XPosix_ptrs[_CC_PSXSPC] = _new_invlist_C_array(XPosixSpace_invlist);
+    PL_XPosix_ptrs[_CC_UPPER] = _new_invlist_C_array(XPosixUpper_invlist);
+    PL_XPosix_ptrs[_CC_VERTSPACE] = _new_invlist_C_array(VertSpace_invlist);
+    PL_XPosix_ptrs[_CC_WORDCHAR] = _new_invlist_C_array(XPosixWord_invlist);
+    PL_XPosix_ptrs[_CC_XDIGIT] = _new_invlist_C_array(XPosixXDigit_invlist);
+
     ENTER;
 }
 
@@ -541,13 +558,13 @@ perl_destruct(pTHXx)
     {
        const char * const s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL");
        if (s) {
-        const int i = atoi(s);
+            const int i = atoi(s);
 #ifdef DEBUGGING
            if (destruct_level < i) destruct_level = i;
 #endif
 #ifdef PERL_TRACK_MEMPOOL
-        /* RT #114496, for perl_free */
-        PL_perl_destruct_level = i;
+            /* RT #114496, for perl_free */
+            PL_perl_destruct_level = i;
 #endif
        }
     }
@@ -660,7 +677,7 @@ perl_destruct(pTHXx)
                msg.msg_name = NULL;
                msg.msg_namelen = 0;
                msg.msg_iov = vec;
-               msg.msg_iovlen = sizeof(vec)/sizeof(vec[0]);
+               msg.msg_iovlen = C_ARRAY_LENGTH(vec);
 
                vec[0].iov_base = (void*)&target;
                vec[0].iov_len = sizeof(target);
@@ -949,16 +966,12 @@ perl_destruct(pTHXx)
     PL_initav = NULL;
 
     /* shortcuts just get cleared */
-    PL_envgv = NULL;
-    PL_incgv = NULL;
     PL_hintgv = NULL;
     PL_errgv = NULL;
-    PL_argvgv = NULL;
     PL_argvoutgv = NULL;
     PL_stdingv = NULL;
     PL_stderrgv = NULL;
     PL_last_in_gv = NULL;
-    PL_replgv = NULL;
     PL_DBsingle = NULL;
     PL_DBtrace = NULL;
     PL_DBsignal = NULL;
@@ -966,9 +979,17 @@ perl_destruct(pTHXx)
     PL_dbargs = NULL;
     PL_debstash = NULL;
 
+    SvREFCNT_dec(PL_envgv);
+    SvREFCNT_dec(PL_incgv);
+    SvREFCNT_dec(PL_argvgv);
+    SvREFCNT_dec(PL_replgv);
     SvREFCNT_dec(PL_DBgv);
     SvREFCNT_dec(PL_DBline);
     SvREFCNT_dec(PL_DBsub);
+    PL_envgv = NULL;
+    PL_incgv = NULL;
+    PL_argvgv = NULL;
+    PL_replgv = NULL;
     PL_DBgv = NULL;
     PL_DBline = NULL;
     PL_DBsub = NULL;
@@ -1017,6 +1038,7 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_utf8_tofold);
     SvREFCNT_dec(PL_utf8_idstart);
     SvREFCNT_dec(PL_utf8_idcont);
+    SvREFCNT_dec(PL_utf8_foldable);
     SvREFCNT_dec(PL_utf8_foldclosures);
     SvREFCNT_dec(PL_AboveLatin1);
     SvREFCNT_dec(PL_UpperLatin1);
@@ -1037,12 +1059,6 @@ perl_destruct(pTHXx)
     PL_NonL1NonFinalFold = NULL;
     PL_UpperLatin1       = NULL;
     for (i = 0; i < POSIX_CC_COUNT; i++) {
-        SvREFCNT_dec(PL_Posix_ptrs[i]);
-        PL_Posix_ptrs[i] = NULL;
-
-        SvREFCNT_dec(PL_L1Posix_ptrs[i]);
-        PL_L1Posix_ptrs[i] = NULL;
-
         SvREFCNT_dec(PL_XPosix_ptrs[i]);
         PL_XPosix_ptrs[i] = NULL;
     }
@@ -1353,7 +1369,7 @@ perl_free(pTHXx)
                PL_debug &= ~ DEBUG_m_FLAG;
            }
            while(aTHXx->Imemory_debug_header.next != &(aTHXx->Imemory_debug_header))
-               safesysfree(sTHX + (char *)(aTHXx->Imemory_debug_header.next));
+               safesysfree(PERL_MEMORY_DEBUG_HEADER_SIZE + (char *)(aTHXx->Imemory_debug_header.next));
            PL_debug = old_debug;
        }
     }
@@ -1418,85 +1434,6 @@ Perl_call_atexit(pTHX_ ATEXIT_t fn, void *ptr)
     ++PL_exitlistlen;
 }
 
-STATIC void
-S_set_caret_X(pTHX) {
-    dVAR;
-    GV* tmpgv = gv_fetchpvs("\030", GV_ADD|GV_NOTQUAL, SVt_PV); /* $^X */
-    if (tmpgv) {
-       SV *const caret_x = GvSV(tmpgv);
-#if defined(OS2)
-       sv_setpv(caret_x, os2_execname(aTHX));
-#else
-#  ifdef USE_KERN_PROC_PATHNAME
-       size_t size = 0;
-       int mib[4];
-       mib[0] = CTL_KERN;
-       mib[1] = KERN_PROC;
-       mib[2] = KERN_PROC_PATHNAME;
-       mib[3] = -1;
-
-       if (sysctl(mib, 4, NULL, &size, NULL, 0) == 0
-           && size > 0 && size < MAXPATHLEN * MAXPATHLEN) {
-           sv_grow(caret_x, size);
-
-           if (sysctl(mib, 4, SvPVX(caret_x), &size, NULL, 0) == 0
-               && size > 2) {
-               SvPOK_only(caret_x);
-               SvCUR_set(caret_x, size - 1);
-               SvTAINT(caret_x);
-               return;
-           }
-       }
-#  elif defined(USE_NSGETEXECUTABLEPATH)
-       char buf[1];
-       uint32_t size = sizeof(buf);
-
-       _NSGetExecutablePath(buf, &size);
-       if (size < MAXPATHLEN * MAXPATHLEN) {
-           sv_grow(caret_x, size);
-           if (_NSGetExecutablePath(SvPVX(caret_x), &size) == 0) {
-               char *const tidied = realpath(SvPVX(caret_x), NULL);
-               if (tidied) {
-                   sv_setpv(caret_x, tidied);
-                   free(tidied);
-               } else {
-                   SvPOK_only(caret_x);
-                   SvCUR_set(caret_x, size);
-               }
-               return;
-           }
-       }
-#  elif defined(HAS_PROCSELFEXE)
-       char buf[MAXPATHLEN];
-       int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
-
-       /* On Playstation2 Linux V1.0 (kernel 2.2.1) readlink(/proc/self/exe)
-          includes a spurious NUL which will cause $^X to fail in system
-          or backticks (this will prevent extensions from being built and
-          many tests from working). readlink is not meant to add a NUL.
-          Normal readlink works fine.
-       */
-       if (len > 0 && buf[len-1] == '\0') {
-           len--;
-       }
-
-       /* FreeBSD's implementation is acknowledged to be imperfect, sometimes
-          returning the text "unknown" from the readlink rather than the path
-          to the executable (or returning an error from the readlink). Any
-          valid path has a '/' in it somewhere, so use that to validate the
-          result. See http://www.freebsd.org/cgi/query-pr.cgi?pr=35703
-       */
-       if (len > 0 && memchr(buf, '/', len)) {
-           sv_setpvn(caret_x, buf, len);
-           return;
-       }
-#  endif
-       /* Fallback to this:  */
-       sv_setpv(caret_x, PL_origargv[0]);
-#endif
-    }
-}
-
 /*
 =for apidoc perl_parse
 
@@ -1559,8 +1496,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
         * --jhi */
         const char *s = NULL;
         int i;
-        const UV mask =
-          ~(UV)(PTRSIZE == 4 ? 3 : PTRSIZE == 8 ? 7 : PTRSIZE == 16 ? 15 : 0);
+        const UV mask = ~(UV)(PTRSIZE-1);
          /* Do the mask check only if the args seem like aligned. */
         const UV aligned =
           (mask < ~(UV)0) && ((PTR2UV(argv[0]) & mask) == PTR2UV(argv[0]));
@@ -1646,7 +1582,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
        init_ids();
        assert (!TAINT_get);
        TAINT;
-       S_set_caret_X(aTHX);
+       set_caret_X();
        TAINT_NOT;
        init_postdump_symbols(argc,argv,env);
        return 0;
@@ -1733,6 +1669,9 @@ S_Internals_V(pTHX_ CV *cv)
 #  ifdef NO_TAINT_SUPPORT
                             " NO_TAINT_SUPPORT"
 #  endif
+#  ifdef PERL_BOOL_AS_CHAR
+                            " PERL_BOOL_AS_CHAR"
+#  endif
 #  ifdef PERL_DISABLE_PMC
                             " PERL_DISABLE_PMC"
 #  endif
@@ -1927,9 +1866,9 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
            break;
 
        case 't':
-#if SILENT_NO_TAINT_SUPPORT
+#if defined(SILENT_NO_TAINT_SUPPORT)
             /* silently ignore */
-#elif NO_TAINT_SUPPORT
+#elif defined(NO_TAINT_SUPPORT)
             Perl_croak_nocontext("This perl was compiled without taint support. "
                        "Cowardly refusing to run with -t or -T flags");
 #else
@@ -1942,9 +1881,9 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
            s++;
            goto reswitch;
        case 'T':
-#if SILENT_NO_TAINT_SUPPORT
+#if defined(SILENT_NO_TAINT_SUPPORT)
             /* silently ignore */
-#elif NO_TAINT_SUPPORT
+#elif defined(NO_TAINT_SUPPORT)
             Perl_croak_nocontext("This perl was compiled without taint support. "
                        "Cowardly refusing to run with -t or -T flags");
 #else
@@ -2059,9 +1998,9 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
        while (isSPACE(*s))
            s++;
        if (*s == '-' && *(s+1) == 'T') {
-#if SILENT_NO_TAINT_SUPPORT
+#if defined(SILENT_NO_TAINT_SUPPORT)
             /* silently ignore */
-#elif NO_TAINT_SUPPORT
+#elif defined(NO_TAINT_SUPPORT)
             Perl_croak_nocontext("This perl was compiled without taint support. "
                        "Cowardly refusing to run with -t or -T flags");
 #else
@@ -2098,9 +2037,9 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
                    }
                }
                if (*d == 't') {
-#if SILENT_NO_TAINT_SUPPORT
+#if defined(SILENT_NO_TAINT_SUPPORT)
             /* silently ignore */
-#elif NO_TAINT_SUPPORT
+#elif defined(NO_TAINT_SUPPORT)
                     Perl_croak_nocontext("This perl was compiled without taint support. "
                                "Cowardly refusing to run with -t or -T flags");
 #else
@@ -2121,7 +2060,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     /* and for SITELIB_EXP in USE_SITECUSTOMIZE                            */
     assert (!TAINT_get);
     TAINT;
-    S_set_caret_X(aTHX);
+    set_caret_X();
     TAINT_NOT;
 
 #if defined(USE_SITECUSTOMIZE)
@@ -2525,7 +2464,7 @@ S_run_body(pTHX_ I32 oldscope)
 =for apidoc p||get_sv
 
 Returns the SV of the specified Perl scalar.  C<flags> are passed to
-C<gv_fetchpv>. If C<GV_ADD> is set and the
+C<gv_fetchpv>.  If C<GV_ADD> is set and the
 Perl variable does not exist then it will be created.  If C<flags> is zero
 and the variable does not exist then NULL is returned.
 
@@ -2552,7 +2491,7 @@ Perl_get_sv(pTHX_ const char *name, I32 flags)
 
 Returns the AV of the specified Perl global or package array with the given
 name (so it won't work on lexical variables).  C<flags> are passed 
-to C<gv_fetchpv>. If C<GV_ADD> is set and the
+to C<gv_fetchpv>.  If C<GV_ADD> is set and the
 Perl variable does not exist then it will be created.  If C<flags> is zero
 and the variable does not exist then NULL is returned.
 
@@ -2581,7 +2520,7 @@ Perl_get_av(pTHX_ const char *name, I32 flags)
 =for apidoc p||get_hv
 
 Returns the HV of the specified Perl hash.  C<flags> are passed to
-C<gv_fetchpv>. If C<GV_ADD> is set and the
+C<gv_fetchpv>.  If C<GV_ADD> is set and the
 Perl variable does not exist then it will be created.  If C<flags> is zero
 and the variable does not exist then NULL is returned.
 
@@ -2608,7 +2547,7 @@ Perl_get_hv(pTHX_ const char *name, I32 flags)
 =for apidoc p||get_cvn_flags
 
 Returns the CV of the specified Perl subroutine.  C<flags> are passed to
-C<gv_fetchpvn_flags>. If C<GV_ADD> is set and the Perl subroutine does not
+C<gv_fetchpvn_flags>.  If C<GV_ADD> is set and the Perl subroutine does not
 exist then it will be declared (which has the same effect as saying
 C<sub name;>).  If C<GV_ADD> is not set and the subroutine does not exist
 then NULL is returned.
@@ -2657,7 +2596,8 @@ Perl_get_cv(pTHX_ const char *name, I32 flags)
 =for apidoc p||call_argv
 
 Performs a callback to the specified named and package-scoped Perl subroutine 
-with C<argv> (a NULL-terminated array of strings) as arguments. See L<perlcall>.
+with C<argv> (a NULL-terminated array of strings) as arguments.  See
+L<perlcall>.
 
 Approximate Perl equivalent: C<&{"$sub_name"}(@$argv)>.
 
@@ -2880,8 +2820,8 @@ Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
 /*
 =for apidoc p||eval_sv
 
-Tells Perl to C<eval> the string in the SV. It supports the same flags
-as C<call_sv>, with the obvious exception of G_EVAL. See L<perlcall>.
+Tells Perl to C<eval> the string in the SV.  It supports the same flags
+as C<call_sv>, with the obvious exception of G_EVAL.  See L<perlcall>.
 
 =cut
 */
@@ -3040,10 +2980,8 @@ Perl_require_pv(pTHX_ const char *pv)
     PERL_ARGS_ASSERT_REQUIRE_PV;
 
     PUSHSTACKi(PERLSI_REQUIRE);
-    PUTBACK;
     sv = Perl_newSVpvf(aTHX_ "require q%c%s%c", 0, pv, 0);
     eval_sv(sv_2mortal(sv), G_DISCARD);
-    SPAGAIN;
     POPSTACK;
 }
 
@@ -3133,6 +3071,7 @@ Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
       "  q  quiet - currently only suppresses the 'EXECUTING' message\n"
       "  M  trace smart match resolution\n"
       "  B  dump suBroutine definitions, including special Blocks like BEGIN\n",
+      "  L  trace some locale setting information--for Perl core development\n",
       NULL
     };
     int i = 0;
@@ -3141,7 +3080,7 @@ Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
 
     if (isALPHA(**s)) {
        /* if adding extra options, remember to update DEBUG_MASK */
-       static const char debopts[] = "psltocPmfrxuUHXDSTRJvCAqMB";
+       static const char debopts[] = "psltocPmfrxuUHXDSTRJvCAqMBL";
 
        for (; isWORDCHAR(**s); (*s)++) {
            const char * const d = strchr(debopts,**s);
@@ -3447,9 +3386,9 @@ Perl_moreswitches(pTHX_ const char *s)
        return s;
     case 't':
     case 'T':
-#if SILENT_NO_TAINT_SUPPORT
+#if defined(SILENT_NO_TAINT_SUPPORT)
             /* silently ignore */
-#elif NO_TAINT_SUPPORT
+#elif defined(NO_TAINT_SUPPORT)
         Perl_croak_nocontext("This perl was compiled without taint support. "
                    "Cowardly refusing to run with -t or -T flags");
 #else
@@ -3526,30 +3465,35 @@ STATIC void
 S_minus_v(pTHX)
 {
        PerlIO * PIO_stdout;
-       if (!sv_derived_from(PL_patchlevel, "version"))
-           upg_version(PL_patchlevel, TRUE);
        {
-           SV* level= vstringify(PL_patchlevel);
+           const char * const level_str = "v" PERL_VERSION_STRING;
+           const STRLEN level_len = sizeof("v" PERL_VERSION_STRING)-1;
 #ifdef PERL_PATCHNUM
+           SV* level;
 #  ifdef PERL_GIT_UNCOMMITTED_CHANGES
-           SV *num = newSVpvs(PERL_PATCHNUM "*");
+           static const char num [] = PERL_PATCHNUM "*";
 #  else
-           SV *num = newSVpvs(PERL_PATCHNUM);
+           static const char num [] = PERL_PATCHNUM;
 #  endif
            {
-               STRLEN level_len, num_len;
-               char * level_str, * num_str;
-               num_str = SvPV(num, num_len);
-               level_str = SvPV(level, level_len);
-               if (num_len>=level_len && strnEQ(num_str,level_str,level_len)) {
-                   SvREFCNT_dec(level);
-                   level= num;
+               const STRLEN num_len = sizeof(num)-1;
+               /* A very advanced compiler would fold away the strnEQ
+                  and this whole conditional, but most (all?) won't do it.
+                  SV level could also be replaced by with preprocessor
+                  catenation.
+               */
+               if (num_len >= level_len && strnEQ(num,level_str,level_len)) {
+                   /* per 46807d8e80, PERL_PATCHNUM is outside of the control
+                      of the interp so it might contain format characters
+                   */
+                   level = newSVpvn(num, num_len);
                } else {
-                   Perl_sv_catpvf(aTHX_ level, " (%"SVf")", num);
-                   SvREFCNT_dec(num);
+                   level = Perl_newSVpvf_nocontext("%s (%s)", level_str, num);
                }
            }
- #endif
+#else
+       SV* level = newSVpvn(level_str, level_len);
+#endif /* #ifdef PERL_PATCHNUM */
        PIO_stdout =  PerlIO_stdout();
            PerlIO_printf(PIO_stdout,
                "\nThis is perl "       STRINGIFY(PERL_REVISION)
@@ -3557,7 +3501,7 @@ S_minus_v(pTHX)
                ", subversion "         STRINGIFY(PERL_SUBVERSION)
                " (%"SVf") built for "  ARCHNAME, level
                );
-           SvREFCNT_dec(level);
+           SvREFCNT_dec_NN(level);
        }
 #if defined(LOCAL_PATCH_COUNT)
        if (LOCAL_PATCH_COUNT > 0)
@@ -3569,7 +3513,7 @@ S_minus_v(pTHX)
 #endif
 
        PerlIO_printf(PIO_stdout,
-                     "\n\nCopyright 1987-2013, Larry Wall\n");
+                     "\n\nCopyright 1987-2014, Larry Wall\n");
 #ifdef MSDOS
        PerlIO_printf(PIO_stdout,
                      "\nMS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n");
@@ -3714,13 +3658,15 @@ S_init_main_stash(pTHX)
     SvREFCNT_inc_simple_void(PL_incgv); /* Don't allow it to be freed */
     GvMULTI_on(PL_incgv);
     PL_hintgv = gv_fetchpvs("\010", GV_ADD|GV_NOTQUAL, SVt_PV); /* ^H */
+    SvREFCNT_inc_simple_void(PL_hintgv);
     GvMULTI_on(PL_hintgv);
     PL_defgv = gv_fetchpvs("_", GV_ADD|GV_NOTQUAL, SVt_PVAV);
     SvREFCNT_inc_simple_void(PL_defgv);
-    PL_errgv = gv_HVadd(gv_fetchpvs("@", GV_ADD|GV_NOTQUAL, SVt_PV));
+    PL_errgv = gv_fetchpvs("@", GV_ADD|GV_NOTQUAL, SVt_PV);
     SvREFCNT_inc_simple_void(PL_errgv);
     GvMULTI_on(PL_errgv);
     PL_replgv = gv_fetchpvs("\022", GV_ADD|GV_NOTQUAL, SVt_PV); /* ^R */
+    SvREFCNT_inc_simple_void(PL_replgv);
     GvMULTI_on(PL_replgv);
     (void)Perl_form(aTHX_ "%240s",""); /* Preallocate temp - for immediate signals. */
 #ifdef PERL_DONT_CREATE_GVSV
@@ -3744,6 +3690,7 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
     PerlIO *rsfp = NULL;
     dVAR;
     Stat_t tmpstatbuf;
+    int fd;
 
     PERL_ARGS_ASSERT_OPEN_SCRIPT;
 
@@ -3816,7 +3763,9 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
        const char * const err = "Failed to create a fake bit bucket";
        if (strEQ(scriptname, BIT_BUCKET)) {
 #ifdef HAS_MKSTEMP /* Hopefully mkstemp() is safe here. */
+            int old_umask = umask(0600);
            int tmpfd = mkstemp(tmpname);
+            umask(old_umask);
            if (tmpfd > -1) {
                scriptname = tmpname;
                close(tmpfd);
@@ -3849,13 +3798,20 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
            Perl_croak(aTHX_ "Can't open perl script \"%s\": %s\n",
                    CopFILE(PL_curcop), Strerror(errno));
     }
+    fd = PerlIO_fileno(rsfp);
 #if defined(HAS_FCNTL) && defined(F_SETFD)
-    /* ensure close-on-exec */
-    fcntl(PerlIO_fileno(rsfp), F_SETFD, 1);
+    if (fd >= 0) {
+        /* ensure close-on-exec */
+        if (fcntl(fd, F_SETFD, 1) < 0) {
+            Perl_croak(aTHX_ "Can't open perl script \"%s\": %s\n",
+                       CopFILE(PL_curcop), Strerror(errno));
+        }
+    }
 #endif
 
-    if (PerlLIO_fstat(PerlIO_fileno(rsfp), &tmpstatbuf) >= 0
-        && S_ISDIR(tmpstatbuf.st_mode))
+    if (fd < 0 ||
+        (PerlLIO_fstat(fd, &tmpstatbuf) >= 0
+         && S_ISDIR(tmpstatbuf.st_mode)))
         Perl_croak(aTHX_ "Can't open perl script \"%s\": %s\n",
             CopFILE(PL_curcop),
             Strerror(EISDIR));
@@ -3886,12 +3842,18 @@ S_validate_suid(pTHX_ PerlIO *rsfp)
 
     if (my_euid != my_uid || my_egid != my_gid) {      /* (suidperl doesn't exist, in fact) */
        dVAR;
-
-       PerlLIO_fstat(PerlIO_fileno(rsfp),&PL_statbuf); /* may be either wrapped or real suid */
-       if ((my_euid != my_uid && my_euid == PL_statbuf.st_uid && PL_statbuf.st_mode & S_ISUID)
-           ||
-           (my_egid != my_gid && my_egid == PL_statbuf.st_gid && PL_statbuf.st_mode & S_ISGID)
-          )
+        int fd = PerlIO_fileno(rsfp);
+        if (fd < 0) {
+            Perl_croak(aTHX_ "Illegal suidscript");
+        } else {
+            if (PerlLIO_fstat(fd, &PL_statbuf) < 0) {  /* may be either wrapped or real suid */
+                Perl_croak(aTHX_ "Illegal suidscript");
+            }
+        }
+        if ((my_euid != my_uid && my_euid == PL_statbuf.st_uid && PL_statbuf.st_mode & S_ISUID)
+            ||
+            (my_egid != my_gid && my_egid == PL_statbuf.st_gid && PL_statbuf.st_mode & S_ISGID)
+            )
            if (!PL_do_undump)
                Perl_croak(aTHX_ "YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
 FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
@@ -3935,7 +3897,7 @@ S_init_ids(pTHX)
 {
     /* no need to do anything here any more if we don't
      * do tainting. */
-#if !NO_TAINT_SUPPORT
+#ifndef NO_TAINT_SUPPORT
     dVAR;
     const Uid_t my_uid = PerlProc_getuid();
     const Uid_t my_euid = PerlProc_geteuid();
@@ -4071,8 +4033,10 @@ Perl_init_debugger(pTHX)
 
 #ifndef STRESS_REALLOC
 #define REASONABLE(size) (size)
+#define REASONABLE_but_at_least(size,min) (size)
 #else
 #define REASONABLE(size) (1) /* unreasonable */
+#define REASONABLE_but_at_least(size,min) (min)
 #endif
 
 void
@@ -4108,9 +4072,9 @@ Perl_init_stacks(pTHX)
     PL_scopestack_ix = 0;
     PL_scopestack_max = REASONABLE(32);
 
-    Newx(PL_savestack,REASONABLE(128),ANY);
+    Newx(PL_savestack,REASONABLE_but_at_least(128,SS_MAXPUSH),ANY);
     PL_savestack_ix = 0;
-    PL_savestack_max = REASONABLE(128);
+    PL_savestack_max = REASONABLE_but_at_least(128,SS_MAXPUSH);
 }
 
 #undef REASONABLE
@@ -4259,6 +4223,7 @@ Perl_init_argv_symbols(pTHX_ int argc, char **argv)
        }
     }
     if ((PL_argvgv = gv_fetchpvs("ARGV", GV_ADD|GV_NOTQUAL, SVt_PVAV))) {
+       SvREFCNT_inc_simple_void_NN(PL_argvgv);
        GvMULTI_on(PL_argvgv);
        av_clear(GvAVn(PL_argvgv));
        for (; argc > 0; argc--,argv++) {
@@ -4303,6 +4268,7 @@ S_init_postdump_symbols(pTHX_ int argc, char **argv, char **env)
     if ((PL_envgv = gv_fetchpvs("ENV", GV_ADD|GV_NOTQUAL, SVt_PVHV))) {
        HV *hv;
        bool env_is_not_environ;
+       SvREFCNT_inc_simple_void_NN(PL_envgv);
        GvMULTI_on(PL_envgv);
        hv = GvHVn(PL_envgv);
        hv_magic(hv, NULL, PERL_MAGIC_env);
@@ -4603,7 +4569,7 @@ S_mayberelocate(pTHX_ const char *const dir, STRLEN len, U32 flags)
 
        if ((unix = tounixspec_ts(SvPV(libdir,len),NULL)) != NULL) {
            len = strlen(unix);
-           while (unix[len-1] == '/') len--;  /* Cosmetic */
+           while (len > 1 && unix[len-1] == '/') len--;  /* Cosmetic */
            sv_usepvn(libdir,unix,len);
        }
        else
@@ -4801,7 +4767,7 @@ S_incpush(pTHX_ const char *const dir, STRLEN len, U32 flags)
 #ifdef PERL_IS_MINIPERL
            const Size_t extra = 0;
 #else
-           Size_t extra = av_len(av) + 1;
+           Size_t extra = av_tindex(av) + 1;
 #endif
            av_unshift(inc, extra + push_basedir);
            if (push_basedir)
@@ -4888,7 +4854,7 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
 
     PERL_ARGS_ASSERT_CALL_LIST;
 
-    while (av_len(paramList) >= 0) {
+    while (av_tindex(paramList) >= 0) {
        cv = MUTABLE_CV(av_shift(paramList));
        if (PL_savebegin) {
            if (paramList == PL_beginav) {
@@ -4976,7 +4942,7 @@ Perl_my_exit(pTHX_ U32 status)
     }
     if (PL_exit_flags & PERL_EXIT_WARN) {
        PL_exit_flags |= PERL_EXIT_ABORT; /* Protect against reentrant calls */
-       Perl_warn(aTHX_ "Unexpected exit %u", status);
+       Perl_warn(aTHX_ "Unexpected exit %lu", (unsigned long)status);
        PL_exit_flags &= ~PERL_EXIT_ABORT;
     }
     switch (status) {
@@ -5081,7 +5047,7 @@ Perl_my_failure_exit(pTHX)
     }
     if (PL_exit_flags & PERL_EXIT_WARN) {
        PL_exit_flags |= PERL_EXIT_ABORT; /* Protect against reentrant calls */
-       Perl_warn(aTHX_ "Unexpected exit failure %u", PL_statusvalue);
+       Perl_warn(aTHX_ "Unexpected exit failure %ld", (long)PL_statusvalue);
        PL_exit_flags &= ~PERL_EXIT_ABORT;
     }
     my_exit_jump();