--- ./sv.c-pre	Thu Mar 13 13:22:36 2003
+++ ./sv.c	Fri Mar 28 16:49:26 2003
@@ -10402,6 +10402,8 @@ perl_clone_using(PerlInterpreter *proto_
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
+    PL_savestack_ix = 0;
+    PL_savestack_max = -1;
     PL_retstack = 0;
     PL_sig_pending = 0;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
@@ -10433,6 +10435,8 @@ perl_clone_using(PerlInterpreter *proto_
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
+    PL_savestack_ix = 0;
+    PL_savestack_max = -1;
     PL_retstack = 0;
     PL_sig_pending = 0;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
--- ./malloc.c-pre	Sun Nov  3 22:34:38 2002
+++ ./malloc.c	Sat Mar 29 20:18:52 2003
@@ -27,9 +27,12 @@
   options take a precise value, while the others are just boolean.
   The boolean ones are listed first.
 
+    # Read configuration settings from malloc_cfg.h
+    HAVE_MALLOC_CFG_H		undef
+
     # Enable code for an emergency memory pool in $^M.  See perlvar.pod
     # for a description of $^M.
-    PERL_EMERGENCY_SBRK		(!PLAIN_MALLOC && PERL_CORE)
+    PERL_EMERGENCY_SBRK		(!PLAIN_MALLOC && (PERL_CORE || !NO_MALLOC_DYNAMIC_CFG))
 
     # Enable code for printing memory statistics.
     DEBUGGING_MSTATS		(!PLAIN_MALLOC && PERL_CORE)
@@ -78,6 +81,22 @@
     # pessimization, error reporting optimization
     RCHECK			(DEBUGGING && !NO_RCHECK)
 
+    # Do not overwrite uninit areas with DEBUGGING.  Speed
+    # optimization, error reporting pessimization
+    NO_MFILL			undef
+
+    # Overwrite uninit areas with DEBUGGING.  Speed
+    # pessimization, error reporting optimization
+    MALLOC_FILL			(DEBUGGING && !NO_RCHECK && !NO_MFILL)
+
+    # Do not check overwritten uninit areas with DEBUGGING.  Speed
+    # optimization, error reporting pessimization
+    NO_FILL_CHECK		undef
+
+    # Check overwritten uninit areas with DEBUGGING.  Speed
+    # pessimization, error reporting optimization
+    MALLOC_FILL_CHECK		(DEBUGGING && !NO_RCHECK && !NO_FILL_CHECK)
+
     # Failed allocations bigger than this size croak (if
     # PERL_EMERGENCY_SBRK is enabled) without touching $^M.  See
     # perlvar.pod for a description of $^M.
@@ -98,6 +117,9 @@
     # Round up sbrk()s to multiples of this percent of footprint.
     MIN_SBRK_FRAC 		3
 
+    # Round up sbrk()s to multiples of this multiple of 1/1000 of footprint.
+    MIN_SBRK_FRAC1000 		(10 * MIN_SBRK_FRAC)
+
     # Add this much memory to big powers of two to get the bucket size.
     PERL_PAGESIZE 		4096
 
@@ -114,6 +136,12 @@
     # define this to disable 12-byte bucket (will increase memory footprint)
     STRICT_ALIGNMENT		undef
 
+    # Do not allow configuration of runtime options at runtime
+    NO_MALLOC_DYNAMIC_CFG	undef
+
+    # Do not allow configuration of runtime options via $ENV{PERL_MALLOC_OPT}
+    NO_PERL_MALLOC_ENV		undef
+
   This implementation assumes that calling PerlIO_printf() does not
   result in any memory allocation calls (used during a panic).
 
@@ -168,6 +196,10 @@
      MUTEX_UNLOCK(l)			void
  */
 
+#ifdef HAVE_MALLOC_CFG_H
+#  include "malloc_cfg.h"
+#endif
+
 #ifndef NO_FANCY_MALLOC
 #  ifndef SMALL_BUCKET_VIA_TABLE
 #    define SMALL_BUCKET_VIA_TABLE
@@ -187,7 +219,7 @@
 #  ifndef TWO_POT_OPTIMIZE
 #    define TWO_POT_OPTIMIZE
 #  endif 
-#  if defined(PERL_CORE) && !defined(PERL_EMERGENCY_SBRK)
+#  if (defined(PERL_CORE) || !defined(NO_MALLOC_DYNAMIC_CFG)) && !defined(PERL_EMERGENCY_SBRK)
 #    define PERL_EMERGENCY_SBRK
 #  endif 
 #  if defined(PERL_CORE) && !defined(DEBUGGING_MSTATS)
@@ -211,6 +243,12 @@
 #  if defined(DEBUGGING) && !defined(NO_RCHECK)
 #    define RCHECK
 #  endif
+#  if defined(DEBUGGING) && !defined(NO_RCHECK) && !defined(NO_MFILL) && !defined(MALLOC_FILL)
+#    define MALLOC_FILL
+#  endif
+#  if defined(DEBUGGING) && !defined(NO_RCHECK) && !defined(NO_FILL_CHECK) && !defined(MALLOC_FILL_CHECK)
+#    define MALLOC_FILL_CHECK
+#  endif
 #  if defined(RCHECK) && defined(IGNORE_SMALL_BAD_FREE)
 #    undef IGNORE_SMALL_BAD_FREE
 #  endif 
@@ -251,6 +289,11 @@
 #    define croak2	croak
 #    define warn2	warn
 #  endif
+#  if defined(USE_5005THREADS) || defined(USE_ITHREADS)
+#     define PERL_MAYBE_ALIVE	PL_thr_key
+#  else
+#     define PERL_MAYBE_ALIVE	1
+#  endif
 #else
 #  ifdef PERL_FOR_X2P
 #    include "../EXTERN.h"
@@ -317,6 +360,7 @@
 #  ifndef PERL_GET_INTERP
 #     define PERL_GET_INTERP	PL_curinterp
 #  endif
+#  define PERL_MAYBE_ALIVE	1
 #  ifndef Perl_malloc
 #     define Perl_malloc malloc
 #  endif
@@ -358,7 +402,7 @@
 #  undef DEBUG_m
 #  define DEBUG_m(a) 							\
     STMT_START {							\
-	if (PERL_GET_INTERP) {						\
+	if (PERL_MAYBE_ALIVE && PERL_GET_THX) {						\
 	    dTHX;							\
 	    if (DEBUG_m_TEST) {						\
 		PL_debug &= ~DEBUG_m_FLAG;				\
@@ -480,7 +524,7 @@ union	overhead {
 		u_char	ovu_index;	/* bucket # */
 		u_char	ovu_magic;	/* magic number */
 #ifdef RCHECK
-		u_short	ovu_size;	/* actual block size */
+		u_short	ovu_size;	/* block size (requested + overhead - 1) */
 		u_int	ovu_rmagic;	/* range magic number */
 #endif
 	} ovu;
@@ -497,7 +541,7 @@ union	overhead {
 #ifdef RCHECK
 #  define	RSLOP		sizeof (u_int)
 #  ifdef TWO_POT_OPTIMIZE
-#    define MAX_SHORT_BUCKET (12 * BUCKETS_PER_POW2)
+#    define MAX_SHORT_BUCKET (12 * BUCKETS_PER_POW2) /* size-1 fits in short */
 #  else
 #    define MAX_SHORT_BUCKET (13 * BUCKETS_PER_POW2)
 #  endif 
@@ -908,6 +952,87 @@ extern	Malloc_t sbrk(int);
 # endif
 #endif
 
+#ifndef MIN_SBRK_FRAC1000	/* Backward compatibility */
+#  define MIN_SBRK_FRAC1000	(MIN_SBRK_FRAC * 10)
+#endif
+
+#ifndef NO_MALLOC_DYNAMIC_CFG
+#define PERL_MALLOC_OPT_CHARS "FMfAPGdac"
+enum {
+  MallocCfg_FIRST_SBRK,
+  MallocCfg_MIN_SBRK,
+  MallocCfg_MIN_SBRK_FRAC1000,
+  MallocCfg_SBRK_ALLOW_FAILURES,
+  MallocCfg_SBRK_FAILURE_PRICE,
+  MallocCfg_sbrk_goodness,
+
+  MallocCfg_filldead,
+  MallocCfg_fillalive,
+  MallocCfg_fillcheck,
+
+  MallocCfg_emergency_buffer,
+  MallocCfg_emergency_buffer_size,
+  MallocCfg_emergency_buffer_last_req,
+
+  MallocCfg_emergency_buffer_prepared,
+  MallocCfg_emergency_buffer_prepared_size,
+
+  MallocCfg_last
+};
+
+IV MallocCfg[MallocCfg_last] = {
+  FIRST_SBRK,
+  MIN_SBRK,
+  MIN_SBRK_FRAC,
+  SBRK_ALLOW_FAILURES,
+  SBRK_FAILURE_PRICE,
+  SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE,	/* sbrk_goodness */
+  1,			/* FILL_DEAD */
+  1,			/* FILL_ALIVE */
+  1,			/* FILL_CHECK */
+  0,			/* MallocCfg_emergency_buffer */
+  0,			/* MallocCfg_emergency_buffer_prepared */
+  0,			/* MallocCfg_emergency_buffer_size */
+  0,			/* MallocCfg_emergency_buffer_prepared_size */
+  0			/* MallocCfg_emergency_buffer_last_req */
+};
+extern IV *MallocCfg_ptr;
+IV *MallocCfg_ptr = MallocCfg;
+
+#  undef MIN_SBRK
+#  undef FIRST_SBRK
+#  undef MIN_SBRK_FRAC1000
+#  undef SBRK_ALLOW_FAILURES
+#  undef SBRK_FAILURE_PRICE
+
+#  define MIN_SBRK		MallocCfg[MallocCfg_MIN_SBRK]
+#  define FIRST_SBRK		MallocCfg[MallocCfg_FIRST_SBRK]
+#  define MIN_SBRK_FRAC1000	MallocCfg[MallocCfg_MIN_SBRK_FRAC1000]
+#  define SBRK_ALLOW_FAILURES	MallocCfg[MallocCfg_SBRK_ALLOW_FAILURES]
+#  define SBRK_FAILURE_PRICE	MallocCfg[MallocCfg_SBRK_FAILURE_PRICE]
+
+#  define sbrk_goodness		MallocCfg[MallocCfg_sbrk_goodness]
+
+#  define emergency_buffer	((char*)MallocCfg[MallocCfg_emergency_buffer])
+#  define emergency_buffer_size	MallocCfg[MallocCfg_emergency_buffer_size]
+#  define emergency_buffer_last_req	MallocCfg[MallocCfg_emergency_buffer_last_req]
+
+#  define FILL_DEAD		MallocCfg[MallocCfg_filldead]
+#  define FILL_ALIVE		MallocCfg[MallocCfg_fillalive]
+#  define FILL_CHECK_		MallocCfg[MallocCfg_fillcheck]
+#  define FILL_CHECK		(FILL_DEAD && FILL_CHECK_)
+
+#else	/* defined(NO_MALLOC_DYNAMIC_CFG) */
+
+#  define FILL_DEAD	1
+#  define FILL_ALIVE	1
+#  define FILL_CHECK	1
+static int sbrk_goodness = SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE;
+
+#  define NO_PERL_MALLOC_ENV
+
+#endif
+
 #ifdef DEBUGGING_MSTATS
 /*
  * nmalloc[i] is the difference between the number of mallocs and frees
@@ -928,21 +1053,99 @@ static	u_int goodsbrk;
 #    define BIG_SIZE (1<<16)		/* 64K */
 #  endif
 
+#  ifdef NO_MALLOC_DYNAMIC_CFG
 static char *emergency_buffer;
 static MEM_SIZE emergency_buffer_size;
-static MEM_SIZE no_mem;	/* 0 if the last request for more memory succeeded.
-			   Otherwise the size of the failing request. */
+	/* 0 if the last request for more memory succeeded.
+	   Otherwise the size of the failing request. */
+static MEM_SIZE emergency_buffer_last_req;
+#  endif
+
+#  ifndef emergency_sbrk_croak
+#    define emergency_sbrk_croak	croak2
+#  endif
+
+#  ifdef PERL_CORE
+static char *
+perl_get_emergency_buffer(IV *size)
+{
+    dTHX;
+    /* First offense, give a possibility to recover by dieing. */
+    /* No malloc involved here: */
+    GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
+    SV *sv;
+    char *pv;
+    STRLEN n_a;
+
+    if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
+    if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
+        || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD))
+        return NULL;		/* Now die die die... */
+    /* Got it, now detach SvPV: */
+    pv = SvPV(sv, n_a);
+    /* Check alignment: */
+    if ((PTR2UV(pv) - sizeof(union overhead)) & (NEEDED_ALIGNMENT - 1)) {
+        PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
+        return NULL;		/* die die die */
+    }
+
+    SvPOK_off(sv);
+    SvPVX(sv) = Nullch;
+    SvCUR(sv) = SvLEN(sv) = 0;
+    *size = malloced_size(pv) + M_OVERHEAD;
+    return pv - sizeof(union overhead);
+}
+#    define PERL_GET_EMERGENCY_BUFFER(p)	perl_get_emergency_buffer(p)
+#  else
+#    define PERL_GET_EMERGENCY_BUFFER(p)	NULL
+#  endif
+
+#  ifndef NO_MALLOC_DYNAMIC_CFG
+static char *
+get_emergency_buffer(IV *size)
+{
+    char *pv = (char*)MallocCfg[MallocCfg_emergency_buffer_prepared];
+
+    *size = MallocCfg[MallocCfg_emergency_buffer_prepared_size];
+    MallocCfg[MallocCfg_emergency_buffer_prepared] = 0;
+    MallocCfg[MallocCfg_emergency_buffer_prepared_size] = 0;
+    return pv;
+}
+
+/* Returns 0 on success, -1 on bad alignment, -2 if not implemented */
+int
+set_emergency_buffer(char *b, IV size)
+{
+    if (PTR2UV(b) & (NEEDED_ALIGNMENT - 1))
+	return -1;
+    if (MallocCfg[MallocCfg_emergency_buffer_prepared_size])
+	add_to_chain((void*)MallocCfg[MallocCfg_emergency_buffer_prepared],
+		     MallocCfg[MallocCfg_emergency_buffer_prepared_size], 0);
+    MallocCfg[MallocCfg_emergency_buffer_prepared] = PTR2UV(b);
+    MallocCfg[MallocCfg_emergency_buffer_prepared_size] = size;
+    return 0;
+}
+#    define GET_EMERGENCY_BUFFER(p)	get_emergency_buffer(p)
+#  else		/* NO_MALLOC_DYNAMIC_CFG */
+#    define GET_EMERGENCY_BUFFER(p)	NULL
+int
+set_emergency_buffer(char *b, IV size)
+{
+    return -1;
+}
+#  endif
 
 static Malloc_t
 emergency_sbrk(MEM_SIZE size)
 {
     MEM_SIZE rsize = (((size - 1)>>LOG_OF_MIN_ARENA) + 1)<<LOG_OF_MIN_ARENA;
 
-    if (size >= BIG_SIZE && (!no_mem || (size < no_mem))) {
+    if (size >= BIG_SIZE
+	&& (!emergency_buffer_last_req || (size < emergency_buffer_last_req))) {
 	/* Give the possibility to recover, but avoid an infinite cycle. */
 	MALLOC_UNLOCK;
-	no_mem = size;
-	croak2("Out of memory during \"large\" request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
+	emergency_buffer_last_req = size;
+	emergency_sbrk_croak("Out of memory during \"large\" request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
     }
 
     if (emergency_buffer_size >= rsize) {
@@ -952,14 +1155,11 @@ emergency_sbrk(MEM_SIZE size)
 	emergency_buffer += rsize;
 	return old;
     } else {		
-	dTHX;
 	/* First offense, give a possibility to recover by dieing. */
 	/* No malloc involved here: */
-	GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
-	SV *sv;
-	char *pv;
+	IV Size;
+	char *pv = GET_EMERGENCY_BUFFER(&Size);
 	int have = 0;
-	STRLEN n_a;
 
 	if (emergency_buffer_size) {
 	    add_to_chain(emergency_buffer, emergency_buffer_size, 0);
@@ -967,30 +1167,29 @@ emergency_sbrk(MEM_SIZE size)
 	    emergency_buffer = Nullch;
 	    have = 1;
 	}
-	if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
-	if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
-	    || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD)) {
+
+	if (!pv)
+	    pv = PERL_GET_EMERGENCY_BUFFER(&Size);
+	if (!pv) {
 	    if (have)
 		goto do_croak;
 	    return (char *)-1;		/* Now die die die... */
 	}
-	/* Got it, now detach SvPV: */
-	pv = SvPV(sv, n_a);
+
 	/* Check alignment: */
-	if ((PTR2UV(pv) - sizeof(union overhead)) & (NEEDED_ALIGNMENT - 1)) {
+	if (PTR2UV(pv) & (NEEDED_ALIGNMENT - 1)) {
+	    dTHX;
+
 	    PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
 	    return (char *)-1;		/* die die die */
 	}
 
-	emergency_buffer = pv - sizeof(union overhead);
-	emergency_buffer_size = malloced_size(pv) + M_OVERHEAD;
-	SvPOK_off(sv);
-	SvPVX(sv) = Nullch;
-	SvCUR(sv) = SvLEN(sv) = 0;
+	emergency_buffer = pv;
+	emergency_buffer_size = Size;
     }
   do_croak:
     MALLOC_UNLOCK;
-    croak("Out of memory during request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
+    emergency_sbrk_croak("Out of memory during request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
     /* NOTREACHED */
     return Nullch;
 }
@@ -1000,20 +1199,115 @@ emergency_sbrk(MEM_SIZE size)
 # endif
 #endif /* ifdef PERL_CORE */
 
+static void
+write2(char *mess)
+{
+  write(2, mess, strlen(mess));
+}
+
 #ifdef DEBUGGING
 #undef ASSERT
 #define	ASSERT(p,diag)   if (!(p)) botch(diag,STRINGIFY(p));  else
 static void
 botch(char *diag, char *s)
 {
+    if (!(PERL_MAYBE_ALIVE && PERL_GET_THX))
+	goto do_write;
+    else {
 	dTHX;
-	PerlIO_printf(PerlIO_stderr(), "assertion botched (%s?): %s\n", diag, s);
+
+	if (PerlIO_printf(PerlIO_stderr(),
+			  "assertion botched (%s?): %s\n", diag, s) != 0) {
+	 do_write:		/* Can be initializing interpreter */
+	    write2("assertion botched (");
+	    write2(diag);
+	    write2("?): ");
+	    write2(s);
+	    write2("\n");
+	}
 	PerlProc_abort();
+    }
 }
 #else
 #define	ASSERT(p, diag)
 #endif
 
+#ifdef MALLOC_FILL
+/* Fill should be long enough to cover long */
+static void
+fill_pat_4bytes(unsigned char *s, size_t nbytes, const unsigned char *fill)
+{
+    unsigned char *e = s + nbytes;
+    long *lp;
+    long lfill = *(long*)fill;
+
+    if (PTR2UV(s) & (sizeof(long)-1)) {		/* Align the pattern */
+	int shift = sizeof(long) - (PTR2UV(s) & (sizeof(long)-1));
+	unsigned const char *f = fill + sizeof(long) - shift;
+	unsigned char *e1 = s + shift;
+
+	while (s < e1)
+	    *s++ = *f++;
+    }
+    lp = (long*)s;
+    while ((unsigned char*)(lp + 1) <= e)
+	*lp++ = lfill;
+    s = (unsigned char*)lp;
+    while (s < e)
+	*s++ = *fill++;
+}
+/* Just malloc()ed */
+static const unsigned char fill_feedadad[] =
+ {0xFE, 0xED, 0xAD, 0xAD, 0xFE, 0xED, 0xAD, 0xAD,
+  0xFE, 0xED, 0xAD, 0xAD, 0xFE, 0xED, 0xAD, 0xAD};
+/* Just free()ed */
+static const unsigned char fill_deadbeef[] =
+ {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
+  0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
+#  define FILL_DEADBEEF(s, n)	\
+	(void)(FILL_DEAD?  (fill_pat_4bytes((s), (n), fill_deadbeef), 0) : 0)
+#  define FILL_FEEDADAD(s, n)	\
+	(void)(FILL_ALIVE? (fill_pat_4bytes((s), (n), fill_feedadad), 0) : 0)
+#else
+#  define FILL_DEADBEEF(s, n)	((void)0)
+#  define FILL_FEEDADAD(s, n)	((void)0)
+#  undef MALLOC_FILL_CHECK
+#endif
+
+#ifdef MALLOC_FILL_CHECK
+static int
+cmp_pat_4bytes(unsigned char *s, size_t nbytes, const unsigned char *fill)
+{
+    unsigned char *e = s + nbytes;
+    long *lp;
+    long lfill = *(long*)fill;
+
+    if (PTR2UV(s) & (sizeof(long)-1)) {		/* Align the pattern */
+	int shift = sizeof(long) - (PTR2UV(s) & (sizeof(long)-1));
+	unsigned const char *f = fill + sizeof(long) - shift;
+	unsigned char *e1 = s + shift;
+
+	while (s < e1)
+	    if (*s++ != *f++)
+		return 1;
+    }
+    lp = (long*)s;
+    while ((unsigned char*)(lp + 1) <= e)
+	if (*lp++ != lfill)
+	    return 1;
+    s = (unsigned char*)lp;
+    while (s < e)
+	if (*s++ != *fill++)
+	    return 1;
+    return 0;
+}
+#  define FILLCHECK_DEADBEEF(s, n)					\
+	ASSERT(!FILL_CHECK || !cmp_pat_4bytes(s, n, fill_deadbeef),	\
+	       "free()ed/realloc()ed-away memory was overwritten")
+#else
+#  define FILLCHECK_DEADBEEF(s, n)	((void)0)
+#endif
+
 Malloc_t
 Perl_malloc(register size_t nbytes)
 {
@@ -1135,6 +1429,9 @@ Perl_malloc(register size_t nbytes)
 			      PTR2UV((Malloc_t)(p + CHUNK_SHIFT)), (unsigned long)(PL_an++),
 			      (long)size));
 
+	FILLCHECK_DEADBEEF((unsigned char*)(p + CHUNK_SHIFT),
+			   BUCKET_SIZE_REAL(bucket));
+
 #ifdef IGNORE_SMALL_BAD_FREE
 	if (bucket >= FIRST_BUCKET_WITH_CHECK)
 #endif 
@@ -1161,6 +1458,7 @@ Perl_malloc(register size_t nbytes)
 	    nbytes = (nbytes + 3) &~ 3; 
 	    *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
 	}
+	FILL_FEEDADAD((unsigned char *)(p + CHUNK_SHIFT), size);
 #endif
   	return ((Malloc_t)(p + CHUNK_SHIFT));
 }
@@ -1168,7 +1466,6 @@ Perl_malloc(register size_t nbytes)
 static char *last_sbrk_top;
 static char *last_op;			/* This arena can be easily extended. */
 static MEM_SIZE sbrked_remains;
-static int sbrk_good = SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE;
 
 #ifdef DEBUGGING_MSTATS
 static int sbrks;
@@ -1274,13 +1571,13 @@ getpages(MEM_SIZE needed, int *nblksp, i
     union overhead *ovp;
     MEM_SIZE slack = 0;
 
-    if (sbrk_good > 0) {
+    if (sbrk_goodness > 0) {
 	if (!last_sbrk_top && require < FIRST_SBRK) 
 	    require = FIRST_SBRK;
 	else if (require < MIN_SBRK) require = MIN_SBRK;
 
-	if (require < goodsbrk * MIN_SBRK_FRAC / 100)
-	    require = goodsbrk * MIN_SBRK_FRAC / 100;
+	if (require < goodsbrk * MIN_SBRK_FRAC1000 / 1000)
+	    require = goodsbrk * MIN_SBRK_FRAC1000 / 1000;
 	require = ((require - 1 + MIN_SBRK) / MIN_SBRK) * MIN_SBRK;
     } else {
 	require = needed;
@@ -1297,7 +1594,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 #endif 
     if (cp == last_sbrk_top) {
 	/* Common case, anything is fine. */
-	sbrk_good++;
+	sbrk_goodness++;
 	ovp = (union overhead *) (cp - sbrked_remains);
 	last_op = cp - sbrked_remains;
 	sbrked_remains = require - (needed - sbrked_remains);
@@ -1369,7 +1666,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 		    if (cp == (char *)-1)
 			return 0;
 		}
-		sbrk_good = -1;	/* Disable optimization!
+		sbrk_goodness = -1;	/* Disable optimization!
 				   Continue with not-aligned... */
 	    } else {
 		cp += slack;
@@ -1378,7 +1675,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 	}
 
 	if (last_sbrk_top) {
-	    sbrk_good -= SBRK_FAILURE_PRICE;
+	    sbrk_goodness -= SBRK_FAILURE_PRICE;
 	}
 
 	ovp = (union overhead *) cp;
@@ -1411,7 +1708,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 	last_op = cp;
     }
 #if !defined(PLAIN_MALLOC) && !defined(NO_FANCY_MALLOC)
-    no_mem = 0;
+    emergency_buffer_last_req = 0;
 #endif
     last_sbrk_top = cp + require;
 #ifdef DEBUGGING_MSTATS
@@ -1450,7 +1747,7 @@ getpages_adjacent(MEM_SIZE require)
 		add_to_chain((void*)(last_sbrk_top - sbrked_remains),
 			     sbrked_remains, 0);
 	    add_to_chain((void*)cp, require, 0);
-	    sbrk_good -= SBRK_FAILURE_PRICE;
+	    sbrk_goodness -= SBRK_FAILURE_PRICE;
 	    sbrked_remains = 0;
 	    last_sbrk_top = 0;
 	    last_op = 0;
@@ -1471,9 +1768,39 @@ morecore(register int bucket)
   	register int rnu;       /* 2^rnu bytes will be requested */
   	int nblks;		/* become nblks blocks of the desired size */
 	register MEM_SIZE siz, needed;
+	static int were_called = 0;
 
   	if (nextf[bucket])
   		return;
+#ifndef NO_PERL_MALLOC_ENV
+	if (!were_called) {
+	    /* It's the our first time.  Initialize ourselves */
+	    were_called = 1;	/* Avoid a loop */
+	    {
+		char *s = getenv("PERL_MALLOC_OPT"), *t = s, *off;
+		const char *opts = PERL_MALLOC_OPT_CHARS;
+
+		while ( t && t[0] && t[1] == '='
+			&& ((off = strchr(opts, *t))) ) {
+		    IV val = 0;
+
+		    t += 2;
+		    while (*t <= '9' && *t >= '0')
+			val = 10*val + *t++ - '0';
+		    if (!*t || *t == ';') {
+			MallocCfg[off - opts] = val;
+			if (*t)
+			    t++;
+		    }
+		}
+		if (t && *t) {
+		    write2("Unrecognized part of PERL_MALLOC_OPT: `");
+		    write2(t);
+		    write2("'\n");
+		}
+	    }
+	}
+#endif
 	if (bucket == sizeof(MEM_SIZE)*8*BUCKETS_PER_POW2) {
 	    MALLOC_UNLOCK;
 	    croak("%s", "Out of memory during ridiculously large request");
@@ -1518,6 +1845,7 @@ morecore(register int bucket)
 
 	if (!ovp)
 	    return;
+	FILL_DEADBEEF((unsigned char*)ovp, needed);
 
 	/*
 	 * Add new memory allocated to that on
@@ -1638,7 +1967,10 @@ Perl_mfree(void *mp)
 	    }
 	    nbytes = (nbytes + 3) &~ 3; 
 	    ASSERT(*(u_int *)((caddr_t)ovp + nbytes - RSLOP) == RMAGIC, "chunk's tail overwrite");	    
+	    FILLCHECK_DEADBEEF((unsigned char*)((caddr_t)ovp + nbytes - RSLOP + sizeof(u_int)),
+			       BUCKET_SIZE_REAL(OV_INDEX(ovp)) - (nbytes - RSLOP + sizeof(u_int)));
 	}
+	FILL_DEADBEEF((unsigned char*)(ovp+1), BUCKET_SIZE_REAL(OV_INDEX(ovp)));
 	ovp->ov_rmagic = RMAGIC - 1;
 #endif
   	ASSERT(OV_INDEX(ovp) < NBUCKETS, "chunk's head overwrite");
@@ -1776,6 +2108,14 @@ Perl_realloc(void *mp, size_t nbytes)
 		       }
 		       nb = (nb + 3) &~ 3; 
 		       ASSERT(*(u_int *)((caddr_t)ovp + nb - RSLOP) == RMAGIC, "chunk's tail overwrite");
+		       FILLCHECK_DEADBEEF((unsigned char*)((caddr_t)ovp + nb - RSLOP + sizeof(u_int)),
+			       BUCKET_SIZE_REAL(OV_INDEX(ovp)) - (nb - RSLOP + sizeof(u_int)));
+		       if (nbytes > ovp->ov_size + 1 - M_OVERHEAD)
+			   FILL_FEEDADAD((unsigned char*)cp + ovp->ov_size + 1 - M_OVERHEAD,
+				     nbytes - (ovp->ov_size + 1 - M_OVERHEAD));
+		       else
+			   FILL_DEADBEEF((unsigned char*)cp + nbytes,
+					 nb - M_OVERHEAD + RSLOP - nbytes);
 			/*
 			 * Convert amount of memory requested into
 			 * closest block size stored in hash buckets
@@ -1954,7 +2294,7 @@ Perl_get_mstats(pTHX_ perl_mstats_t *buf
 	}
 	buf->total_sbrk = goodsbrk + sbrk_slack;
 	buf->sbrks = sbrks;
-	buf->sbrk_good = sbrk_good;
+	buf->sbrk_good = sbrk_goodness;
 	buf->sbrk_slack = sbrk_slack;
 	buf->start_slack = start_slack;
 	buf->sbrked_remains = sbrked_remains;
