Skip to content

Commit

Permalink
Fix buggy -DPERL_POISON code in S_rxres_free(), exposed by a recent t…
Browse files Browse the repository at this point in the history
…est.

The code had been buggily attempting to overwrite just-freed memory since
PERL_POISON was added by commit 94010e7 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.
  • Loading branch information
nwc10 committed Sep 14, 2012
1 parent 77f8f7c commit 6c31ff7
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions pp_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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))
Expand All @@ -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++;
Expand All @@ -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;
}
Expand Down

0 comments on commit 6c31ff7

Please sign in to comment.