Mercurial > vim
comparison src/eval.c @ 21220:ad13736a1783 v8.2.1161
patch 8.2.1161: Vim9: using freed memory
Commit: https://github.com/vim/vim/commit/8e2730a315b8b06192f5fc822dc218dbb3cff7ae
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Jul 8 22:01:49 2020 +0200
patch 8.2.1161: Vim9: using freed memory
Problem: Vim9: using freed memory.
Solution: Put pointer back in evalarg instead of freeing it.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 08 Jul 2020 22:15:04 +0200 |
parents | 09377fd59b2e |
children | d1215fcdbca8 |
comparison
equal
deleted
inserted
replaced
21219:8ad4d2754054 | 21220:ad13736a1783 |
---|---|
377 | 377 |
378 /* | 378 /* |
379 * Skip over an expression at "*pp". | 379 * Skip over an expression at "*pp". |
380 * If in Vim9 script and line breaks are encountered, the lines are | 380 * If in Vim9 script and line breaks are encountered, the lines are |
381 * concatenated. "evalarg->eval_tofree" will be set accordingly. | 381 * concatenated. "evalarg->eval_tofree" will be set accordingly. |
382 * "arg" is advanced to just after the expression. | |
383 * "start" is set to the start of the expression, "end" to just after the end. | |
384 * Also when the expression is copied to allocated memory. | |
382 * Return FAIL for an error, OK otherwise. | 385 * Return FAIL for an error, OK otherwise. |
383 */ | 386 */ |
384 int | 387 int |
385 skip_expr_concatenate(char_u **start, char_u **end, evalarg_T *evalarg) | 388 skip_expr_concatenate( |
389 char_u **arg, | |
390 char_u **start, | |
391 char_u **end, | |
392 evalarg_T *evalarg) | |
386 { | 393 { |
387 typval_T rettv; | 394 typval_T rettv; |
388 int res; | 395 int res; |
389 int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9; | 396 int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9; |
390 garray_T *gap = &evalarg->eval_ga; | 397 garray_T *gap = &evalarg->eval_ga; |
396 ga_init2(gap, sizeof(char_u *), 10); | 403 ga_init2(gap, sizeof(char_u *), 10); |
397 // leave room for "start" | 404 // leave room for "start" |
398 if (ga_grow(gap, 1) == OK) | 405 if (ga_grow(gap, 1) == OK) |
399 ++gap->ga_len; | 406 ++gap->ga_len; |
400 } | 407 } |
408 *start = *arg; | |
401 | 409 |
402 // Don't evaluate the expression. | 410 // Don't evaluate the expression. |
403 if (evalarg != NULL) | 411 if (evalarg != NULL) |
404 evalarg->eval_flags &= ~EVAL_EVALUATE; | 412 evalarg->eval_flags &= ~EVAL_EVALUATE; |
405 *end = skipwhite(*end); | 413 *arg = skipwhite(*arg); |
406 res = eval1(end, &rettv, evalarg); | 414 res = eval1(arg, &rettv, evalarg); |
415 *end = *arg; | |
407 if (evalarg != NULL) | 416 if (evalarg != NULL) |
408 evalarg->eval_flags = save_flags; | 417 evalarg->eval_flags = save_flags; |
409 | 418 |
410 if (vim9script | 419 if (vim9script |
411 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)) | 420 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)) |
417 gap->ga_itemsize = 0; | 426 gap->ga_itemsize = 0; |
418 } | 427 } |
419 else | 428 else |
420 { | 429 { |
421 char_u *p; | 430 char_u *p; |
422 size_t endoff = STRLEN(*end); | 431 size_t endoff = STRLEN(*arg); |
423 | 432 |
424 // Line breaks encountered, concatenate all the lines. | 433 // Line breaks encountered, concatenate all the lines. |
425 *((char_u **)gap->ga_data) = *start; | 434 *((char_u **)gap->ga_data) = *start; |
426 p = ga_concat_strings(gap, ""); | 435 p = ga_concat_strings(gap, ""); |
427 | 436 |
428 // free the lines only when using getsourceline() | 437 // free the lines only when using getsourceline() |
429 if (evalarg->eval_cookie != NULL) | 438 if (evalarg->eval_cookie != NULL) |
430 { | 439 { |
440 // Do not free the first line, the caller can still use it. | |
431 *((char_u **)gap->ga_data) = NULL; | 441 *((char_u **)gap->ga_data) = NULL; |
442 // Do not free the last line, "arg" points into it, free it | |
443 // later. | |
444 vim_free(evalarg->eval_tofree); | |
445 evalarg->eval_tofree = | |
446 ((char_u **)gap->ga_data)[gap->ga_len - 1]; | |
447 ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL; | |
432 ga_clear_strings(gap); | 448 ga_clear_strings(gap); |
433 } | 449 } |
434 else | 450 else |
435 ga_clear(gap); | 451 ga_clear(gap); |
436 gap->ga_itemsize = 0; | 452 gap->ga_itemsize = 0; |
437 if (p == NULL) | 453 if (p == NULL) |
438 return FAIL; | 454 return FAIL; |
439 *start = p; | 455 *start = p; |
440 vim_free(evalarg->eval_tofree); | 456 vim_free(evalarg->eval_tofree_lambda); |
441 evalarg->eval_tofree = p; | 457 evalarg->eval_tofree_lambda = p; |
442 // Compute "end" relative to the end. | 458 // Compute "end" relative to the end. |
443 *end = *start + STRLEN(*start) - endoff; | 459 *end = *start + STRLEN(*start) - endoff; |
444 } | 460 } |
445 } | 461 } |
446 | 462 |
1934 { | 1950 { |
1935 // Going to concatenate the lines after parsing. | 1951 // Going to concatenate the lines after parsing. |
1936 ((char_u **)gap->ga_data)[gap->ga_len] = line; | 1952 ((char_u **)gap->ga_data)[gap->ga_len] = line; |
1937 ++gap->ga_len; | 1953 ++gap->ga_len; |
1938 } | 1954 } |
1939 else | 1955 else if (evalarg->eval_cookie != NULL) |
1940 { | 1956 { |
1941 vim_free(evalarg->eval_tofree); | 1957 vim_free(evalarg->eval_tofree); |
1942 evalarg->eval_tofree = line; | 1958 evalarg->eval_tofree = line; |
1943 } | 1959 } |
1944 return skipwhite(line); | 1960 return skipwhite(line); |
1960 return eval_next_line(evalarg); | 1976 return eval_next_line(evalarg); |
1961 return p; | 1977 return p; |
1962 } | 1978 } |
1963 | 1979 |
1964 /* | 1980 /* |
1965 * After using "evalarg" filled from "eap" free the memory. | 1981 * After using "evalarg" filled from "eap": free the memory. |
1966 */ | 1982 */ |
1967 void | 1983 void |
1968 clear_evalarg(evalarg_T *evalarg, exarg_T *eap) | 1984 clear_evalarg(evalarg_T *evalarg, exarg_T *eap) |
1969 { | 1985 { |
1970 if (evalarg != NULL && evalarg->eval_tofree != NULL) | 1986 if (evalarg != NULL) |
1971 { | 1987 { |
1972 if (eap != NULL) | 1988 if (evalarg->eval_tofree != NULL) |
1973 { | 1989 { |
1974 // We may need to keep the original command line, e.g. for | 1990 if (eap != NULL) |
1975 // ":let" it has the variable names. But we may also need the | 1991 { |
1976 // new one, "nextcmd" points into it. Keep both. | 1992 // We may need to keep the original command line, e.g. for |
1977 vim_free(eap->cmdline_tofree); | 1993 // ":let" it has the variable names. But we may also need the |
1978 eap->cmdline_tofree = *eap->cmdlinep; | 1994 // new one, "nextcmd" points into it. Keep both. |
1979 *eap->cmdlinep = evalarg->eval_tofree; | 1995 vim_free(eap->cmdline_tofree); |
1980 } | 1996 eap->cmdline_tofree = *eap->cmdlinep; |
1981 else | 1997 *eap->cmdlinep = evalarg->eval_tofree; |
1982 vim_free(evalarg->eval_tofree); | 1998 } |
1983 evalarg->eval_tofree = NULL; | 1999 else |
2000 vim_free(evalarg->eval_tofree); | |
2001 evalarg->eval_tofree = NULL; | |
2002 } | |
2003 | |
2004 vim_free(evalarg->eval_tofree_lambda); | |
2005 evalarg->eval_tofree_lambda = NULL; | |
1984 } | 2006 } |
1985 } | 2007 } |
1986 | 2008 |
1987 /* | 2009 /* |
1988 * The "evaluate" argument: When FALSE, the argument is only parsed but not | 2010 * The "evaluate" argument: When FALSE, the argument is only parsed but not |