]> git.pld-linux.org Git - packages/vim.git/blob - 7.2.070
- updated to 7.2.102
[packages/vim.git] / 7.2.070
1 To: vim-dev@vim.org
2 Subject: Patch 7.2.070
3 Fcc: outbox
4 From: Bram Moolenaar <Bram@moolenaar.net>
5 Mime-Version: 1.0
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
8 ------------
9
10 Patch 7.2.070
11 Problem:    Crash when a function returns a:000. (Matt Wozkiski)
12 Solution:   Don't put the function struct on the stack, allocate it.  Free it
13             only when nothing in it is used.
14 Files:      src/eval.c
15
16
17 *** ../vim-7.2.069/src/eval.c   Tue Dec  9 10:56:50 2008
18 --- src/eval.c  Wed Dec 17 21:32:26 2008
19 ***************
20 *** 32,37 ****
21 --- 32,40 ----
22   
23   #define DICT_MAXNEST 100      /* maximum nesting of lists and dicts */
24   
25 + #define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not
26 +                                  be freed. */
27
28   /*
29    * In a hashtab item "hi_key" points to "di_key" in a dictitem.
30    * This avoids adding a pointer to the hashtab item.
31 ***************
32 *** 789,794 ****
33 --- 792,799 ----
34   static void func_unref __ARGS((char_u *name));
35   static void func_ref __ARGS((char_u *name));
36   static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
37 + static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
38 + static void free_funccal __ARGS((funccall_T *fc, int free_val));
39   static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
40   static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp));
41   static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
42 ***************
43 *** 923,928 ****
44 --- 928,937 ----
45   /* pointer to funccal for currently active function */
46   funccall_T *current_funccal = NULL;
47   
48 + /* pointer to list of previously used funccal, still around because some
49 +  * item in it is still being used. */
50 + funccall_T *previous_funccal = NULL;
51
52   /*
53    * Return TRUE when a function was ended by a ":return" command.
54    */
55 ***************
56 *** 6490,6496 ****
57       buf_T     *buf;
58       win_T     *wp;
59       int               i;
60 !     funccall_T        *fc;
61       int               did_free = FALSE;
62   #ifdef FEAT_WINDOWS
63       tabpage_T *tp;
64 --- 6499,6505 ----
65       buf_T     *buf;
66       win_T     *wp;
67       int               i;
68 !     funccall_T        *fc, **pfc;
69       int               did_free = FALSE;
70   #ifdef FEAT_WINDOWS
71       tabpage_T *tp;
72 ***************
73 *** 6574,6579 ****
74 --- 6583,6602 ----
75         else
76             ll = ll->lv_used_next;
77   
78 +     /* check if any funccal can be freed now */
79 +     for (pfc = &previous_funccal; *pfc != NULL; )
80 +     {
81 +       if (can_free_funccal(*pfc, copyID))
82 +       {
83 +           fc = *pfc;
84 +           *pfc = fc->caller;
85 +           free_funccal(fc, TRUE);
86 +           did_free = TRUE;
87 +       }
88 +       else
89 +           pfc = &(*pfc)->caller;
90 +     }
91
92       return did_free;
93   }
94   
95 ***************
96 *** 18962,18968 ****
97       dictitem_T        *dict_var;
98   {
99       hash_init(&dict->dv_hashtab);
100 !     dict->dv_refcount = 99999;
101       dict_var->di_tv.vval.v_dict = dict;
102       dict_var->di_tv.v_type = VAR_DICT;
103       dict_var->di_tv.v_lock = VAR_FIXED;
104 --- 18985,18991 ----
105       dictitem_T        *dict_var;
106   {
107       hash_init(&dict->dv_hashtab);
108 !     dict->dv_refcount = DO_NOT_FREE_CNT;
109       dict_var->di_tv.vval.v_dict = dict;
110       dict_var->di_tv.v_type = VAR_DICT;
111       dict_var->di_tv.v_lock = VAR_FIXED;
112 ***************
113 *** 19299,19304 ****
114 --- 19322,19329 ----
115    * Copy the values from typval_T "from" to typval_T "to".
116    * When needed allocates string or increases reference count.
117    * Does not make a copy of a list or dict but copies the reference!
118 +  * It is OK for "from" and "to" to point to the same item.  This is used to
119 +  * make a copy later.
120    */
121       static void
122   copy_tv(from, to)
123 ***************
124 *** 21111,21117 ****
125       char_u    *save_sourcing_name;
126       linenr_T  save_sourcing_lnum;
127       scid_T    save_current_SID;
128 !     funccall_T        fc;
129       int               save_did_emsg;
130       static int        depth = 0;
131       dictitem_T        *v;
132 --- 21136,21142 ----
133       char_u    *save_sourcing_name;
134       linenr_T  save_sourcing_lnum;
135       scid_T    save_current_SID;
136 !     funccall_T        *fc;
137       int               save_did_emsg;
138       static int        depth = 0;
139       dictitem_T        *v;
140 ***************
141 *** 21137,21172 ****
142   
143       line_breakcheck();                /* check for CTRL-C hit */
144   
145 !     fc.caller = current_funccal;
146 !     current_funccal = &fc;
147 !     fc.func = fp;
148 !     fc.rettv = rettv;
149       rettv->vval.v_number = 0;
150 !     fc.linenr = 0;
151 !     fc.returned = FALSE;
152 !     fc.level = ex_nesting_level;
153       /* Check if this function has a breakpoint. */
154 !     fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
155 !     fc.dbg_tick = debug_tick;
156   
157       /*
158 !      * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
159        * with names up to VAR_SHORT_LEN long.  This avoids having to alloc/free
160        * each argument variable and saves a lot of time.
161        */
162       /*
163        * Init l: variables.
164        */
165 !     init_var_dict(&fc.l_vars, &fc.l_vars_var);
166       if (selfdict != NULL)
167       {
168         /* Set l:self to "selfdict".  Use "name" to avoid a warning from
169          * some compiler that checks the destination size. */
170 !       v = &fc.fixvar[fixvar_idx++].var;
171         name = v->di_key;
172         STRCPY(name, "self");
173         v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
174 !       hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
175         v->di_tv.v_type = VAR_DICT;
176         v->di_tv.v_lock = 0;
177         v->di_tv.vval.v_dict = selfdict;
178 --- 21162,21198 ----
179   
180       line_breakcheck();                /* check for CTRL-C hit */
181   
182 !     fc = (funccall_T *)alloc(sizeof(funccall_T));
183 !     fc->caller = current_funccal;
184 !     current_funccal = fc;
185 !     fc->func = fp;
186 !     fc->rettv = rettv;
187       rettv->vval.v_number = 0;
188 !     fc->linenr = 0;
189 !     fc->returned = FALSE;
190 !     fc->level = ex_nesting_level;
191       /* Check if this function has a breakpoint. */
192 !     fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
193 !     fc->dbg_tick = debug_tick;
194   
195       /*
196 !      * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
197        * with names up to VAR_SHORT_LEN long.  This avoids having to alloc/free
198        * each argument variable and saves a lot of time.
199        */
200       /*
201        * Init l: variables.
202        */
203 !     init_var_dict(&fc->l_vars, &fc->l_vars_var);
204       if (selfdict != NULL)
205       {
206         /* Set l:self to "selfdict".  Use "name" to avoid a warning from
207          * some compiler that checks the destination size. */
208 !       v = &fc->fixvar[fixvar_idx++].var;
209         name = v->di_key;
210         STRCPY(name, "self");
211         v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
212 !       hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
213         v->di_tv.v_type = VAR_DICT;
214         v->di_tv.v_lock = 0;
215         v->di_tv.vval.v_dict = selfdict;
216 ***************
217 *** 21178,21208 ****
218        * Set a:0 to "argcount".
219        * Set a:000 to a list with room for the "..." arguments.
220        */
221 !     init_var_dict(&fc.l_avars, &fc.l_avars_var);
222 !     add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
223                                 (varnumber_T)(argcount - fp->uf_args.ga_len));
224       /* Use "name" to avoid a warning from some compiler that checks the
225        * destination size. */
226 !     v = &fc.fixvar[fixvar_idx++].var;
227       name = v->di_key;
228       STRCPY(name, "000");
229       v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
230 !     hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
231       v->di_tv.v_type = VAR_LIST;
232       v->di_tv.v_lock = VAR_FIXED;
233 !     v->di_tv.vval.v_list = &fc.l_varlist;
234 !     vim_memset(&fc.l_varlist, 0, sizeof(list_T));
235 !     fc.l_varlist.lv_refcount = 99999;
236 !     fc.l_varlist.lv_lock = VAR_FIXED;
237   
238       /*
239        * Set a:firstline to "firstline" and a:lastline to "lastline".
240        * Set a:name to named arguments.
241        * Set a:N to the "..." arguments.
242        */
243 !     add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
244                                                       (varnumber_T)firstline);
245 !     add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
246                                                        (varnumber_T)lastline);
247       for (i = 0; i < argcount; ++i)
248       {
249 --- 21204,21234 ----
250        * Set a:0 to "argcount".
251        * Set a:000 to a list with room for the "..." arguments.
252        */
253 !     init_var_dict(&fc->l_avars, &fc->l_avars_var);
254 !     add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
255                                 (varnumber_T)(argcount - fp->uf_args.ga_len));
256       /* Use "name" to avoid a warning from some compiler that checks the
257        * destination size. */
258 !     v = &fc->fixvar[fixvar_idx++].var;
259       name = v->di_key;
260       STRCPY(name, "000");
261       v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
262 !     hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
263       v->di_tv.v_type = VAR_LIST;
264       v->di_tv.v_lock = VAR_FIXED;
265 !     v->di_tv.vval.v_list = &fc->l_varlist;
266 !     vim_memset(&fc->l_varlist, 0, sizeof(list_T));
267 !     fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
268 !     fc->l_varlist.lv_lock = VAR_FIXED;
269   
270       /*
271        * Set a:firstline to "firstline" and a:lastline to "lastline".
272        * Set a:name to named arguments.
273        * Set a:N to the "..." arguments.
274        */
275 !     add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
276                                                       (varnumber_T)firstline);
277 !     add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
278                                                        (varnumber_T)lastline);
279       for (i = 0; i < argcount; ++i)
280       {
281 ***************
282 *** 21218,21224 ****
283         }
284         if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
285         {
286 !           v = &fc.fixvar[fixvar_idx++].var;
287             v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
288         }
289         else
290 --- 21244,21250 ----
291         }
292         if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
293         {
294 !           v = &fc->fixvar[fixvar_idx++].var;
295             v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
296         }
297         else
298 ***************
299 *** 21230,21236 ****
300             v->di_flags = DI_FLAGS_RO;
301         }
302         STRCPY(v->di_key, name);
303 !       hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
304   
305         /* Note: the values are copied directly to avoid alloc/free.
306          * "argvars" must have VAR_FIXED for v_lock. */
307 --- 21256,21262 ----
308             v->di_flags = DI_FLAGS_RO;
309         }
310         STRCPY(v->di_key, name);
311 !       hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
312   
313         /* Note: the values are copied directly to avoid alloc/free.
314          * "argvars" must have VAR_FIXED for v_lock. */
315 ***************
316 *** 21239,21247 ****
317   
318         if (ai >= 0 && ai < MAX_FUNC_ARGS)
319         {
320 !           list_append(&fc.l_varlist, &fc.l_listitems[ai]);
321 !           fc.l_listitems[ai].li_tv = argvars[i];
322 !           fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
323         }
324       }
325   
326 --- 21265,21273 ----
327   
328         if (ai >= 0 && ai < MAX_FUNC_ARGS)
329         {
330 !           list_append(&fc->l_varlist, &fc->l_listitems[ai]);
331 !           fc->l_listitems[ai].li_tv = argvars[i];
332 !           fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED;
333         }
334       }
335   
336 ***************
337 *** 21306,21312 ****
338         if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
339             func_do_profile(fp);
340         if (fp->uf_profiling
341 !                      || (fc.caller != NULL && fc.caller->func->uf_profiling))
342         {
343             ++fp->uf_tm_count;
344             profile_start(&call_start);
345 --- 21332,21338 ----
346         if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
347             func_do_profile(fp);
348         if (fp->uf_profiling
349 !                   || (fc->caller != NULL && fc->caller->func->uf_profiling))
350         {
351             ++fp->uf_tm_count;
352             profile_start(&call_start);
353 ***************
354 *** 21322,21328 ****
355       did_emsg = FALSE;
356   
357       /* call do_cmdline() to execute the lines */
358 !     do_cmdline(NULL, get_func_line, (void *)&fc,
359                                      DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
360   
361       --RedrawingDisabled;
362 --- 21348,21354 ----
363       did_emsg = FALSE;
364   
365       /* call do_cmdline() to execute the lines */
366 !     do_cmdline(NULL, get_func_line, (void *)fc,
367                                      DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
368   
369       --RedrawingDisabled;
370 ***************
371 *** 21337,21352 ****
372   
373   #ifdef FEAT_PROFILE
374       if (do_profiling == PROF_YES && (fp->uf_profiling
375 !                   || (fc.caller != NULL && fc.caller->func->uf_profiling)))
376       {
377         profile_end(&call_start);
378         profile_sub_wait(&wait_start, &call_start);
379         profile_add(&fp->uf_tm_total, &call_start);
380         profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
381 !       if (fc.caller != NULL && fc.caller->func->uf_profiling)
382         {
383 !           profile_add(&fc.caller->func->uf_tm_children, &call_start);
384 !           profile_add(&fc.caller->func->uf_tml_children, &call_start);
385         }
386       }
387   #endif
388 --- 21363,21378 ----
389   
390   #ifdef FEAT_PROFILE
391       if (do_profiling == PROF_YES && (fp->uf_profiling
392 !                   || (fc->caller != NULL && fc->caller->func->uf_profiling)))
393       {
394         profile_end(&call_start);
395         profile_sub_wait(&wait_start, &call_start);
396         profile_add(&fp->uf_tm_total, &call_start);
397         profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
398 !       if (fc->caller != NULL && fc->caller->func->uf_profiling)
399         {
400 !           profile_add(&fc->caller->func->uf_tm_children, &call_start);
401 !           profile_add(&fc->caller->func->uf_tml_children, &call_start);
402         }
403       }
404   #endif
405 ***************
406 *** 21359,21367 ****
407   
408         if (aborting())
409             smsg((char_u *)_("%s aborted"), sourcing_name);
410 !       else if (fc.rettv->v_type == VAR_NUMBER)
411             smsg((char_u *)_("%s returning #%ld"), sourcing_name,
412 !                                              (long)fc.rettv->vval.v_number);
413         else
414         {
415             char_u      buf[MSG_BUF_LEN];
416 --- 21385,21393 ----
417   
418         if (aborting())
419             smsg((char_u *)_("%s aborted"), sourcing_name);
420 !       else if (fc->rettv->v_type == VAR_NUMBER)
421             smsg((char_u *)_("%s returning #%ld"), sourcing_name,
422 !                                              (long)fc->rettv->vval.v_number);
423         else
424         {
425             char_u      buf[MSG_BUF_LEN];
426 ***************
427 *** 21372,21378 ****
428             /* The value may be very long.  Skip the middle part, so that we
429              * have some idea how it starts and ends. smsg() would always
430              * truncate it at the end. */
431 !           s = tv2string(fc.rettv, &tofree, numbuf2, 0);
432             if (s != NULL)
433             {
434                 trunc_string(s, buf, MSG_BUF_CLEN);
435 --- 21398,21404 ----
436             /* The value may be very long.  Skip the middle part, so that we
437              * have some idea how it starts and ends. smsg() would always
438              * truncate it at the end. */
439 !           s = tv2string(fc->rettv, &tofree, numbuf2, 0);
440             if (s != NULL)
441             {
442                 trunc_string(s, buf, MSG_BUF_CLEN);
443 ***************
444 *** 21408,21421 ****
445       }
446   
447       did_emsg |= save_did_emsg;
448 !     current_funccal = fc.caller;
449   
450 !     /* The a: variables typevals were not allocated, only free the allocated
451 !      * variables. */
452 !     vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
453   
454 !     vars_clear(&fc.l_vars.dv_hashtab);                /* free all l: variables */
455 !     --depth;
456   }
457   
458   /*
459 --- 21434,21517 ----
460       }
461   
462       did_emsg |= save_did_emsg;
463 !     current_funccal = fc->caller;
464 !     --depth;
465   
466 !     /* if the a:000 list and the a: dict are not referenced we can free the
467 !      * funccall_T and what's in it. */
468 !     if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
469 !           && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
470 !           && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
471 !     {
472 !       free_funccal(fc, FALSE);
473 !     }
474 !     else
475 !     {
476 !       hashitem_T      *hi;
477 !       listitem_T      *li;
478 !       int             todo;
479   
480 !       /* "fc" is still in use.  This can happen when returning "a:000" or
481 !        * assigning "l:" to a global variable.
482 !        * Link "fc" in the list for garbage collection later. */
483 !       fc->caller = previous_funccal;
484 !       previous_funccal = fc;
485
486 !       /* Make a copy of the a: variables, since we didn't do that above. */
487 !       todo = (int)fc->l_avars.dv_hashtab.ht_used;
488 !       for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
489 !       {
490 !           if (!HASHITEM_EMPTY(hi))
491 !           {
492 !               --todo;
493 !               v = HI2DI(hi);
494 !               copy_tv(&v->di_tv, &v->di_tv);
495 !           }
496 !       }
497
498 !       /* Make a copy of the a:000 items, since we didn't do that above. */
499 !       for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
500 !           copy_tv(&li->li_tv, &li->li_tv);
501 !     }
502 ! }
503
504 ! /*
505 !  * Return TRUE if items in "fc" do not have "copyID".  That means they are not
506 !  * referenced from anywyere.
507 !  */
508 !     static int
509 ! can_free_funccal(fc, copyID)
510 !     funccall_T        *fc;
511 !     int               copyID;
512 ! {
513 !     return (fc->l_varlist.lv_copyID != copyID
514 !           && fc->l_vars.dv_copyID != copyID
515 !           && fc->l_avars.dv_copyID != copyID);
516 ! }
517
518 ! /*
519 !  * Free "fc" and what it contains.
520 !  */
521 !    static void
522 ! free_funccal(fc, free_val)
523 !     funccall_T        *fc;
524 !     int               free_val;  /* a: vars were allocated */
525 ! {
526 !     listitem_T        *li;
527
528 !     /* The a: variables typevals may not have been allocated, only free the
529 !      * allocated variables. */
530 !     vars_clear_ext(&fc->l_avars.dv_hashtab, free_val);
531
532 !     /* free all l: variables */
533 !     vars_clear(&fc->l_vars.dv_hashtab);
534
535 !     /* Free the a:000 variables if they were allocated. */
536 !     if (free_val)
537 !       for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
538 !           clear_tv(&li->li_tv);
539
540 !     vim_free(fc);
541   }
542   
543   /*
544 *** ../vim-7.2.069/src/version.c        Tue Dec  9 22:34:02 2008
545 --- src/version.c       Sun Dec 21 12:47:07 2008
546 ***************
547 *** 678,679 ****
548 --- 678,681 ----
549   {   /* Add new patch number below this line */
550 + /**/
551 +     70,
552   /**/
553
554 -- 
555 Close your shells, or I'll kill -9 you
556 Tomorrow I'll quota you
557 Remember the disks'll always be full
558 And then while I'm away
559 I'll write ~ everyday
560 And I'll send-pr all my buggings to you.
561     [ CVS log "Beatles style" for FreeBSD ports/INDEX, Satoshi Asami ]
562
563  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
564 ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
565 \\\        download, build and distribute -- http://www.A-A-P.org        ///
566  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
This page took 0.121125 seconds and 3 git commands to generate.