diff options
author | Nicholas Clark <nick@ccl4.org> | 2012-09-13 18:13:43 +0200 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2012-09-14 08:34:18 +0200 |
commit | 6c31ff7434088c8eb1fd81ffe6b039a372bd9fc7 (patch) | |
tree | 34816515ee1de443587e3b738e8d73cbe0367fe1 | |
parent | 77f8f7c12a17bc6246ab7d4fd8a427fae71040af (diff) | |
download | perl-6c31ff7434088c8eb1fd81ffe6b039a372bd9fc7.tar.gz |
Fix buggy -DPERL_POISON code in S_rxres_free(), exposed by a recent test.
The code had been buggily attempting to overwrite just-freed memory since
PERL_POISON was added by commit 94010e71b67db040 in June 2005. However, no
regression test exercised this code path until recently.
Also fix the offset in the array of UVs used by PERL_OLD_COPY_ON_WRITE to
store RX_SAVED_COPY(). It now uses p[2]. Previously it had used p[1],
directly conflicting with the use of p[1] to store RX_NPARENS().
The code is too intertwined to meaningfully do these as separate commits.
-rw-r--r-- | pp_ctl.c | 24 |
1 files changed, 14 insertions, 10 deletions
@@ -366,13 +366,13 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) /* what (if anything) to free on croak */ *p++ = PTR2UV(RX_MATCH_COPIED(rx) ? RX_SUBBEG(rx) : NULL); RX_MATCH_COPIED_off(rx); + *p++ = RX_NPARENS(rx); #ifdef PERL_OLD_COPY_ON_WRITE *p++ = PTR2UV(RX_SAVED_COPY(rx)); RX_SAVED_COPY(rx) = NULL; #endif - *p++ = RX_NPARENS(rx); *p++ = PTR2UV(RX_SUBBEG(rx)); *p++ = (UV)RX_SUBLEN(rx); *p++ = (UV)RX_SUBOFFSET(rx); @@ -395,6 +395,7 @@ S_rxres_restore(pTHX_ void **rsp, REGEXP *rx) RX_MATCH_COPY_FREE(rx); RX_MATCH_COPIED_set(rx, *p); *p++ = 0; + RX_NPARENS(rx) = *p++; #ifdef PERL_OLD_COPY_ON_WRITE if (RX_SAVED_COPY(rx)) @@ -403,7 +404,6 @@ S_rxres_restore(pTHX_ void **rsp, REGEXP *rx) *p++ = 0; #endif - RX_NPARENS(rx) = *p++; RX_SUBBEG(rx) = INT2PTR(char*,*p++); RX_SUBLEN(rx) = (I32)(*p++); RX_SUBOFFSET(rx) = (I32)*p++; @@ -423,19 +423,23 @@ S_rxres_free(pTHX_ void **rsp) PERL_UNUSED_CONTEXT; if (p) { -#ifdef PERL_POISON void *tmp = INT2PTR(char*,*p); - Safefree(tmp); - if (*p) - PoisonFree(*p, 1, sizeof(*p)); +#ifdef PERL_POISON +#ifdef PERL_OLD_COPY_ON_WRITE + U32 i = 9 + p[1] * 2; #else - Safefree(INT2PTR(char*,*p)); + U32 i = 8 + p[1] * 2; #endif +#endif + #ifdef PERL_OLD_COPY_ON_WRITE - if (p[1]) { - SvREFCNT_dec (INT2PTR(SV*,p[1])); - } + SvREFCNT_dec (INT2PTR(SV*,p[2])); #endif +#ifdef PERL_POISON + PoisonFree(p, i, sizeof(UV)); +#endif + + Safefree(tmp); Safefree(p); *rsp = NULL; } |