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

patch 9.0.2129: [security]: use-after-free in call_dfunc()

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>
This commit is contained in:
mityu
2023-11-25 15:41:20 +01:00
committed by Christian Brabandt
parent 8c14e79737
commit a555069b7d
3 changed files with 175 additions and 0 deletions

View File

@@ -8585,4 +8585,171 @@ def Test_dict_member_key_type_check()
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3) v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
enddef 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 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

View File

@@ -704,6 +704,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 */
/**/
2129,
/**/ /**/
2128, 2128,
/**/ /**/

View File

@@ -548,6 +548,12 @@ call_dfunc(
if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL) if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
return 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: // Reserve space for:
// - missing arguments // - missing arguments
// - stack frame // - stack frame