This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix #124181 double free/refcnt problems in IO types in typemap
authorDaniel Dragan <bulk88@hotmail.com>
Wed, 24 Jun 2015 19:48:12 +0000 (15:48 -0400)
committerTony Cook <tony@develop-help.com>
Wed, 8 Jul 2015 00:55:07 +0000 (10:55 +1000)
commit7ed1d857c7b7016b9bde564c6802a4721d903d95
tree3283bba2888a998b55f9d27d3fb31c0f51a61c5c
parentc1b8440fca7358a5c52763ce726d40026870519c
fix #124181 double free/refcnt problems in IO types in typemap

commit 50e5165b96 "stop T_IN/OUT/INOUT/STDIO typemaps leaking" changed
newRV to newRV_noinc, but the GV * returned by newGVgen() is owned by the
package tree, like the SV * returned by get_sv(). Now when the RV to GV is
freed on mortal stack, the GV * in the package tree is freed, and now there
is a freed GV * in the package tree, if you turn on "PERL_DESTRUCT_LEVEL=2"
(and perhaps DEBUGGING is needed too), the package tree is destroyed SV *
by SV *, and perl will eventually warn with
"Attempt to free unreferenced scalar" which a very bad panic type warning.

commit 50e5165b96 was reverted in commit bae466e878
"Revert "stop T_IN/OUT/INOUT/STDIO typemaps leaking" for 5.22's release
to stop the panic, but reintroduced the SV/RV leak. So fix the RV leak (the val
passed as source arg of sv_setsv) by freeing it after the copying. In a very
unlikely scenario, the RV could still leak if sv_setsv dies.

Also fix the problem, that if this OUTPUT: type is being used for an
incoming arg, not the outgoing RETVAL arg, you can't assign a new SV*
ontop of the old one, that only works for perl stack return args, so
replace "$arg = &PL_sv_undef;" with "sv_setsv($arg, &PL_sv_undef);" if its
not RETVAL, this way OUTPUT on incoming args also works if it goes down the
error path. For efficiency, in a RETVAL siutation, let the undef original
SV* in $arg which is typically obtained from sv_newmortal() by xsubpp pass
through if we error out.

Also for efficiency, if it is RETVAL (which is more common) dont do the
sv_setsv/SvREFCNT_dec_NN stuff (2 function calls), just mortalize
(1 function call) the ex-temp RV and arrange for the RV to wind up on
perl stack.

Also, the GV * already knows what HV * stash it belongs to, so avoid the
stash lookup done by gv_stashpv() and just use GvSTASH which are simple
pointer derefs.
lib/ExtUtils/typemap
pod/perldelta.pod