comparison src/regexp.c @ 29255:5ebc561444fe v8.2.5146

patch 8.2.5146: memory leak when substitute expression nests Commit: https://github.com/vim/vim/commit/44ddf19ec0ff59c969658ec7d9ed42070c59c51b Author: Bram Moolenaar <Bram@vim.org> Date: Tue Jun 21 22:15:25 2022 +0100 patch 8.2.5146: memory leak when substitute expression nests Problem: Memory leak when substitute expression nests. Solution: Use an array of expression results.
author Bram Moolenaar <Bram@vim.org>
date Tue, 21 Jun 2022 23:30:03 +0200
parents b12fd2b3be63
children 8175cd4c8fdd
comparison
equal deleted inserted replaced
29254:acb7f19c9d07 29255:5ebc561444fe
1920 rex = rex_save; 1920 rex = rex_save;
1921 1921
1922 return result; 1922 return result;
1923 } 1923 }
1924 1924
1925 #if defined(FEAT_EVAL) || defined(PROTO)
1926 // When nesting more than a couple levels it's probably a mistake.
1927 # define MAX_REGSUB_NESTING 4
1928 static char_u *eval_result[MAX_REGSUB_NESTING] = {NULL, NULL, NULL, NULL};
1929
1930 # if defined(EXITFREE) || defined(PROTO)
1931 void
1932 free_resub_eval_result(void)
1933 {
1934 int i;
1935
1936 for (i = 0; i < MAX_REGSUB_NESTING; ++i)
1937 VIM_CLEAR(eval_result[i]);
1938 }
1939 # endif
1940 #endif
1941
1925 static int 1942 static int
1926 vim_regsub_both( 1943 vim_regsub_both(
1927 char_u *source, 1944 char_u *source,
1928 typval_T *expr, 1945 typval_T *expr,
1929 char_u *dest, 1946 char_u *dest,
1939 fptr_T func_all = (fptr_T)NULL; 1956 fptr_T func_all = (fptr_T)NULL;
1940 fptr_T func_one = (fptr_T)NULL; 1957 fptr_T func_one = (fptr_T)NULL;
1941 linenr_T clnum = 0; // init for GCC 1958 linenr_T clnum = 0; // init for GCC
1942 int len = 0; // init for GCC 1959 int len = 0; // init for GCC
1943 #ifdef FEAT_EVAL 1960 #ifdef FEAT_EVAL
1944 static char_u *eval_result = NULL; 1961 static int nesting = 0;
1962 int nested;
1945 #endif 1963 #endif
1946 int copy = flags & REGSUB_COPY; 1964 int copy = flags & REGSUB_COPY;
1947 1965
1948 // Be paranoid... 1966 // Be paranoid...
1949 if ((source == NULL && expr == NULL) || dest == NULL) 1967 if ((source == NULL && expr == NULL) || dest == NULL)
1951 emsg(_(e_null_argument)); 1969 emsg(_(e_null_argument));
1952 return 0; 1970 return 0;
1953 } 1971 }
1954 if (prog_magic_wrong()) 1972 if (prog_magic_wrong())
1955 return 0; 1973 return 0;
1974 #ifdef FEAT_EVAL
1975 if (nesting == MAX_REGSUB_NESTING)
1976 {
1977 emsg(_(e_substitute_nesting_too_deep));
1978 return 0;
1979 }
1980 nested = nesting;
1981 #endif
1956 src = source; 1982 src = source;
1957 dst = dest; 1983 dst = dest;
1958 1984
1959 /* 1985 /*
1960 * When the substitute part starts with "\=" evaluate it as an expression. 1986 * When the substitute part starts with "\=" evaluate it as an expression.
1967 // resulting string is saved from the call with 1993 // resulting string is saved from the call with
1968 // "flags & REGSUB_COPY" == 0 to the call with 1994 // "flags & REGSUB_COPY" == 0 to the call with
1969 // "flags & REGSUB_COPY" != 0. 1995 // "flags & REGSUB_COPY" != 0.
1970 if (copy) 1996 if (copy)
1971 { 1997 {
1972 if (eval_result != NULL) 1998 if (eval_result[nested] != NULL)
1973 { 1999 {
1974 STRCPY(dest, eval_result); 2000 STRCPY(dest, eval_result[nested]);
1975 dst += STRLEN(eval_result); 2001 dst += STRLEN(eval_result[nested]);
1976 VIM_CLEAR(eval_result); 2002 VIM_CLEAR(eval_result[nested]);
1977 } 2003 }
1978 } 2004 }
1979 else 2005 else
1980 { 2006 {
1981 int prev_can_f_submatch = can_f_submatch; 2007 int prev_can_f_submatch = can_f_submatch;
1982 regsubmatch_T rsm_save; 2008 regsubmatch_T rsm_save;
1983 2009
1984 VIM_CLEAR(eval_result); 2010 VIM_CLEAR(eval_result[nested]);
1985 2011
1986 // The expression may contain substitute(), which calls us 2012 // The expression may contain substitute(), which calls us
1987 // recursively. Make sure submatch() gets the text from the first 2013 // recursively. Make sure submatch() gets the text from the first
1988 // level. 2014 // level.
1989 if (can_f_submatch) 2015 if (can_f_submatch)
1992 rsm.sm_match = rex.reg_match; 2018 rsm.sm_match = rex.reg_match;
1993 rsm.sm_mmatch = rex.reg_mmatch; 2019 rsm.sm_mmatch = rex.reg_mmatch;
1994 rsm.sm_firstlnum = rex.reg_firstlnum; 2020 rsm.sm_firstlnum = rex.reg_firstlnum;
1995 rsm.sm_maxline = rex.reg_maxline; 2021 rsm.sm_maxline = rex.reg_maxline;
1996 rsm.sm_line_lbr = rex.reg_line_lbr; 2022 rsm.sm_line_lbr = rex.reg_line_lbr;
2023
2024 // Although unlikely, it is possible that the expression invokes a
2025 // substitute command (it might fail, but still). Therefore keep
2026 // an array if eval results.
2027 ++nesting;
1997 2028
1998 if (expr != NULL) 2029 if (expr != NULL)
1999 { 2030 {
2000 typval_T argv[2]; 2031 typval_T argv[2];
2001 char_u buf[NUMBUFLEN]; 2032 char_u buf[NUMBUFLEN];
2032 // fill_submatch_list() was called 2063 // fill_submatch_list() was called
2033 clear_submatch_list(&matchList); 2064 clear_submatch_list(&matchList);
2034 2065
2035 if (rettv.v_type == VAR_UNKNOWN) 2066 if (rettv.v_type == VAR_UNKNOWN)
2036 // something failed, no need to report another error 2067 // something failed, no need to report another error
2037 eval_result = NULL; 2068 eval_result[nested] = NULL;
2038 else 2069 else
2039 { 2070 {
2040 eval_result = tv_get_string_buf_chk(&rettv, buf); 2071 eval_result[nested] = tv_get_string_buf_chk(&rettv, buf);
2041 if (eval_result != NULL) 2072 if (eval_result[nested] != NULL)
2042 eval_result = vim_strsave(eval_result); 2073 eval_result[nested] = vim_strsave(eval_result[nested]);
2043 } 2074 }
2044 clear_tv(&rettv); 2075 clear_tv(&rettv);
2045 } 2076 }
2046 else if (substitute_instr != NULL) 2077 else if (substitute_instr != NULL)
2047 // Execute instructions from ISN_SUBSTITUTE. 2078 // Execute instructions from ISN_SUBSTITUTE.
2048 eval_result = exe_substitute_instr(); 2079 eval_result[nested] = exe_substitute_instr();
2049 else 2080 else
2050 eval_result = eval_to_string(source + 2, TRUE); 2081 eval_result[nested] = eval_to_string(source + 2, TRUE);
2051 2082 --nesting;
2052 if (eval_result != NULL) 2083
2084 if (eval_result[nested] != NULL)
2053 { 2085 {
2054 int had_backslash = FALSE; 2086 int had_backslash = FALSE;
2055 2087
2056 for (s = eval_result; *s != NUL; MB_PTR_ADV(s)) 2088 for (s = eval_result[nested]; *s != NUL; MB_PTR_ADV(s))
2057 { 2089 {
2058 // Change NL to CR, so that it becomes a line break, 2090 // Change NL to CR, so that it becomes a line break,
2059 // unless called from vim_regexec_nl(). 2091 // unless called from vim_regexec_nl().
2060 // Skip over a backslashed character. 2092 // Skip over a backslashed character.
2061 if (*s == NL && !rsm.sm_line_lbr) 2093 if (*s == NL && !rsm.sm_line_lbr)
2075 } 2107 }
2076 } 2108 }
2077 if (had_backslash && (flags & REGSUB_BACKSLASH)) 2109 if (had_backslash && (flags & REGSUB_BACKSLASH))
2078 { 2110 {
2079 // Backslashes will be consumed, need to double them. 2111 // Backslashes will be consumed, need to double them.
2080 s = vim_strsave_escaped(eval_result, (char_u *)"\\"); 2112 s = vim_strsave_escaped(eval_result[nested], (char_u *)"\\");
2081 if (s != NULL) 2113 if (s != NULL)
2082 { 2114 {
2083 vim_free(eval_result); 2115 vim_free(eval_result[nested]);
2084 eval_result = s; 2116 eval_result[nested] = s;
2085 } 2117 }
2086 } 2118 }
2087 2119
2088 dst += STRLEN(eval_result); 2120 dst += STRLEN(eval_result[nested]);
2089 } 2121 }
2090 2122
2091 can_f_submatch = prev_can_f_submatch; 2123 can_f_submatch = prev_can_f_submatch;
2092 if (can_f_submatch) 2124 if (can_f_submatch)
2093 rsm = rsm_save; 2125 rsm = rsm_save;