]> granicus.if.org Git - vim/commitdiff
patch 8.2.1539: using invalid script ID causes a crash v8.2.1539
authorBram Moolenaar <Bram@vim.org>
Sat, 29 Aug 2020 11:39:17 +0000 (13:39 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 29 Aug 2020 11:39:17 +0000 (13:39 +0200)
Problem:    Using invalid script ID causes a crash.
Solution:   Check the script ID to be valid. (closes #6804)

src/evalvars.c
src/globals.h
src/profiler.c
src/scriptfile.c
src/testdir/test_vim9_script.vim
src/version.c
src/vim9compile.c

index a946c75ba7de4e4059b61f3b40b592a51ec0980e..ecd0ce6bd5b77ba31823631e5f2b8e1ee33f0aa3 100644 (file)
@@ -524,7 +524,7 @@ list_vim_vars(int *first)
     static void
 list_script_vars(int *first)
 {
-    if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len)
+    if (SCRIPT_ID_VALID(current_sctx.sc_sid))
        list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
                                                           "s:", FALSE, first);
 }
@@ -2609,7 +2609,7 @@ get_script_local_ht(void)
 {
     scid_T sid = current_sctx.sc_sid;
 
-    if (sid > 0 && sid <= script_items.ga_len)
+    if (SCRIPT_ID_VALID(sid))
        return &SCRIPT_VARS(sid);
     return NULL;
 }
index e883c56f637d25f53a9a02b60feced504b1f703d..1a764b50919f070490015f5b2acdd91981f7ca34 100644 (file)
@@ -297,8 +297,9 @@ EXTERN int  do_profiling INIT(= PROF_NONE); // PROF_ values
 # endif
 EXTERN garray_T script_items INIT5(0, 0, sizeof(scriptitem_T *), 20, NULL);
 # define SCRIPT_ITEM(id)    (((scriptitem_T **)script_items.ga_data)[(id) - 1])
-# define SCRIPT_SV(id)     (SCRIPT_ITEM(id)->sn_vars)
-# define SCRIPT_VARS(id)    (SCRIPT_SV(id)->sv_dict.dv_hashtab)
+# define SCRIPT_ID_VALID(id)    ((id) > 0 && (id) <= script_items.ga_len)
+# define SCRIPT_SV(id)         (SCRIPT_ITEM(id)->sn_vars)
+# define SCRIPT_VARS(id)       (SCRIPT_SV(id)->sv_dict.dv_hashtab)
 
 # define FUNCLINE(fp, j)       ((char_u **)(fp->uf_lines.ga_data))[j]
 
