]> git.pld-linux.org Git - packages/vim.git/blob - 7.2.188
- new
[packages/vim.git] / 7.2.188
1 To: vim-dev@vim.org
2 Subject: Patch 7.2.188
3 Fcc: outbox
4 From: Bram Moolenaar <Bram@moolenaar.net>
5 Mime-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8 ------------
9
10 Patch 7.2.188
11 Problem:    Crash with specific use of function calls. (Meikel Brandmeyer)
12 Solution:   Make sure the items referenced by a function call are not freed
13             twice.  (based on patch from Nico Weber)
14 Files:      src/eval.c
15
16
17 *** ../vim-7.2.187/src/eval.c   2009-05-16 17:29:37.000000000 +0200
18 --- src/eval.c  2009-05-22 20:04:22.000000000 +0200
19 ***************
20 *** 129,136 ****
21 --- 129,139 ----
22   /*
23    * When recursively copying lists and dicts we need to remember which ones we
24    * have done to avoid endless recursiveness.  This unique ID is used for that.
25 +  * The last bit is used for previous_funccal, ignored when comparing.
26    */
27   static int current_copyID = 0;
28 + #define COPYID_INC 2
29 + #define COPYID_MASK (~0x1)
30   
31   /*
32    * Array to hold the hashtab with variables local to each sourced script.
33 ***************
34 *** 439,444 ****
35 --- 442,448 ----
36   static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
37   static char_u *list2string __ARGS((typval_T *tv, int copyID));
38   static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
39 + static int free_unref_items __ARGS((int copyID));
40   static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
41   static void set_ref_in_list __ARGS((list_T *l, int copyID));
42   static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
43 ***************
44 *** 6494,6507 ****
45       int
46   garbage_collect()
47   {
48 !     dict_T    *dd;
49 !     list_T    *ll;
50 !     int               copyID = ++current_copyID;
51       buf_T     *buf;
52       win_T     *wp;
53       int               i;
54       funccall_T        *fc, **pfc;
55 !     int               did_free = FALSE;
56   #ifdef FEAT_WINDOWS
57       tabpage_T *tp;
58   #endif
59 --- 6498,6510 ----
60       int
61   garbage_collect()
62   {
63 !     int               copyID;
64       buf_T     *buf;
65       win_T     *wp;
66       int               i;
67       funccall_T        *fc, **pfc;
68 !     int               did_free;
69 !     int               did_free_funccal = FALSE;
70   #ifdef FEAT_WINDOWS
71       tabpage_T *tp;
72   #endif
73 ***************
74 *** 6511,6520 ****
75 --- 6514,6538 ----
76       may_garbage_collect = FALSE;
77       garbage_collect_at_exit = FALSE;
78   
79 +     /* We advance by two because we add one for items referenced through
80 +      * previous_funccal. */
81 +     current_copyID += COPYID_INC;
82 +     copyID = current_copyID;
83
84       /*
85        * 1. Go through all accessible variables and mark all lists and dicts
86        *    with copyID.
87        */
88
89 +     /* Don't free variables in the previous_funccal list unless they are only
90 +      * referenced through previous_funccal.  This must be first, because if
91 +      * the item is referenced elsewhere it must not be freed. */
92 +     for (fc = previous_funccal; fc != NULL; fc = fc->caller)
93 +     {
94 +       set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
95 +       set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
96 +     }
97
98       /* script-local variables */
99       for (i = 1; i <= ga_scripts.ga_len; ++i)
100         set_ref_in_ht(&SCRIPT_VARS(i), copyID);
101 ***************
102 *** 6546,6556 ****
103       /* v: vars */
104       set_ref_in_ht(&vimvarht, copyID);
105   
106       /*
107 !      * 2. Go through the list of dicts and free items without the copyID.
108        */
109       for (dd = first_dict; dd != NULL; )
110 !       if (dd->dv_copyID != copyID)
111         {
112             /* Free the Dictionary and ordinary items it contains, but don't
113              * recurse into Lists and Dictionaries, they will be in the list
114 --- 6564,6610 ----
115       /* v: vars */
116       set_ref_in_ht(&vimvarht, copyID);
117   
118 +     /* Free lists and dictionaries that are not referenced. */
119 +     did_free = free_unref_items(copyID);
120
121 +     /* check if any funccal can be freed now */
122 +     for (pfc = &previous_funccal; *pfc != NULL; )
123 +     {
124 +       if (can_free_funccal(*pfc, copyID))
125 +       {
126 +           fc = *pfc;
127 +           *pfc = fc->caller;
128 +           free_funccal(fc, TRUE);
129 +           did_free = TRUE;
130 +           did_free_funccal = TRUE;
131 +       }
132 +       else
133 +           pfc = &(*pfc)->caller;
134 +     }
135 +     if (did_free_funccal)
136 +       /* When a funccal was freed some more items might be garbage
137 +        * collected, so run again. */
138 +       (void)garbage_collect();
139
140 +     return did_free;
141 + }
142
143 + /*
144 +  * Free lists and dictionaries that are no longer referenced.
145 +  */
146 +     static int
147 + free_unref_items(copyID)
148 +     int copyID;
149 + {
150 +     dict_T    *dd;
151 +     list_T    *ll;
152 +     int               did_free = FALSE;
153
154       /*
155 !      * Go through the list of dicts and free items without the copyID.
156        */
157       for (dd = first_dict; dd != NULL; )
158 !       if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
159         {
160             /* Free the Dictionary and ordinary items it contains, but don't
161              * recurse into Lists and Dictionaries, they will be in the list
162 ***************
163 *** 6565,6576 ****
164             dd = dd->dv_used_next;
165   
166       /*
167 !      * 3. Go through the list of lists and free items without the copyID.
168 !      *    But don't free a list that has a watcher (used in a for loop), these
169 !      *    are not referenced anywhere.
170        */
171       for (ll = first_list; ll != NULL; )
172 !       if (ll->lv_copyID != copyID && ll->lv_watch == NULL)
173         {
174             /* Free the List and ordinary items it contains, but don't recurse
175              * into Lists and Dictionaries, they will be in the list of dicts
176 --- 6619,6631 ----
177             dd = dd->dv_used_next;
178   
179       /*
180 !      * Go through the list of lists and free items without the copyID.
181 !      * But don't free a list that has a watcher (used in a for loop), these
182 !      * are not referenced anywhere.
183        */
184       for (ll = first_list; ll != NULL; )
185 !       if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
186 !                                                     && ll->lv_watch == NULL)
187         {
188             /* Free the List and ordinary items it contains, but don't recurse
189              * into Lists and Dictionaries, they will be in the list of dicts
190 ***************
191 *** 6584,6603 ****
192         else
193             ll = ll->lv_used_next;
194   
195 -     /* check if any funccal can be freed now */
196 -     for (pfc = &previous_funccal; *pfc != NULL; )
197 -     {
198 -       if (can_free_funccal(*pfc, copyID))
199 -       {
200 -           fc = *pfc;
201 -           *pfc = fc->caller;
202 -           free_funccal(fc, TRUE);
203 -           did_free = TRUE;
204 -       }
205 -       else
206 -           pfc = &(*pfc)->caller;
207 -     }
208
209       return did_free;
210   }
211   
212 --- 6639,6644 ----
213 ***************
214 *** 18842,18847 ****
215 --- 18883,18889 ----
216   {
217       hash_init(&dict->dv_hashtab);
218       dict->dv_refcount = DO_NOT_FREE_CNT;
219 +     dict->dv_copyID = 0;
220       dict_var->di_tv.vval.v_dict = dict;
221       dict_var->di_tv.v_type = VAR_DICT;
222       dict_var->di_tv.v_lock = VAR_FIXED;
223 ***************
224 *** 21294,21301 ****
225       current_funccal = fc->caller;
226       --depth;
227   
228 !     /* if the a:000 list and the a: dict are not referenced we can free the
229 !      * funccall_T and what's in it. */
230       if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
231             && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
232             && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
233 --- 21336,21343 ----
234       current_funccal = fc->caller;
235       --depth;
236   
237 !     /* If the a:000 list and the l: and a: dicts are not referenced we can
238 !      * free the funccall_T and what's in it. */
239       if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
240             && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
241             && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
242 ***************
243 *** 21334,21340 ****
244   
245   /*
246    * Return TRUE if items in "fc" do not have "copyID".  That means they are not
247 !  * referenced from anywhere.
248    */
249       static int
250   can_free_funccal(fc, copyID)
251 --- 21376,21382 ----
252   
253   /*
254    * Return TRUE if items in "fc" do not have "copyID".  That means they are not
255 !  * referenced from anywhere that is in use.
256    */
257       static int
258   can_free_funccal(fc, copyID)
259 *** ../vim-7.2.187/src/version.c        2009-05-23 14:27:43.000000000 +0200
260 --- src/version.c       2009-05-24 13:20:49.000000000 +0200
261 ***************
262 *** 678,679 ****
263 --- 678,681 ----
264   {   /* Add new patch number below this line */
265 + /**/
266 +     188,
267   /**/
268
269 -- 
270 ARTHUR:    ... and I am your king ....
271 OLD WOMAN: Ooooh!  I didn't know we had a king.  I thought we were an
272            autonomous collective ...
273                  "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
274
275  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
276 ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
277 \\\        download, build and distribute -- http://www.A-A-P.org        ///
278  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
This page took 0.041302 seconds and 3 git commands to generate.