Skip to content

Commit 41c363a

Browse files
committed
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)
1 parent ded27a1 commit 41c363a

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

src/if_perl.xs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -831,8 +831,7 @@ newWINrv(SV *rv, win_T *ptr)
831831
ptr->w_perl_private = newSV(0);
832832
sv_setiv(ptr->w_perl_private, PTR2IV(ptr));
833833
}
834-
else
835-
SvREFCNT_inc_void_NN(ptr->w_perl_private);
834+
SvREFCNT_inc_void_NN(ptr->w_perl_private);
836835
SvRV(rv) = ptr->w_perl_private;
837836
SvROK_on(rv);
838837
return sv_bless(rv, gv_stashpv("VIWIN", TRUE));
@@ -847,8 +846,7 @@ newBUFrv(SV *rv, buf_T *ptr)
847846
ptr->b_perl_private = newSV(0);
848847
sv_setiv(ptr->b_perl_private, PTR2IV(ptr));
849848
}
850-
else
851-
SvREFCNT_inc_void_NN(ptr->b_perl_private);
849+
SvREFCNT_inc_void_NN(ptr->b_perl_private);
852850
SvRV(rv) = ptr->b_perl_private;
853851
SvROK_on(rv);
854852
return sv_bless(rv, gv_stashpv("VIBUF", TRUE));
@@ -918,12 +916,13 @@ I32 cur_val(IV iv, SV *sv)
918916
else
919917
rv = newBUFrv(newSV(0), curbuf);
920918

921-
if (SvRV(sv) == SvRV(rv))
922-
SvREFCNT_dec(SvRV(rv));
923-
else // XXX: Not sure if the `else` condition are right
924-
// Test_SvREFCNT() pass in all case.
919+
if (SvRV(sv) != SvRV(rv))
920+
// XXX: This magic variable is a bit confusing...
921+
// Is curently refcounted ?
925922
sv_setsv(sv, rv);
926923

924+
SvREFCNT_dec(rv);
925+
927926
return 0;
928927
}
929928
#endif /* !PROTO */

src/testdir/test_perl.vim

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ if !has('perl')
44
finish
55
end
66

7+
" FIXME: RunTest don't see any error when Perl abort...
8+
perl $SIG{__WARN__} = sub { die "Unexpected warnings from perl: @_" };
9+
710
func Test_change_buffer()
811
call setline(line('$'), ['1 line 1'])
912
perl VIM::DoCommand("normal /^1\n")
@@ -229,6 +232,15 @@ func Test_000_SvREFCNT()
229232
#line 5 "Test_000_SvREFCNT()"
230233
my ($b, $w);
231234

235+
my $num = 0;
236+
for ( 0 .. 100 ) {
237+
if ( ++$num >= 8 ) { $num = 0 }
238+
VIM::DoCommand("buffer X$num");
239+
$b = $curbuf;
240+
}
241+
242+
VIM::DoCommand("buffer t");
243+
232244
$b = $curbuf for 0 .. 100;
233245
$w = $curwin for 0 .. 100;
234246
() = VIM::Buffers for 0 .. 100;
@@ -240,12 +252,13 @@ func Test_000_SvREFCNT()
240252
my $cw = Internals::SvREFCNT($$w);
241253
VIM::Eval("assert_equal(2, $cb, 'T1')");
242254
VIM::Eval("assert_equal(2, $cw, 'T2')");
255+
my $strongref;
243256
foreach ( VIM::Buffers, VIM::Windows ) {
257+
VIM::DoCommand("%bw!");
244258
my $c = Internals::SvREFCNT($_);
245259
VIM::Eval("assert_equal(2, $c, 'T3')");
246260
$c = Internals::SvREFCNT($$_);
247-
# Why only one ref?
248-
# Look wrong but work. Maybe not portable...
261+
next if $c == 2 && !$strongref++;
249262
VIM::Eval("assert_equal(1, $c, 'T4')");
250263
}
251264
$cb = Internals::SvREFCNT($$curbuf);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ static char *(features[]) =
794794

795795
static int included_patches[] =
796796
{ /* Add new patch number below this line */
797+
/**/
798+
234,
797799
/**/
798800
233,
799801
/**/

0 commit comments

Comments
 (0)