# HG changeset patch # User Christian Brabandt # Date 1533240006 -7200 # Node ID 2d6703d4448a48789029f91660d21cc30ec29df1 # Parent e9311564eccafb82b0fbaac0a24ee0aba72c5330 patch 8.1.0234: incorrect reference counting in Perl interface commit https://github.com/vim/vim/commit/41c363a3154dd1caeb431fa54748ad48ef6d3bd1 Author: Bram Moolenaar Date: Thu Aug 2 21:46:51 2018 +0200 patch 8.1.0234: incorrect reference counting in Perl interface Problem: Incorrect reference counting in Perl interface. Solution: Call SvREFCNT_inc more often, add a test. (Damien) diff --git a/src/if_perl.xs b/src/if_perl.xs --- a/src/if_perl.xs +++ b/src/if_perl.xs @@ -831,8 +831,7 @@ newWINrv(SV *rv, win_T *ptr) ptr->w_perl_private = newSV(0); sv_setiv(ptr->w_perl_private, PTR2IV(ptr)); } - else - SvREFCNT_inc_void_NN(ptr->w_perl_private); + SvREFCNT_inc_void_NN(ptr->w_perl_private); SvRV(rv) = ptr->w_perl_private; SvROK_on(rv); return sv_bless(rv, gv_stashpv("VIWIN", TRUE)); @@ -847,8 +846,7 @@ newBUFrv(SV *rv, buf_T *ptr) ptr->b_perl_private = newSV(0); sv_setiv(ptr->b_perl_private, PTR2IV(ptr)); } - else - SvREFCNT_inc_void_NN(ptr->b_perl_private); + SvREFCNT_inc_void_NN(ptr->b_perl_private); SvRV(rv) = ptr->b_perl_private; SvROK_on(rv); return sv_bless(rv, gv_stashpv("VIBUF", TRUE)); @@ -918,12 +916,13 @@ I32 cur_val(IV iv, SV *sv) else rv = newBUFrv(newSV(0), curbuf); - if (SvRV(sv) == SvRV(rv)) - SvREFCNT_dec(SvRV(rv)); - else // XXX: Not sure if the `else` condition are right - // Test_SvREFCNT() pass in all case. + if (SvRV(sv) != SvRV(rv)) + // XXX: This magic variable is a bit confusing... + // Is curently refcounted ? sv_setsv(sv, rv); + SvREFCNT_dec(rv); + return 0; } #endif /* !PROTO */ diff --git a/src/testdir/test_perl.vim b/src/testdir/test_perl.vim --- a/src/testdir/test_perl.vim +++ b/src/testdir/test_perl.vim @@ -4,6 +4,9 @@ if !has('perl') finish end +" FIXME: RunTest don't see any error when Perl abort... +perl $SIG{__WARN__} = sub { die "Unexpected warnings from perl: @_" }; + func Test_change_buffer() call setline(line('$'), ['1 line 1']) perl VIM::DoCommand("normal /^1\n") @@ -229,6 +232,15 @@ func Test_000_SvREFCNT() #line 5 "Test_000_SvREFCNT()" my ($b, $w); + my $num = 0; + for ( 0 .. 100 ) { + if ( ++$num >= 8 ) { $num = 0 } + VIM::DoCommand("buffer X$num"); + $b = $curbuf; + } + + VIM::DoCommand("buffer t"); + $b = $curbuf for 0 .. 100; $w = $curwin for 0 .. 100; () = VIM::Buffers for 0 .. 100; @@ -240,12 +252,13 @@ func Test_000_SvREFCNT() my $cw = Internals::SvREFCNT($$w); VIM::Eval("assert_equal(2, $cb, 'T1')"); VIM::Eval("assert_equal(2, $cw, 'T2')"); + my $strongref; foreach ( VIM::Buffers, VIM::Windows ) { + VIM::DoCommand("%bw!"); my $c = Internals::SvREFCNT($_); VIM::Eval("assert_equal(2, $c, 'T3')"); $c = Internals::SvREFCNT($$_); - # Why only one ref? - # Look wrong but work. Maybe not portable... + next if $c == 2 && !$strongref++; VIM::Eval("assert_equal(1, $c, 'T4')"); } $cb = Internals::SvREFCNT($$curbuf); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -795,6 +795,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 234, +/**/ 233, /**/ 232,