patch 9.0.2001: Vim9: segfault with islocked()
Problem: Vim9: segfault with islocked()
Solution: Check that the lval pointer is not null for objects and
class variables
closes: #13295
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 0e70c9f..555c46c 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -4161,6 +4161,86 @@
v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "C"')
enddef
+" Test builtin islocked()
+def Test_lockvar_islocked()
+ # Can't lock class/object variable
+ # Lock class/object variable's value
+ # Lock item of variabl's value (a list item)
+ # varible is at index 1 within class/object
+ var lines =<< trim END
+ vim9script
+
+ class C
+ this.o0: list<list<number>> = [ [0], [1], [2]]
+ this.o1: list<list<number>> = [[10], [11], [12]]
+ static c0: list<list<number>> = [[20], [21], [22]]
+ static c1: list<list<number>> = [[30], [31], [32]]
+ endclass
+
+ def LockIt(arg: any)
+ lockvar arg
+ enddef
+
+ def UnlockIt(arg: any)
+ unlockvar arg
+ enddef
+
+ var obj = C.new()
+ #lockvar obj.o1 # can't lock something you can't write to
+
+ try
+ lockvar obj.o1 # can't lock something you can't write to
+ call assert_false(1, '"lockvar obj.o1" should have failed')
+ catch
+ call assert_exception('E1335:')
+ endtry
+
+ LockIt(obj.o1) # but can lock it's value
+ assert_equal(1, islocked("obj.o1"))
+ assert_equal(1, islocked("obj.o1[0]"))
+ assert_equal(1, islocked("obj.o1[1]"))
+ UnlockIt(obj.o1)
+ assert_equal(0, islocked("obj.o1"))
+ assert_equal(0, islocked("obj.o1[0]"))
+
+ lockvar obj.o1[0]
+ assert_equal(0, islocked("obj.o1"))
+ assert_equal(1, islocked("obj.o1[0]"))
+ assert_equal(0, islocked("obj.o1[1]"))
+ unlockvar obj.o1[0]
+ assert_equal(0, islocked("obj.o1"))
+ assert_equal(0, islocked("obj.o1[0]"))
+
+ # Same thing, but with a static
+
+ try
+ lockvar C.c1 # can't lock something you can't write to
+ call assert_false(1, '"lockvar C.c1" should have failed')
+ catch
+ call assert_exception('E1335:')
+ endtry
+
+ LockIt(C.c1) # but can lock it's value
+ assert_equal(1, islocked("C.c1"))
+ assert_equal(1, islocked("C.c1[0]"))
+ assert_equal(1, islocked("C.c1[1]"))
+ UnlockIt(C.c1)
+ assert_equal(0, islocked("C.c1"))
+ assert_equal(0, islocked("C.c1[0]"))
+
+ lockvar C.c1[0]
+ assert_equal(0, islocked("C.c1"))
+ assert_equal(1, islocked("C.c1[0]"))
+ assert_equal(0, islocked("C.c1[1]"))
+ unlockvar C.c1[0]
+ assert_equal(0, islocked("C.c1"))
+ assert_equal(0, islocked("C.c1[0]"))
+ END
+ v9.CheckSourceSuccess(lines)
+ lines =<< trim END
+ END
+enddef
+
" Test for a private object method
def Test_private_object_method()
# Try calling a private method using an object (at the script level)