summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authormityu <mityu.mail@gmail.com>2023-11-25 15:41:20 +0100
committerChristian Brabandt <cb@256bit.org>2023-11-25 15:41:20 +0100
commita555069b7d790abedc60edc505bd35bda257949d (patch)
tree1514af3bf9ce5f9470b9b731f45ef2e8f6dd759f /src
parent8c14e79737c5df5cd111f60e7bda46cb0b9d89f7 (diff)
patch 9.0.2129: [security]: use-after-free in call_dfunc()v9.0.2129
Problem: [security]: use-after-free in call_dfunc() Solution: Refresh dfunc pointer closes: #13571 This Commit fixes a SEGV caused by a use-after-free bug in call_dfunc(). When calling check_ufunc_arg_types() from the call_dfunc() it may cause def functions to be re-compiled and if there are too many def functions, the def_functions array will be re-allocated. Which means, that the dfunc pointer in call_dfunc() now starts pointing to freed memory. So we need to reset the dfunc pointer after calling check_ufunc_arg_types(). Let's also add a test, to ensure we do not regress. Signed-off-by: mityu <mityu.mail@gmail.com> Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src')
-rw-r--r--src/testdir/test_vim9_class.vim167
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c6
3 files changed, 175 insertions, 0 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 18fde09910..3da4eb00f3 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -8585,4 +8585,171 @@ def Test_dict_member_key_type_check()
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
enddef
+def Test_compile_many_def_functions_in_funcref_instr()
+ # This used to crash Vim. This is reproducible only when run on new instance
+ # of Vim.
+ var lines =<< trim END
+ vim9script
+
+ class A
+ def new()
+ this.TakeFunc(this.F00)
+ enddef
+
+ def TakeFunc(F: func)
+ enddef
+
+ def F00()
+ this.F01()
+ this.F02()
+ this.F03()
+ this.F04()
+ this.F05()
+ this.F06()
+ this.F07()
+ this.F08()
+ this.F09()
+ this.F10()
+ this.F11()
+ this.F12()
+ this.F13()
+ this.F14()
+ this.F15()
+ this.F16()
+ this.F17()
+ this.F18()
+ this.F19()
+ this.F20()
+ this.F21()
+ this.F22()
+ this.F23()
+ this.F24()
+ this.F25()
+ this.F26()
+ this.F27()
+ this.F28()
+ this.F29()
+ this.F30()
+ this.F31()
+ this.F32()
+ this.F33()
+ this.F34()
+ this.F35()
+ this.F36()
+ this.F37()
+ this.F38()
+ this.F39()
+ this.F40()
+ this.F41()
+ this.F42()
+ this.F43()
+ this.F44()
+ this.F45()
+ this.F46()
+ this.F47()
+ enddef
+
+ def F01()
+ enddef
+ def F02()
+ enddef
+ def F03()
+ enddef
+ def F04()
+ enddef
+ def F05()
+ enddef
+ def F06()
+ enddef
+ def F07()
+ enddef
+ def F08()
+ enddef
+ def F09()
+ enddef
+ def F10()
+ enddef
+ def F11()
+ enddef
+ def F12()
+ enddef
+ def F13()
+ enddef
+ def F14()
+ enddef
+ def F15()
+ enddef
+ def F16()
+ enddef
+ def F17()
+ enddef
+ def F18()
+ enddef
+ def F19()
+ enddef
+ def F20()
+ enddef
+ def F21()
+ enddef
+ def F22()
+ enddef
+ def F23()
+ enddef
+ def F24()
+ enddef
+ def F25()
+ enddef
+ def F26()
+ enddef
+ def F27()
+ enddef
+ def F28()
+ enddef
+ def F29()
+ enddef
+ def F30()
+ enddef
+ def F31()
+ enddef
+ def F32()
+ enddef
+ def F33()
+ enddef
+ def F34()
+ enddef
+ def F35()
+ enddef
+ def F36()
+ enddef
+ def F37()
+ enddef
+ def F38()
+ enddef
+ def F39()
+ enddef
+ def F40()
+ enddef
+ def F41()
+ enddef
+ def F42()
+ enddef
+ def F43()
+ enddef
+ def F44()
+ enddef
+ def F45()
+ enddef
+ def F46()
+ enddef
+ def F47()
+ enddef
+ endclass
+
+ A.new()
+ END
+ writefile(lines, 'Xscript', 'D')
+ g:RunVim([], [], '-u NONE -S Xscript -c qa')
+ assert_equal(0, v:shell_error)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/version.c b/src/version.c
index a9d0bdd2b4..ab8492840d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2129,
+/**/
2128,
/**/
2127,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 997dfa00ab..e329559eab 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -548,6 +548,12 @@ call_dfunc(
if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
return FAIL;
+ // While check_ufunc_arg_types call, def function compilation process may
+ // run. If so many def functions are compiled, def_functions array may be
+ // reallocated and dfunc may no longer have valid pointer. Get the object
+ // pointer from def_functions again here.
+ dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
+
// Reserve space for:
// - missing arguments
// - stack frame