]>
Commit | Line | Data |
---|---|---|
46534d20 AM |
1 | To: vim_dev@googlegroups.com |
2 | Subject: Patch 7.3.603 | |
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.3.603 | |
11 | Problem: It is possible to add replace builtin functions by calling | |
12 | extend() on g:. | |
13 | Solution: Add a flag to a dict to indicate it is a scope. Check for | |
14 | existing functions. (ZyX) | |
15 | Files: src/buffer.c, src/eval.c, src/proto/eval.pro, src/structs.h, | |
16 | src/testdir/test34.in, src/testdir/test34.ok, src/window.c | |
17 | ||
18 | ||
19 | *** ../vim-7.3.602/src/buffer.c 2012-07-10 15:18:18.000000000 +0200 | |
20 | --- src/buffer.c 2012-07-16 16:52:58.000000000 +0200 | |
21 | *************** | |
22 | *** 1747,1753 **** | |
23 | buf->b_wininfo->wi_win = curwin; | |
24 | ||
25 | #ifdef FEAT_EVAL | |
26 | ! init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */ | |
27 | #endif | |
28 | #ifdef FEAT_SYN_HL | |
29 | hash_init(&buf->b_s.b_keywtab); | |
30 | --- 1747,1754 ---- | |
31 | buf->b_wininfo->wi_win = curwin; | |
32 | ||
33 | #ifdef FEAT_EVAL | |
34 | ! /* init b: variables */ | |
35 | ! init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE); | |
36 | #endif | |
37 | #ifdef FEAT_SYN_HL | |
38 | hash_init(&buf->b_s.b_keywtab); | |
39 | *** ../vim-7.3.602/src/eval.c 2012-07-10 13:41:09.000000000 +0200 | |
40 | --- src/eval.c 2012-07-16 17:18:11.000000000 +0200 | |
41 | *************** | |
42 | *** 850,857 **** | |
43 | int i; | |
44 | struct vimvar *p; | |
45 | ||
46 | ! init_var_dict(&globvardict, &globvars_var); | |
47 | ! init_var_dict(&vimvardict, &vimvars_var); | |
48 | vimvardict.dv_lock = VAR_FIXED; | |
49 | hash_init(&compat_hashtab); | |
50 | hash_init(&func_hashtab); | |
51 | --- 850,857 ---- | |
52 | int i; | |
53 | struct vimvar *p; | |
54 | ||
55 | ! init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); | |
56 | ! init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE); | |
57 | vimvardict.dv_lock = VAR_FIXED; | |
58 | hash_init(&compat_hashtab); | |
59 | hash_init(&func_hashtab); | |
60 | *************** | |
61 | *** 2725,2738 **** | |
62 | lp->ll_dict = lp->ll_tv->vval.v_dict; | |
63 | lp->ll_di = dict_find(lp->ll_dict, key, len); | |
64 | ||
65 | ! /* When assigning to g: check that a function and variable name is | |
66 | ! * valid. */ | |
67 | ! if (rettv != NULL && lp->ll_dict == &globvardict) | |
68 | { | |
69 | ! if (rettv->v_type == VAR_FUNC | |
70 | && var_check_func_name(key, lp->ll_di == NULL)) | |
71 | ! return NULL; | |
72 | ! if (!valid_varname(key)) | |
73 | return NULL; | |
74 | } | |
75 | ||
76 | --- 2725,2750 ---- | |
77 | lp->ll_dict = lp->ll_tv->vval.v_dict; | |
78 | lp->ll_di = dict_find(lp->ll_dict, key, len); | |
79 | ||
80 | ! /* When assigning to a scope dictionary check that a function and | |
81 | ! * variable name is valid (only variable name unless it is l: or | |
82 | ! * g: dictionary). Disallow overwriting a builtin function. */ | |
83 | ! if (rettv != NULL && lp->ll_dict->dv_scope != 0) | |
84 | { | |
85 | ! int prevval; | |
86 | ! int wrong; | |
87 | ! | |
88 | ! if (len != -1) | |
89 | ! { | |
90 | ! prevval = key[len]; | |
91 | ! key[len] = NUL; | |
92 | ! } | |
93 | ! wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE | |
94 | ! && rettv->v_type == VAR_FUNC | |
95 | && var_check_func_name(key, lp->ll_di == NULL)) | |
96 | ! || !valid_varname(key); | |
97 | ! if (len != -1) | |
98 | ! key[len] = prevval; | |
99 | ! if (wrong) | |
100 | return NULL; | |
101 | } | |
102 | ||
103 | *************** | |
104 | *** 6951,6957 **** | |
105 | d = (dict_T *)alloc(sizeof(dict_T)); | |
106 | if (d != NULL) | |
107 | { | |
108 | ! /* Add the list to the list of dicts for garbage collection. */ | |
109 | if (first_dict != NULL) | |
110 | first_dict->dv_used_prev = d; | |
111 | d->dv_used_next = first_dict; | |
112 | --- 6963,6969 ---- | |
113 | d = (dict_T *)alloc(sizeof(dict_T)); | |
114 | if (d != NULL) | |
115 | { | |
116 | ! /* Add the dict to the list of dicts for garbage collection. */ | |
117 | if (first_dict != NULL) | |
118 | first_dict->dv_used_prev = d; | |
119 | d->dv_used_next = first_dict; | |
120 | *************** | |
121 | *** 6960,6965 **** | |
122 | --- 6972,6978 ---- | |
123 | ||
124 | hash_init(&d->dv_hashtab); | |
125 | d->dv_lock = 0; | |
126 | + d->dv_scope = 0; | |
127 | d->dv_refcount = 0; | |
128 | d->dv_copyID = 0; | |
129 | } | |
130 | *************** | |
131 | *** 10203,10208 **** | |
132 | --- 10216,10234 ---- | |
133 | { | |
134 | --todo; | |
135 | di1 = dict_find(d1, hi2->hi_key, -1); | |
136 | + if (d1->dv_scope != 0) | |
137 | + { | |
138 | + /* Disallow replacing a builtin function in l: and g:. | |
139 | + * Check the key to be valid when adding to any | |
140 | + * scope. */ | |
141 | + if (d1->dv_scope == VAR_DEF_SCOPE | |
142 | + && HI2DI(hi2)->di_tv.v_type == VAR_FUNC | |
143 | + && var_check_func_name(hi2->hi_key, | |
144 | + di1 == NULL)) | |
145 | + break; | |
146 | + if (!valid_varname(hi2->hi_key)) | |
147 | + break; | |
148 | + } | |
149 | if (di1 == NULL) | |
150 | { | |
151 | di1 = dictitem_copy(HI2DI(hi2)); | |
152 | *************** | |
153 | *** 20027,20033 **** | |
154 | { | |
155 | sv = SCRIPT_SV(ga_scripts.ga_len + 1) = | |
156 | (scriptvar_T *)alloc_clear(sizeof(scriptvar_T)); | |
157 | ! init_var_dict(&sv->sv_dict, &sv->sv_var); | |
158 | ++ga_scripts.ga_len; | |
159 | } | |
160 | } | |
161 | --- 20053,20059 ---- | |
162 | { | |
163 | sv = SCRIPT_SV(ga_scripts.ga_len + 1) = | |
164 | (scriptvar_T *)alloc_clear(sizeof(scriptvar_T)); | |
165 | ! init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); | |
166 | ++ga_scripts.ga_len; | |
167 | } | |
168 | } | |
169 | *************** | |
170 | *** 20038,20049 **** | |
171 | * point to it. | |
172 | */ | |
173 | void | |
174 | ! init_var_dict(dict, dict_var) | |
175 | dict_T *dict; | |
176 | dictitem_T *dict_var; | |
177 | { | |
178 | hash_init(&dict->dv_hashtab); | |
179 | dict->dv_lock = 0; | |
180 | dict->dv_refcount = DO_NOT_FREE_CNT; | |
181 | dict->dv_copyID = 0; | |
182 | dict_var->di_tv.vval.v_dict = dict; | |
183 | --- 20064,20077 ---- | |
184 | * point to it. | |
185 | */ | |
186 | void | |
187 | ! init_var_dict(dict, dict_var, scope) | |
188 | dict_T *dict; | |
189 | dictitem_T *dict_var; | |
190 | + int scope; | |
191 | { | |
192 | hash_init(&dict->dv_hashtab); | |
193 | dict->dv_lock = 0; | |
194 | + dict->dv_scope = scope; | |
195 | dict->dv_refcount = DO_NOT_FREE_CNT; | |
196 | dict->dv_copyID = 0; | |
197 | dict_var->di_tv.vval.v_dict = dict; | |
198 | *************** | |
199 | *** 22304,22310 **** | |
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 | --- 22332,22338 ---- | |
208 | /* | |
209 | * Init l: variables. | |
210 | */ | |
211 | ! init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); | |
212 | if (selfdict != NULL) | |
213 | { | |
214 | /* Set l:self to "selfdict". Use "name" to avoid a warning from | |
215 | *************** | |
216 | *** 22325,22331 **** | |
217 | * Set a:0 to "argcount". | |
218 | * Set a:000 to a list with room for the "..." arguments. | |
219 | */ | |
220 | ! init_var_dict(&fc->l_avars, &fc->l_avars_var); | |
221 | add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", | |
222 | (varnumber_T)(argcount - fp->uf_args.ga_len)); | |
223 | /* Use "name" to avoid a warning from some compiler that checks the | |
224 | --- 22353,22359 ---- | |
225 | * Set a:0 to "argcount". | |
226 | * Set a:000 to a list with room for the "..." arguments. | |
227 | */ | |
228 | ! init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); | |
229 | add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", | |
230 | (varnumber_T)(argcount - fp->uf_args.ga_len)); | |
231 | /* Use "name" to avoid a warning from some compiler that checks the | |
232 | *** ../vim-7.3.602/src/proto/eval.pro 2012-06-29 12:54:32.000000000 +0200 | |
233 | --- src/proto/eval.pro 2012-07-16 16:55:16.000000000 +0200 | |
234 | *************** | |
235 | *** 93,99 **** | |
236 | char_u *get_tv_string_chk __ARGS((typval_T *varp)); | |
237 | char_u *get_var_value __ARGS((char_u *name)); | |
238 | void new_script_vars __ARGS((scid_T id)); | |
239 | ! void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var)); | |
240 | void vars_clear __ARGS((hashtab_T *ht)); | |
241 | void copy_tv __ARGS((typval_T *from, typval_T *to)); | |
242 | void ex_echo __ARGS((exarg_T *eap)); | |
243 | --- 93,99 ---- | |
244 | char_u *get_tv_string_chk __ARGS((typval_T *varp)); | |
245 | char_u *get_var_value __ARGS((char_u *name)); | |
246 | void new_script_vars __ARGS((scid_T id)); | |
247 | ! void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope)); | |
248 | void vars_clear __ARGS((hashtab_T *ht)); | |
249 | void copy_tv __ARGS((typval_T *from, typval_T *to)); | |
250 | void ex_echo __ARGS((exarg_T *eap)); | |
251 | *** ../vim-7.3.602/src/structs.h 2012-06-06 19:02:40.000000000 +0200 | |
252 | --- src/structs.h 2012-07-16 16:56:43.000000000 +0200 | |
253 | *************** | |
254 | *** 1106,1111 **** | |
255 | --- 1106,1116 ---- | |
256 | #define VAR_DICT 5 /* "v_dict" is used */ | |
257 | #define VAR_FLOAT 6 /* "v_float" is used */ | |
258 | ||
259 | + /* Values for "dv_scope". */ | |
260 | + #define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */ | |
261 | + #define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not | |
262 | + allowed to mask existing functions */ | |
263 | + | |
264 | /* Values for "v_lock". */ | |
265 | #define VAR_LOCKED 1 /* locked with lock(), can use unlock() */ | |
266 | #define VAR_FIXED 2 /* locked forever */ | |
267 | *************** | |
268 | *** 1181,1186 **** | |
269 | --- 1186,1192 ---- | |
270 | int dv_copyID; /* ID used by deepcopy() */ | |
271 | dict_T *dv_copydict; /* copied dict used by deepcopy() */ | |
272 | char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */ | |
273 | + char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */ | |
274 | dict_T *dv_used_next; /* next dict in used dicts list */ | |
275 | dict_T *dv_used_prev; /* previous dict in used dicts list */ | |
276 | }; | |
277 | *** ../vim-7.3.602/src/testdir/test34.in 2010-08-15 21:57:29.000000000 +0200 | |
278 | --- src/testdir/test34.in 2012-07-16 16:51:29.000000000 +0200 | |
279 | *************** | |
280 | *** 1,5 **** | |
281 | --- 1,6 ---- | |
282 | Test for user functions. | |
283 | Also test an <expr> mapping calling a function. | |
284 | + Also test that a builtin function cannot be replaced. | |
285 | ||
286 | STARTTEST | |
287 | :so small.vim | |
288 | *************** | |
289 | *** 58,64 **** | |
290 | ---*--- | |
291 | (one | |
292 | (two | |
293 | ! [(one again\e:$-5,$w! test.out | |
294 | :delfunc Table | |
295 | :delfunc Compute | |
296 | :delfunc Expr1 | |
297 | --- 59,68 ---- | |
298 | ---*--- | |
299 | (one | |
300 | (two | |
301 | ! [(one again\e:call append(line('$'), max([1, 2, 3])) | |
302 | ! :call extend(g:, {'max': function('min')}) | |
303 | ! :call append(line('$'), max([1, 2, 3])) | |
304 | ! :$-7,$w! test.out | |
305 | :delfunc Table | |
306 | :delfunc Compute | |
307 | :delfunc Expr1 | |
308 | *** ../vim-7.3.602/src/testdir/test34.ok 2011-10-12 22:02:07.000000000 +0200 | |
309 | --- src/testdir/test34.ok 2012-07-16 16:43:15.000000000 +0200 | |
310 | *************** | |
311 | *** 4,6 **** | |
312 | --- 4,8 ---- | |
313 | 1. one | |
314 | 2. two | |
315 | 1. one again | |
316 | + 3 | |
317 | + 3 | |
318 | *** ../vim-7.3.602/src/window.c 2012-07-06 18:27:34.000000000 +0200 | |
319 | --- src/window.c 2012-07-16 16:53:45.000000000 +0200 | |
320 | *************** | |
321 | *** 3468,3474 **** | |
322 | # endif | |
323 | #ifdef FEAT_EVAL | |
324 | /* init t: variables */ | |
325 | ! init_var_dict(&tp->tp_vars, &tp->tp_winvar); | |
326 | #endif | |
327 | tp->tp_ch_used = p_ch; | |
328 | } | |
329 | --- 3468,3474 ---- | |
330 | # endif | |
331 | #ifdef FEAT_EVAL | |
332 | /* init t: variables */ | |
333 | ! init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE); | |
334 | #endif | |
335 | tp->tp_ch_used = p_ch; | |
336 | } | |
337 | *************** | |
338 | *** 4410,4416 **** | |
339 | #endif | |
340 | #ifdef FEAT_EVAL | |
341 | /* init w: variables */ | |
342 | ! init_var_dict(&new_wp->w_vars, &new_wp->w_winvar); | |
343 | #endif | |
344 | #ifdef FEAT_FOLDING | |
345 | foldInitWin(new_wp); | |
346 | --- 4410,4416 ---- | |
347 | #endif | |
348 | #ifdef FEAT_EVAL | |
349 | /* init w: variables */ | |
350 | ! init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE); | |
351 | #endif | |
352 | #ifdef FEAT_FOLDING | |
353 | foldInitWin(new_wp); | |
354 | *** ../vim-7.3.602/src/version.c 2012-07-16 17:27:57.000000000 +0200 | |
355 | --- src/version.c 2012-07-16 17:29:06.000000000 +0200 | |
356 | *************** | |
357 | *** 716,717 **** | |
358 | --- 716,719 ---- | |
359 | { /* Add new patch number below this line */ | |
360 | + /**/ | |
361 | + 603, | |
362 | /**/ | |
363 | ||
364 | -- | |
365 | Birthdays are healthy. The more you have them, the longer you live. | |
366 | ||
367 | /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ | |
368 | /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ | |
369 | \\\ an exciting new programming language -- http://www.Zimbu.org /// | |
370 | \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |