patch 9.1.0620: Vim9: segfauls with null objects

Commit: 
https://github.com/vim/vim/commit/be82825687fcf020dc79667cc1cdf62ace2215f2
Author: Ernie Rael <err...@raelity.com>
Date:   Fri Jul 26 18:37:02 2024 +0200

    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 <err...@raelity.com>
    Signed-off-by: Yegappan Lakshmanan <yegap...@yahoo.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 465459846..b2ef0db98 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -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
diff --git a/src/typval.c b/src/typval.c
index 67c819f0a..e50e96af0 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -267,11 +267,16 @@ tv_get_bool_or_number_chk(
            break;
        case VAR_OBJECT:
            {
-               class_T *cl = varp->vval.v_object->obj_class;
-               if (cl != NULL && IS_ENUM(cl))
-                   semsg(_(e_using_enum_str_as_number), cl->class_name);
+               if (varp->vval.v_object == NULL)
+                   emsg(_(e_using_object_as_string));
                else
-                   emsg(_(e_using_object_as_number));
+               {
+                   class_T *cl = varp->vval.v_object->obj_class;
+                   if (cl != NULL && IS_ENUM(cl))
+                       semsg(_(e_using_enum_str_as_number), cl->class_name);
+                   else
+                       emsg(_(e_using_object_as_number));
+               }
            }
            break;
        case VAR_VOID:
@@ -1146,11 +1151,16 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u 
*buf, int strict)
            break;
        case VAR_OBJECT:
            {
-               class_T *cl = varp->vval.v_object->obj_class;
-               if (cl != NULL && IS_ENUM(cl))
-                   semsg(_(e_using_enum_str_as_string), cl->class_name);
-               else
+               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))
+                       semsg(_(e_using_enum_str_as_string), cl->class_name);
+                   else
+                       emsg(_(e_using_object_as_string));
+               }
            }
            break;
        case VAR_JOB:
diff --git a/src/version.c b/src/version.c
index 298d57714..806e3c542 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    620,
 /**/
     619,
 /**/
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 3a3960a8d..40b549934 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2254,26 +2254,35 @@ 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;
-           class_T *cl = obj->obj_class;
-           char_u  *member = tv_idx->vval.v_string;
-
-           int         m_idx;
-           ocmember_T *m = object_member_lookup(cl, member, 0, &m_idx);
-           if (m != NULL)
+           if (obj == NULL)
            {
-               if (*member == '_')
-               {
-                   emsg_var_cl_define(e_cannot_access_protected_variable_str,
-                                                       m->ocm_name, 0, cl);
-                   status = FAIL;
-               }
-
-               lidx = m_idx;
+               emsg(_(e_using_null_object));
+               status = FAIL;
            }
            else
            {
-               member_not_found_msg(cl, VAR_OBJECT, member, 0);
-               status = FAIL;
+               class_T *cl = obj->obj_class;
+               char_u  *member = tv_idx->vval.v_string;
+
+               int             m_idx;
+               ocmember_T *m = object_member_lookup(cl, member, 0, &m_idx);
+               if (m != NULL)
+               {
+                   if (*member == '_')
+                   {
+                       emsg_var_cl_define(
+                                       e_cannot_access_protected_variable_str,
+                                       m->ocm_name, 0, cl);
+                       status = FAIL;
+                   }
+
+                   lidx = m_idx;
+               }
+               else
+               {
+                   member_not_found_msg(cl, VAR_OBJECT, member, 0);
+                   status = FAIL;
+               }
            }
        }
        else if ((dest_type == VAR_LIST || dest_type == VAR_OBJECT)
@@ -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);

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sXO3z-00CbCI-8H%40256bit.org.

Raspunde prin e-mail lui