diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-10-26 06:00:59 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-10-26 06:00:59 -0700 |
commit | 8cece9139aefc96dd3920fa7908afea1581f51b7 (patch) | |
tree | 77e6ff3562783ced6268592a9717a584e2f496fb /perl.c | |
parent | b188953e9dd3c8a2696f2e1ea1f59ccc6a80d81f (diff) | |
download | perl-8cece9139aefc96dd3920fa7908afea1581f51b7.tar.gz |
Make PL_DBgv and other db interp vars refcounted
$ PERL5DB=1 perl -de '*DB::DB = sub {} if 0; sub DB::DB{}'
No DB::DB routine defined at -e line 1.
When the ‘if’ gets folded and *DB::DB is freed, it triggers
gv_try_downgrade, causing $DB::{DB} to be deleted and PL_DBgv to point
to a freed SV. A higher refcount would prevent gv_try_downgrade from
touching it.
Diffstat (limited to 'perl.c')
-rw-r--r-- | perl.c | 22 |
1 files changed, 16 insertions, 6 deletions
@@ -959,9 +959,6 @@ perl_destruct(pTHXx) PL_stderrgv = NULL; PL_last_in_gv = NULL; PL_replgv = NULL; - PL_DBgv = NULL; - PL_DBline = NULL; - PL_DBsub = NULL; PL_DBsingle = NULL; PL_DBtrace = NULL; PL_DBsignal = NULL; @@ -969,6 +966,13 @@ perl_destruct(pTHXx) PL_dbargs = NULL; PL_debstash = NULL; + SvREFCNT_dec(PL_DBgv); + SvREFCNT_dec(PL_DBline); + SvREFCNT_dec(PL_DBsub); + PL_DBgv = NULL; + PL_DBline = NULL; + PL_DBsub = NULL; + SvREFCNT_dec(PL_argvout_stack); PL_argvout_stack = NULL; @@ -4043,9 +4047,15 @@ Perl_init_debugger(pTHX) PL_curstash = (HV *)SvREFCNT_inc_simple(PL_debstash); Perl_init_dbargs(aTHX); - PL_DBgv = gv_fetchpvs("DB::DB", GV_ADDMULTI, SVt_PVGV); - PL_DBline = gv_fetchpvs("DB::dbline", GV_ADDMULTI, SVt_PVAV); - PL_DBsub = gv_HVadd(gv_fetchpvs("DB::sub", GV_ADDMULTI, SVt_PVHV)); + PL_DBgv = MUTABLE_GV( + SvREFCNT_inc(gv_fetchpvs("DB::DB", GV_ADDMULTI, SVt_PVGV)) + ); + PL_DBline = MUTABLE_GV( + SvREFCNT_inc(gv_fetchpvs("DB::dbline", GV_ADDMULTI, SVt_PVAV)) + ); + PL_DBsub = MUTABLE_GV(SvREFCNT_inc( + gv_HVadd(gv_fetchpvs("DB::sub", GV_ADDMULTI, SVt_PVHV)) + )); PL_DBsingle = GvSV((gv_fetchpvs("DB::single", GV_ADDMULTI, SVt_PV))); if (!SvIOK(PL_DBsingle)) sv_setiv(PL_DBsingle, 0); |