0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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)
This commit is contained in:
Bram Moolenaar
2018-08-02 21:46:51 +02:00
parent ded27a1feb
commit 41c363a315
3 changed files with 24 additions and 10 deletions

View File

@@ -831,8 +831,7 @@ newWINrv(SV *rv, win_T *ptr)
ptr->w_perl_private = newSV(0); ptr->w_perl_private = newSV(0);
sv_setiv(ptr->w_perl_private, PTR2IV(ptr)); 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; SvRV(rv) = ptr->w_perl_private;
SvROK_on(rv); SvROK_on(rv);
return sv_bless(rv, gv_stashpv("VIWIN", TRUE)); return sv_bless(rv, gv_stashpv("VIWIN", TRUE));
@@ -847,8 +846,7 @@ newBUFrv(SV *rv, buf_T *ptr)
ptr->b_perl_private = newSV(0); ptr->b_perl_private = newSV(0);
sv_setiv(ptr->b_perl_private, PTR2IV(ptr)); 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; SvRV(rv) = ptr->b_perl_private;
SvROK_on(rv); SvROK_on(rv);
return sv_bless(rv, gv_stashpv("VIBUF", TRUE)); return sv_bless(rv, gv_stashpv("VIBUF", TRUE));
@@ -918,12 +916,13 @@ I32 cur_val(IV iv, SV *sv)
else else
rv = newBUFrv(newSV(0), curbuf); rv = newBUFrv(newSV(0), curbuf);
if (SvRV(sv) == SvRV(rv)) if (SvRV(sv) != SvRV(rv))
SvREFCNT_dec(SvRV(rv)); // XXX: This magic variable is a bit confusing...
else // XXX: Not sure if the `else` condition are right // Is curently refcounted ?
// Test_SvREFCNT() pass in all case.
sv_setsv(sv, rv); sv_setsv(sv, rv);
SvREFCNT_dec(rv);
return 0; return 0;
} }
#endif /* !PROTO */ #endif /* !PROTO */

View File

@@ -4,6 +4,9 @@ if !has('perl')
finish finish
end end
" FIXME: RunTest don't see any error when Perl abort...
perl $SIG{__WARN__} = sub { die "Unexpected warnings from perl: @_" };
func Test_change_buffer() func Test_change_buffer()
call setline(line('$'), ['1 line 1']) call setline(line('$'), ['1 line 1'])
perl VIM::DoCommand("normal /^1\n") perl VIM::DoCommand("normal /^1\n")
@@ -229,6 +232,15 @@ func Test_000_SvREFCNT()
#line 5 "Test_000_SvREFCNT()" #line 5 "Test_000_SvREFCNT()"
my ($b, $w); 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; $b = $curbuf for 0 .. 100;
$w = $curwin for 0 .. 100; $w = $curwin for 0 .. 100;
() = VIM::Buffers for 0 .. 100; () = VIM::Buffers for 0 .. 100;
@@ -240,12 +252,13 @@ func Test_000_SvREFCNT()
my $cw = Internals::SvREFCNT($$w); my $cw = Internals::SvREFCNT($$w);
VIM::Eval("assert_equal(2, $cb, 'T1')"); VIM::Eval("assert_equal(2, $cb, 'T1')");
VIM::Eval("assert_equal(2, $cw, 'T2')"); VIM::Eval("assert_equal(2, $cw, 'T2')");
my $strongref;
foreach ( VIM::Buffers, VIM::Windows ) { foreach ( VIM::Buffers, VIM::Windows ) {
VIM::DoCommand("%bw!");
my $c = Internals::SvREFCNT($_); my $c = Internals::SvREFCNT($_);
VIM::Eval("assert_equal(2, $c, 'T3')"); VIM::Eval("assert_equal(2, $c, 'T3')");
$c = Internals::SvREFCNT($$_); $c = Internals::SvREFCNT($$_);
# Why only one ref? next if $c == 2 && !$strongref++;
# Look wrong but work. Maybe not portable...
VIM::Eval("assert_equal(1, $c, 'T4')"); VIM::Eval("assert_equal(1, $c, 'T4')");
} }
$cb = Internals::SvREFCNT($$curbuf); $cb = Internals::SvREFCNT($$curbuf);

View File

@@ -794,6 +794,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
234,
/**/ /**/
233, 233,
/**/ /**/