This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use SSize_t when extending the stack
authorFather Chrysostomos <sprout@cpan.org>
Sun, 25 Aug 2013 02:09:59 +0000 (19:09 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 25 Aug 2013 13:39:28 +0000 (06:39 -0700)
(I am referring to what is usually known simply as The Stack.)

This partially fixes #119161.

By casting the argument to int, we can end up truncating/wrapping
it on 64-bit systems, so EXTEND(SP, 2147483648) translates into
EXTEND(SP, -1), which does not extend the stack at all.  Then writing
to the stack in code like ()=1..1000000000000 goes past the end of
allocated memory and crashes.

I can’t really write a test for this, since instead of crashing it
will use more memory than I have available (and then I’ll start for-
getting things).

av.c
embed.fnc
pp.h
proto.h
scope.c

diff --git a/av.c b/av.c
index aae70bf..401a61c 100644 (file)
--- a/av.c
+++ b/av.c
@@ -63,7 +63,7 @@ extended.
 */
 
 void
-Perl_av_extend(pTHX_ AV *av, I32 key)
+Perl_av_extend(pTHX_ AV *av, SSize_t key)
 {
     dVAR;
     MAGIC *mg;
@@ -84,7 +84,7 @@ Perl_av_extend(pTHX_ AV *av, I32 key)
 
 /* The guts of av_extend.  *Not* for general use! */
 void
-Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
+Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
                          SV ***arrayp)
 {
     dVAR;
@@ -93,8 +93,8 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
 
     if (key > *maxp) {
        SV** ary;
-       I32 tmp;
-       I32 newmax;
+       SSize_t tmp;
+       SSize_t newmax;
 
        if (av && *allocp != *arrayp) {
            ary = *allocp + AvFILLp(av) + 1;
index ff88193..63896f3 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -209,8 +209,9 @@ ApM |void   |apply_attrs_string|NN const char *stashpv|NN CV *cv|NN const char *at
 Apd    |void   |av_clear       |NN AV *av
 Apd    |SV*    |av_delete      |NN AV *av|I32 key|I32 flags
 ApdR   |bool   |av_exists      |NN AV *av|I32 key
-Apd    |void   |av_extend      |NN AV *av|I32 key
-p      |void   |av_extend_guts |NULLOK AV *av|I32 key|NN SSize_t *maxp \
+Apd    |void   |av_extend      |NN AV *av|SSize_t key
+p      |void   |av_extend_guts |NULLOK AV *av|SSize_t key \
+                               |NN SSize_t *maxp \
                                |NN SV ***allocp|NN SV ***arrayp
 ApdR   |SV**   |av_fetch       |NN AV *av|I32 key|I32 lval
 Apd    |void   |av_fill        |NN AV *av|I32 fill
@@ -1265,7 +1266,7 @@ Anp       |Signal_t |csighandler  |int sig|NULLOK siginfo_t *info|NULLOK void *uap
 np     |Signal_t |sighandler   |int sig
 Anp    |Signal_t |csighandler  |int sig
 #endif
-Ap     |SV**   |stack_grow     |NN SV** sp|NN SV** p|int n
+Ap     |SV**   |stack_grow     |NN SV** sp|NN SV** p|SSize_t n
 Ap     |I32    |start_subparse |I32 is_format|U32 flags
 : Used in pp_ctl.c
 p      |void   |sub_crush_depth|NN CV* cv
diff --git a/pp.h b/pp.h
index cb6a066..af58a52 100644 (file)
--- a/pp.h
+++ b/pp.h
@@ -156,7 +156,7 @@ Pops a long off the stack.
 /* Go to some pains in the rare event that we must extend the stack. */
 
 /*
-=for apidoc Am|void|EXTEND|SP|int nitems
+=for apidoc Am|void|EXTEND|SP|SSize_t nitems
 Used to extend the argument stack for an XSUB's return values. Once
 used, guarantees that there is room for at least C<nitems> to be pushed
 onto the stack.
@@ -278,13 +278,13 @@ Does not use C<TARG>.  See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
 =cut
 */
 
-#define EXTEND(p,n)    (void)(UNLIKELY(PL_stack_max - p < (int)(n)) &&         \
-                           (sp = stack_grow(sp,p, (int) (n))))
+#define EXTEND(p,n)    (void)(UNLIKELY(PL_stack_max - p < (SSize_t)(n)) &&     \
+                           (sp = stack_grow(sp,p, (SSize_t) (n))))
 
 /* Same thing, but update mark register too. */
 #define MEXTEND(p,n)   STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
                            const int markoff = mark - PL_stack_base;           \
-                           sp = stack_grow(sp,p,(int) (n));                    \
+                           sp = stack_grow(sp,p,(SSize_t) (n));                \
                            mark = PL_stack_base + markoff;                     \
                        } } STMT_END
 
diff --git a/proto.h b/proto.h
index 4d5db7f..9b1bc8f 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -160,12 +160,12 @@ PERL_CALLCONV bool        Perl_av_exists(pTHX_ AV *av, I32 key)
 #define PERL_ARGS_ASSERT_AV_EXISTS     \
        assert(av)
 
-PERL_CALLCONV void     Perl_av_extend(pTHX_ AV *av, I32 key)
+PERL_CALLCONV void     Perl_av_extend(pTHX_ AV *av, SSize_t key)
                        __attribute__nonnull__(pTHX_1);
 #define PERL_ARGS_ASSERT_AV_EXTEND     \
        assert(av)
 
-PERL_CALLCONV void     Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp, SV ***arrayp)
+PERL_CALLCONV void     Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp, SV ***arrayp)
                        __attribute__nonnull__(pTHX_3)
                        __attribute__nonnull__(pTHX_4)
                        __attribute__nonnull__(pTHX_5);
@@ -3794,7 +3794,7 @@ PERL_CALLCONV void        Perl_sortsv_flags(pTHX_ SV** array, size_t num_elts, SVCOMPAR
 #define PERL_ARGS_ASSERT_SORTSV_FLAGS  \
        assert(cmp)
 
-PERL_CALLCONV SV**     Perl_stack_grow(pTHX_ SV** sp, SV** p, int n)
+PERL_CALLCONV SV**     Perl_stack_grow(pTHX_ SV** sp, SV** p, SSize_t n)
                        __attribute__nonnull__(pTHX_1)
                        __attribute__nonnull__(pTHX_2);
 #define PERL_ARGS_ASSERT_STACK_GROW    \
diff --git a/scope.c b/scope.c
index 08ecc30..fb226a1 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -27,7 +27,7 @@
 #include "perl.h"
 
 SV**
-Perl_stack_grow(pTHX_ SV **sp, SV **p, int n)
+Perl_stack_grow(pTHX_ SV **sp, SV **p, SSize_t n)
 {
     dVAR;