summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-10-20 15:04:49 +0100
committerDavid Mitchell <davem@iabyn.com>2015-10-28 12:55:28 +0000
commit402d079e250e3dfdc9724f77bd7880f39e109b24 (patch)
tree1355d2ccfc4dc6d85d76b07d0e1060a5ddfc9fc9 /scope.c
parent0c7fc6418c524329d47034aa2f4bec4f288095e2 (diff)
downloadperl-402d079e250e3dfdc9724f77bd7880f39e109b24.tar.gz
RT: #126309 die more gracefully on (1) x ~1
Recent improvements to MEXTEND() etc means that the above is now caught and panics rather than crashing. However, the panic is: panic: av_extend_guts() negative count (-9223372036854775681) which is safe, but not pretty. This commit makes it croak instead with: Out of memory during stack extend Basically Perl_stack_grow() adds an extra 128 bytes of headroom to the amount it actually extends the stack by. Check in stack_grow() itself whether this has wrapped, rather than leaving it to av_extend_guts(), which can only give a generic panic message.
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/scope.c b/scope.c
index 1b891861de..bdf299a9c4 100644
--- a/scope.c
+++ b/scope.c
@@ -29,18 +29,32 @@
SV**
Perl_stack_grow(pTHX_ SV **sp, SV **p, SSize_t n)
{
+ SSize_t extra;
+ SSize_t current = (p - PL_stack_base);
+
PERL_ARGS_ASSERT_STACK_GROW;
- if (n < 0)
+ if (UNLIKELY(n < 0))
Perl_croak(aTHX_
"panic: stack_grow() negative count (%"IVdf")", (IV)n);
PL_stack_sp = sp;
-#ifndef STRESS_REALLOC
- av_extend(PL_curstack, (p - PL_stack_base) + (n) + 128);
+ extra =
+#ifdef STRESS_REALLOC
+ 1;
#else
- av_extend(PL_curstack, (p - PL_stack_base) + (n) + 1);
+ 128;
#endif
+ /* If the total might wrap, panic instead. This is really testing
+ * that (current + n + extra < SSize_t_MAX), but done in a way that
+ * can't wrap */
+ if (UNLIKELY( current > SSize_t_MAX - extra
+ || current + extra > SSize_t_MAX - n
+ ))
+ /* diag_listed_as: Out of memory during %s extend */
+ Perl_croak(aTHX_ "Out of memory during stack extend");
+
+ av_extend(PL_curstack, current + n + extra);
return PL_stack_sp;
}