diff options
author | Nicholas Clark <nick@ccl4.org> | 2010-10-13 14:12:27 +0100 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2010-10-13 14:12:27 +0100 |
commit | 0cf05ef1177b39ff322b92e7bf0e21b642395f49 (patch) | |
tree | 822452c6085e2a4ef51958f845c68fe103ef5c3d /universal.c | |
parent | 05099f26a2ddd438807aa96853b7e317f8afc787 (diff) | |
download | perl-0cf05ef1177b39ff322b92e7bf0e21b642395f49.tar.gz |
In XS_Tie_Hash_NamedCapture_{CLEAR,STORE}, free any returned value.
The calling convention for CALLREG_NAMED_BUFF_*() is to return NULL, or a
reference to a scalar. For CLEAR and STORE we return no values, so if we're
erroneously passed a reference, we should free it to stop it being leaked.
Diffstat (limited to 'universal.c')
-rw-r--r-- | universal.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/universal.c b/universal.c index f3fe05dc79..556a79661d 100644 --- a/universal.c +++ b/universal.c @@ -1296,6 +1296,7 @@ XS(XS_Tie_Hash_NamedCapture_STORE) dXSARGS; REGEXP * rx; U32 flags; + SV *ret; if (items != 3) croak_xs_usage(cv, "$key, $value, $flags"); @@ -1310,10 +1311,15 @@ XS(XS_Tie_Hash_NamedCapture_STORE) PUTBACK; flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0)))); - CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags); + ret = CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags); + /* Perl_magic_setpack calls us with G_DISCARD, so our return stack state is thrown away. */ + + /* If we were returned anything, free it immediately. */ + SvREFCNT_dec(ret); + XSRETURN_EMPTY; } XS(XS_Tie_Hash_NamedCapture_DELETE) @@ -1347,6 +1353,7 @@ XS(XS_Tie_Hash_NamedCapture_CLEAR) dXSARGS; REGEXP * rx; U32 flags; + SV *ret; if (items != 1) croak_xs_usage(cv, "$flags"); @@ -1360,10 +1367,14 @@ XS(XS_Tie_Hash_NamedCapture_CLEAR) PUTBACK; flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0)))); - CALLREG_NAMED_BUFF_CLEAR(rx, flags); + ret = CALLREG_NAMED_BUFF_CLEAR(rx, flags); /* Perl_magic_wipepack calls us with G_DISCARD, so our return stack state is thrown away. */ + + /* If we were returned anything, free it immediately. */ + SvREFCNT_dec(ret); + XSRETURN_EMPTY; } XS(XS_Tie_Hash_NamedCapture_EXISTS) |