Mercurial > vim
comparison src/eval.c @ 29771:c71a42be2d7f v9.0.0225
patch 9.0.0225: using freed memory with multiple line breaks in expression
Commit: https://github.com/vim/vim/commit/91c7cbfe31bbef57d5fcf7d76989fc159f73ef15
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Aug 18 13:28:31 2022 +0100
patch 9.0.0225: using freed memory with multiple line breaks in expression
Problem: Using freed memory with multiple line breaks in expression.
Solution: Free eval_tofree later.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 18 Aug 2022 14:30:05 +0200 |
parents | 9d54c8e6c682 |
children | 6b7020f3d856 |
comparison
equal
deleted
inserted
replaced
29770:653c04c1dcf1 | 29771:c71a42be2d7f |
---|---|
352 | 352 |
353 return retval; | 353 return retval; |
354 } | 354 } |
355 | 355 |
356 /* | 356 /* |
357 * Initialize "evalarg" for use. | |
358 */ | |
359 void | |
360 init_evalarg(evalarg_T *evalarg) | |
361 { | |
362 CLEAR_POINTER(evalarg); | |
363 ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20); | |
364 } | |
365 | |
366 /* | |
367 * If "evalarg->eval_tofree" is not NULL free it later. | |
368 * Caller is expected to overwrite "evalarg->eval_tofree" next. | |
369 */ | |
370 static void | |
371 free_eval_tofree_later(evalarg_T *evalarg) | |
372 { | |
373 if (evalarg->eval_tofree != NULL) | |
374 { | |
375 if (ga_grow(&evalarg->eval_tofree_ga, 1) == OK) | |
376 ((char_u **)evalarg->eval_tofree_ga.ga_data) | |
377 [evalarg->eval_tofree_ga.ga_len++] | |
378 = evalarg->eval_tofree; | |
379 else | |
380 vim_free(evalarg->eval_tofree); | |
381 } | |
382 } | |
383 | |
384 /* | |
385 * After using "evalarg" filled from "eap": free the memory. | |
386 */ | |
387 void | |
388 clear_evalarg(evalarg_T *evalarg, exarg_T *eap) | |
389 { | |
390 if (evalarg != NULL) | |
391 { | |
392 if (evalarg->eval_tofree != NULL) | |
393 { | |
394 if (eap != NULL) | |
395 { | |
396 // We may need to keep the original command line, e.g. for | |
397 // ":let" it has the variable names. But we may also need the | |
398 // new one, "nextcmd" points into it. Keep both. | |
399 vim_free(eap->cmdline_tofree); | |
400 eap->cmdline_tofree = *eap->cmdlinep; | |
401 *eap->cmdlinep = evalarg->eval_tofree; | |
402 } | |
403 else | |
404 vim_free(evalarg->eval_tofree); | |
405 evalarg->eval_tofree = NULL; | |
406 } | |
407 | |
408 ga_clear_strings(&evalarg->eval_tofree_ga); | |
409 VIM_CLEAR(evalarg->eval_tofree_lambda); | |
410 } | |
411 } | |
412 | |
413 /* | |
357 * Skip over an expression at "*pp". | 414 * Skip over an expression at "*pp". |
358 * Return FAIL for an error, OK otherwise. | 415 * Return FAIL for an error, OK otherwise. |
359 */ | 416 */ |
360 int | 417 int |
361 skip_expr(char_u **pp, evalarg_T *evalarg) | 418 skip_expr(char_u **pp, evalarg_T *evalarg) |
433 if (evalarg->eval_cookie != NULL) | 490 if (evalarg->eval_cookie != NULL) |
434 { | 491 { |
435 // Do not free the first line, the caller can still use it. | 492 // Do not free the first line, the caller can still use it. |
436 *((char_u **)gap->ga_data) = NULL; | 493 *((char_u **)gap->ga_data) = NULL; |
437 // Do not free the last line, "arg" points into it, free it | 494 // Do not free the last line, "arg" points into it, free it |
438 // later. | 495 // later. Also free "eval_tofree" later if needed. |
439 vim_free(evalarg->eval_tofree); | 496 free_eval_tofree_later(evalarg); |
440 evalarg->eval_tofree = | 497 evalarg->eval_tofree = |
441 ((char_u **)gap->ga_data)[gap->ga_len - 1]; | 498 ((char_u **)gap->ga_data)[gap->ga_len - 1]; |
442 ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL; | 499 ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL; |
443 ga_clear_strings(gap); | 500 ga_clear_strings(gap); |
444 } | 501 } |
2272 ((char_u **)gap->ga_data)[gap->ga_len] = line; | 2329 ((char_u **)gap->ga_data)[gap->ga_len] = line; |
2273 ++gap->ga_len; | 2330 ++gap->ga_len; |
2274 } | 2331 } |
2275 else if (evalarg->eval_cookie != NULL) | 2332 else if (evalarg->eval_cookie != NULL) |
2276 { | 2333 { |
2277 vim_free(evalarg->eval_tofree); | 2334 free_eval_tofree_later(evalarg); |
2278 evalarg->eval_tofree = line; | 2335 evalarg->eval_tofree = line; |
2279 } | 2336 } |
2280 | 2337 |
2281 // Advanced to the next line, "arg" no longer points into the previous | 2338 // Advanced to the next line, "arg" no longer points into the previous |
2282 // line. | 2339 // line. |
2297 return skipwhite(arg); | 2354 return skipwhite(arg); |
2298 eval_next_non_blank(p, evalarg, &getnext); | 2355 eval_next_non_blank(p, evalarg, &getnext); |
2299 if (getnext) | 2356 if (getnext) |
2300 return eval_next_line(arg, evalarg); | 2357 return eval_next_line(arg, evalarg); |
2301 return p; | 2358 return p; |
2302 } | |
2303 | |
2304 /* | |
2305 * Initialize "evalarg" for use. | |
2306 */ | |
2307 void | |
2308 init_evalarg(evalarg_T *evalarg) | |
2309 { | |
2310 CLEAR_POINTER(evalarg); | |
2311 ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20); | |
2312 } | |
2313 | |
2314 /* | |
2315 * After using "evalarg" filled from "eap": free the memory. | |
2316 */ | |
2317 void | |
2318 clear_evalarg(evalarg_T *evalarg, exarg_T *eap) | |
2319 { | |
2320 if (evalarg != NULL) | |
2321 { | |
2322 if (evalarg->eval_tofree != NULL) | |
2323 { | |
2324 if (eap != NULL) | |
2325 { | |
2326 // We may need to keep the original command line, e.g. for | |
2327 // ":let" it has the variable names. But we may also need the | |
2328 // new one, "nextcmd" points into it. Keep both. | |
2329 vim_free(eap->cmdline_tofree); | |
2330 eap->cmdline_tofree = *eap->cmdlinep; | |
2331 *eap->cmdlinep = evalarg->eval_tofree; | |
2332 } | |
2333 else | |
2334 vim_free(evalarg->eval_tofree); | |
2335 evalarg->eval_tofree = NULL; | |
2336 } | |
2337 | |
2338 ga_clear_strings(&evalarg->eval_tofree_ga); | |
2339 VIM_CLEAR(evalarg->eval_tofree_lambda); | |
2340 } | |
2341 } | 2359 } |
2342 | 2360 |
2343 /* | 2361 /* |
2344 * The "evaluate" argument: When FALSE, the argument is only parsed but not | 2362 * The "evaluate" argument: When FALSE, the argument is only parsed but not |
2345 * executed. The function may return OK, but the rettv will be of type | 2363 * executed. The function may return OK, but the rettv will be of type |