index 647934d522cb1ea97335270431573c43fad36f3d..7896897a44debd5788204bdf5a298a17ae1dd071 100644 (file)
@@ -761,7 +761,7 @@ script_prof_save(
 {
     scriptitem_T    *si;
 
-    if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len)
+    if (SCRIPT_ID_VALID(current_sctx.sc_sid))
     {
        si = SCRIPT_ITEM(current_sctx.sc_sid);
        if (si->sn_prof_on && si->sn_pr_nest++ == 0)
@@ -778,7 +778,7 @@ script_prof_restore(proftime_T *tm)
 {
     scriptitem_T    *si;
 
-    if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len)
+    if (SCRIPT_ID_VALID(current_sctx.sc_sid))
     {
        si = SCRIPT_ITEM(current_sctx.sc_sid);
        if (si->sn_prof_on && --si->sn_pr_nest == 0)
@@ -903,7 +903,7 @@ script_line_start(void)
     scriptitem_T    *si;
     sn_prl_T       *pp;
 
-    if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len)
+    if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
        return;
     si = SCRIPT_ITEM(current_sctx.sc_sid);
     if (si->sn_prof_on && SOURCING_LNUM >= 1)
@@ -938,7 +938,7 @@ script_line_exec(void)
 {
     scriptitem_T    *si;
 
-    if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len)
+    if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
        return;
     si = SCRIPT_ITEM(current_sctx.sc_sid);
     if (si->sn_prof_on && si->sn_prl_idx >= 0)
@@ -954,7 +954,7 @@ script_line_end(void)
     scriptitem_T    *si;
     sn_prl_T       *pp;
 
-    if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len)
+    if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
        return;
     si = SCRIPT_ITEM(current_sctx.sc_sid);
     if (si->sn_prof_on && si->sn_prl_idx >= 0
index 27d0eb2a52270aa1464e05ebc650ac86ae28a09a..e07523695306bd2782bd610748724ba5d2e0bc80 100644 (file)
@@ -1517,7 +1517,7 @@ ex_scriptnames(exarg_T *eap)
     if (eap->addr_count > 0)
     {
        // :script {scriptId}: edit the script
-       if (eap->line2 < 1 || eap->line2 > script_items.ga_len)
+       if (!SCRIPT_ID_VALID(eap->line2))
            emsg(_(e_invarg));
        else
        {
index 054fe4cbfc16c379dc83dd6076b9d1156ddfc72e..49aacb0fab1d942c6b7905dda60daa67ec1787de 100644 (file)
@@ -4,6 +4,7 @@ source check.vim
 source term_util.vim
 source view_util.vim
 source vim9.vim
+source shared.vim
 
 def Test_syntax()
   let var = 234
@@ -3252,6 +3253,14 @@ def Test_cmdline_win()
   delete('rtp', 'rf')
 enddef
 
+def Test_invalid_sid()
+  assert_fails('func <SNR>1234_func', 'E123:')
+  if RunVim([], ['wq Xdidit'], '+"func <SNR>1_func"')
+    call assert_equal([], readfile('Xdidit'))
+  endif
+  delete('Xdidit')
+enddef
+
 " Keep this last, it messes up highlighting.
 def Test_substitute_cmd()
   new
index 9e3430a10655da69cfadff1f2b74b7edd89eb43c..ba308cdba9113876c08ee6cb0f01dd081e5b76b7 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1539,
 /**/
     1538,
 /**/
index 5e4bfdb76c9e7f205d5644601669069e83a74e50..bec6988e546c0b94852f35454dd27228701b60fe 100644 (file)
@@ -1661,7 +1661,7 @@ get_script_item_idx(int sid, char_u *name, int check_writable)
     int                    idx;
 
     // First look the name up in the hashtable.
-    if (sid <= 0 || sid > script_items.ga_len)
+    if (!SCRIPT_ID_VALID(sid))
        return -1;
     ht = &SCRIPT_VARS(sid);
     di = find_var_in_ht(ht, 0, name, TRUE);
@@ -1692,7 +1692,7 @@ find_imported(char_u *name, size_t len, cctx_T *cctx)
 {
     int                    idx;
 
-    if (current_sctx.sc_sid <= 0)
+    if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
        return NULL;
     if (cctx != NULL)
        for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
@@ -1712,9 +1712,12 @@ find_imported(char_u *name, size_t len, cctx_T *cctx)
     imported_T *
 find_imported_in_script(char_u *name, size_t len, int sid)
 {
-    scriptitem_T    *si = SCRIPT_ITEM(sid);
+    scriptitem_T    *si;
     int                    idx;
 
+    if (!SCRIPT_ID_VALID(sid))
+       return NULL;
+    si = SCRIPT_ITEM(sid);
     for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
     {
        imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
@@ -1966,10 +1969,14 @@ compile_load_scriptvar(
        char_u **end,       // end of variable
        int    error)       // when TRUE may give error
 {
-    scriptitem_T    *si = SCRIPT_ITEM(current_sctx.sc_sid);
-    int                    idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
+    scriptitem_T    *si;
+    int                    idx;
     imported_T     *import;
 
+    if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
+       return FAIL;
+    si = SCRIPT_ITEM(current_sctx.sc_sid);
+    idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
     if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
     {
        // variable is not in sn_var_vals: old style script.
@@ -4750,15 +4757,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                        scriptvar_sid = current_sctx.sc_sid;
                        if (import != NULL)
                            scriptvar_sid = import->imp_sid;
-                       scriptvar_idx = get_script_item_idx(scriptvar_sid,
-                                                               rawname, TRUE);
-                       if (scriptvar_idx >= 0)
+                       if (SCRIPT_ID_VALID(scriptvar_sid))
                        {
-                           scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
-                           svar_T           *sv =
+                           scriptvar_idx = get_script_item_idx(scriptvar_sid,
+                                                               rawname, TRUE);
+                           if (scriptvar_idx > 0)
+                           {
+                               scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
+                               svar_T       *sv =
                                            ((svar_T *)si->sn_var_vals.ga_data)
                                                               + scriptvar_idx;
-                           type = sv->sv_type;
+                               type = sv->sv_type;
+                           }
                        }
                    }
                    else if (name[1] == ':' && name[2] != NUL)