Bram Moolenaar wrote:

> Yukihiro Nakadaira wrote:
>
>> Kana Natsuno wrote:
>> > On Mon, 12 Oct 2009 05:03:27 +0900, Bram Moolenaar <[email protected]> 
>> > wrote:
>> >> Can you somehow simplify the way to reproduce this and send me the Vim
>> >> script for this?
>> >
>> > Sorry, I tried to simplify before reporting but failed.  Because the
>> > problem I encountered seems to depend on the number/order of operations,
>> > and the problem doesn't occur even if I delete a key/value pair
>> > expression from dictionary literal which seems not to be related to
>> > executing scripts.
>> >
>> > Anyway, I'll try to simplify again.
>>
>> Perhaps your problem is ...
>>
>> In eval.c, all "s:" dictionary is stored in one array (ga_scripts).
>> When new script file is sourced, the array is re-allocated for new "s:"
>> dictionary.  Then "s:" dictionary, previously assigned to other variable
>> (e.g. :let g:foo = s:), will become an invalid pointer.
>>
>>
>> Script to reproduce: (might not crash 100%)
>>
>>    let script_vars = []
>>    for src in range(10)
>>      call writefile(['call add(script_vars, s:)'], src)
>>      source `=src`
>>      " allocate memory to ensure crash.
>>      call repeat(' ', 1000)
>>    endfor
>>    echo script_vars
>
> Very good point.  Thanks for finding this problem.  I'll think about a
> solution.  Unless someone beats me to it.

Hi

Crash in eval.c described above was reported a long time ago.

Attached patch fixes it by making ga_scripts in eval.c a growing
array of pointers "scriptvar_T *" rather than growing array of
structs "scriptvar_T" so that when ga_scripts is reallocated,
structures don't move in memory.

I verified that the sample script given by Yukihiro Nakadaira which
always caused a crash (and errors with Valgrind) no longer crashes
after patch (and Valgrind no complain either).

Regards
-- Dominique

-- 
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
diff -r 24100651daa9 runtime/doc/todo.txt
--- a/runtime/doc/todo.txt	Tue Mar 23 18:22:46 2010 +0100
+++ b/runtime/doc/todo.txt	Fri Apr 30 21:59:02 2010 +0200
@@ -62,9 +62,6 @@
 Patch to support netbeans in Unix console Vim. (Xavier de Gaye, 2009 Apr 26)
 Now with Mercurial repository (2010 Jan 2)
 
-Crash when assigning s: to variable, pointer becomes invalid later.
-(Yukihiro Nakadaira, 2009 Oct 12, confirmed by Dominique Pelle)
-
 Test 69 breaks on MS-Windows, both 32 and 64 builds. (George Reilly, 2010 Feb
 26)
 
@@ -175,7 +172,7 @@
 because win_valid() always returns FALSE.  Below win_new_tabpage() in
 ex_docmd.c.
 
-Space before comma in function defenition not allowed: "function x(a , b)"
+Space before comma in function definition not allowed: "function x(a , b)"
 Give a more appropriate error message.  Add a remark to the docs.
 
 string_convert() should be able to convert between utf-8 and utf-16le.  Used
diff -r 24100651daa9 src/eval.c
--- a/src/eval.c	Tue Mar 23 18:22:46 2010 +0100
+++ b/src/eval.c	Fri Apr 30 21:59:02 2010 +0200
@@ -145,9 +145,9 @@
     dict_T	sv_dict;
 } scriptvar_T;
 
-static garray_T	    ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};
-#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])
-#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab)
+static garray_T	    ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
+#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
+#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
 
 static int echo_attr = 0;   /* attributes used for ":echo" */
 
@@ -866,17 +866,21 @@
     hash_init(&vimvarht);  /* garbage_collect() will access it */
     hash_clear(&compat_hashtab);
 
+    free_scriptnames();
+
+    /* global variables */
+    vars_clear(&globvarht);
+
+    /* autoloaded script names */
+    ga_clear_strings(&ga_loaded);
+
     /* script-local variables */
     for (i = 1; i <= ga_scripts.ga_len; ++i)
+    {
 	vars_clear(&SCRIPT_VARS(i));
+	vim_free(SCRIPT_SV(i));
+    }
     ga_clear(&ga_scripts);
-    free_scriptnames();
-
-    /* global variables */
-    vars_clear(&globvarht);
-
-    /* autoloaded script names */
-    ga_clear_strings(&ga_loaded);
 
     /* unreferenced lists and dicts */
     (void)garbage_collect();
@@ -18803,7 +18807,7 @@
 	/* Must be something like "s:", otherwise "ht" would be NULL. */
 	switch (varname[-2])
 	{
-	    case 's': return &SCRIPT_SV(current_SID).sv_var;
+	    case 's': return &SCRIPT_SV(current_SID)->sv_var;
 	    case 'g': return &globvars_var;
 	    case 'v': return &vimvars_var;
 	    case 'b': return &curbuf->b_bufvar;
@@ -18928,13 +18932,14 @@
 	    ht = &SCRIPT_VARS(i);
 	    if (ht->ht_mask == HT_INIT_SIZE - 1)
 		ht->ht_array = ht->ht_smallarray;
-	    sv = &SCRIPT_SV(i);
+	    sv = SCRIPT_SV(i);
 	    sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
 	}
 
 	while (ga_scripts.ga_len < id)
 	{
-	    sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
+	    sv = SCRIPT_SV(ga_scripts.ga_len + 1) = 
+		(scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
 	    init_var_dict(&sv->sv_dict, &sv->sv_var);
 	    ++ga_scripts.ga_len;
 	}
@@ -21931,7 +21936,7 @@
     if (find_viminfo_parameter('!') == NULL)
 	return;
 
-    fprintf(fp, _("\n# global variables:\n"));
+    fputs(_("\n# global variables:\n"), fp);
 
     todo = (int)globvarht.ht_used;
     for (hi = globvarht.ht_array; todo > 0; ++hi)

Raspunde prin e-mail lui