mirror of
https://github.com/vim/vim.git
synced 2025-10-17 07:44:28 -04:00
patch 9.1.0620: Vim9: segfauls with null objects
Problem: Vim9: segfauls with null objects (after v9.1.0219) Solution: Check object pointer being NULL (Ernie Rael) fixes: #15338 closes: #15349 Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
8754efe437
commit
be82825687
@@ -661,6 +661,31 @@ def Test_object_not_set()
|
||||
Func()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
|
||||
|
||||
# Reference a object variable through a null class object which is stored in a
|
||||
# variable of type "any".
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
def Z()
|
||||
var o: any = null_object
|
||||
o.v = 4
|
||||
enddef
|
||||
Z()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
||||
|
||||
# Do "echom" of a null object variable.
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
def X()
|
||||
var x = null_object
|
||||
echom x
|
||||
enddef
|
||||
X()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 2)
|
||||
enddef
|
||||
|
||||
" Null object assignment and comparison
|
||||
@@ -7203,6 +7228,47 @@ def Test_null_object_method_call()
|
||||
T()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
||||
|
||||
# Calling an object method defined in a class that is extended. This differs
|
||||
# from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class C0
|
||||
def F()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
class C extends C0
|
||||
endclass
|
||||
|
||||
def X()
|
||||
var o: C0 = null_object
|
||||
o.F()
|
||||
enddef
|
||||
X()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
||||
|
||||
# Getting a function ref an object method.
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class C0
|
||||
def F()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
class C extends C0
|
||||
endclass
|
||||
|
||||
def X()
|
||||
var o: C0 = null_object
|
||||
var XXX = o.F
|
||||
enddef
|
||||
X()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
||||
enddef
|
||||
|
||||
" Test for using a dict as an object member
|
||||
|
10
src/typval.c
10
src/typval.c
@@ -266,6 +266,10 @@ tv_get_bool_or_number_chk(
|
||||
check_typval_is_value(varp);
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
{
|
||||
if (varp->vval.v_object == NULL)
|
||||
emsg(_(e_using_object_as_string));
|
||||
else
|
||||
{
|
||||
class_T *cl = varp->vval.v_object->obj_class;
|
||||
if (cl != NULL && IS_ENUM(cl))
|
||||
@@ -273,6 +277,7 @@ tv_get_bool_or_number_chk(
|
||||
else
|
||||
emsg(_(e_using_object_as_number));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VAR_VOID:
|
||||
emsg(_(e_cannot_use_void_value));
|
||||
@@ -1145,6 +1150,10 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
|
||||
check_typval_is_value(varp);
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
{
|
||||
if (varp->vval.v_object == NULL)
|
||||
emsg(_(e_using_object_as_string));
|
||||
else
|
||||
{
|
||||
class_T *cl = varp->vval.v_object->obj_class;
|
||||
if (cl != NULL && IS_ENUM(cl))
|
||||
@@ -1152,6 +1161,7 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
|
||||
else
|
||||
emsg(_(e_using_object_as_string));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
620,
|
||||
/**/
|
||||
619,
|
||||
/**/
|
||||
|
@@ -2254,6 +2254,13 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
|
||||
{
|
||||
// Need to get the member index now that the class is known.
|
||||
object_T *obj = tv_dest->vval.v_object;
|
||||
if (obj == NULL)
|
||||
{
|
||||
emsg(_(e_using_null_object));
|
||||
status = FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
class_T *cl = obj->obj_class;
|
||||
char_u *member = tv_idx->vval.v_string;
|
||||
|
||||
@@ -2263,7 +2270,8 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
|
||||
{
|
||||
if (*member == '_')
|
||||
{
|
||||
emsg_var_cl_define(e_cannot_access_protected_variable_str,
|
||||
emsg_var_cl_define(
|
||||
e_cannot_access_protected_variable_str,
|
||||
m->ocm_name, 0, cl);
|
||||
status = FAIL;
|
||||
}
|
||||
@@ -2276,6 +2284,7 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
|
||||
status = FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((dest_type == VAR_LIST || dest_type == VAR_OBJECT)
|
||||
&& tv_idx->v_type != VAR_NUMBER)
|
||||
{
|
||||
@@ -3567,7 +3576,10 @@ exec_instructions(ectx_T *ectx)
|
||||
p = tv_get_string_buf(tv, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
p = tv_stringify(tv, buf);
|
||||
}
|
||||
|
||||
len = (int)STRLEN(p);
|
||||
if (GA_GROW_FAILS(&ga, len + 2))
|
||||
@@ -4380,7 +4392,14 @@ exec_instructions(ectx_T *ectx)
|
||||
object_required_error(tv);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
object_T *obj = tv->vval.v_object;
|
||||
if (obj == NULL)
|
||||
{
|
||||
emsg(_(e_using_null_object));
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
class_T *cl = obj->obj_class;
|
||||
|
||||
// convert the interface index to the object index
|
||||
@@ -4536,12 +4555,21 @@ exec_instructions(ectx_T *ectx)
|
||||
tv = STACK_TV_BOT(-1);
|
||||
if (tv->v_type != VAR_OBJECT)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
object_required_error(tv);
|
||||
vim_free(pt);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
object_T *obj = tv->vval.v_object;
|
||||
if (obj == NULL)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
emsg(_(e_using_null_object));
|
||||
vim_free(pt);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
cl = obj->obj_class;
|
||||
// drop the value from the stack
|
||||
clear_tv(tv);
|
||||
|
Reference in New Issue
Block a user