diff options
author | David Mitchell <davem@iabyn.com> | 2015-10-20 15:04:49 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2015-10-28 12:55:28 +0000 |
commit | 402d079e250e3dfdc9724f77bd7880f39e109b24 (patch) | |
tree | 1355d2ccfc4dc6d85d76b07d0e1060a5ddfc9fc9 /scope.c | |
parent | 0c7fc6418c524329d47034aa2f4bec4f288095e2 (diff) | |
download | perl-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.c | 22 |
1 files changed, 18 insertions, 4 deletions
@@ -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; } |