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