Skip to content

Commit b2b47bd

Browse files
h-eastchrisbra
authored andcommitted
patch 9.2.1172: Vim9: crash when lambda assigns to item of outer argument
Problem: Assigning to an element of an outer function's argument inside a lambda causes a crash when the lambda is called. Solution: When an outer function's argument is found on the left-hand side of an assignment, record that the outer scope is used and treat the lambda as a closure. When an outer function's argument was used on the left-hand side of an assignment, a LOADOUTER instruction was generated, but the lambda was not treated as a closure. Consequently, the outer stack was not set for the partial, leading to a NULL reference during the execution of LOADOUTER. fixes: #21460 closes: #21465 Signed-off-by: Hirohito Higashi <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent ec130c0 commit b2b47bd

3 files changed

Lines changed: 45 additions & 0 deletions

File tree

‎src/testdir/test_vim9_func.vim‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3142,6 +3142,46 @@ def Test_closure_using_argument()
31423142
assert_equal([3, 4, 5], Test(Inc))
31433143
END
31443144
v9.CheckScriptSuccess(lines)
3145+
3146+
# assign to an element of the outer function's argument
3147+
lines =<< trim END
3148+
vim9script
3149+
def MakeSetter(arg: dict<any>): func()
3150+
return () => {
3151+
arg.key = 1
3152+
}
3153+
enddef
3154+
def Run()
3155+
var Set = MakeSetter({})
3156+
Set()
3157+
enddef
3158+
Run()
3159+
3160+
var d: dict<any> = {}
3161+
MakeSetter(d)()
3162+
assert_equal({key: 1}, d)
3163+
3164+
def MakeListSetter(arg: list<number>): func()
3165+
return () => {
3166+
arg[0] = 2
3167+
}
3168+
enddef
3169+
var l = [0]
3170+
MakeListSetter(l)()
3171+
assert_equal([2], l)
3172+
3173+
def MakeNestedSetter(arg: dict<any>): func(): func()
3174+
return () => {
3175+
return () => {
3176+
arg.key = 3
3177+
}
3178+
}
3179+
enddef
3180+
var nd: dict<any> = {}
3181+
MakeNestedSetter(nd)()()
3182+
assert_equal({key: 3}, nd)
3183+
END
3184+
v9.CheckScriptSuccess(lines)
31453185
enddef
31463186

31473187
def s:MakeGetAndAppendRefs()

‎src/version.c‎

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

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1172,
746748
/**/
747749
1171,
748750
/**/

‎src/vim9compile.c‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ arg_exists(
183183
== OK)
184184
{
185185
if (gen_load_outer != NULL)
186+
{
186187
++*gen_load_outer;
188+
cctx->ctx_outer_used = TRUE;
189+
}
187190
return OK;
188191
}
189192
}

0 commit comments

Comments
 (0)