@@ -1922,6 +1922,23 @@ vim_regsub_multi(
19221922 return result ;
19231923}
19241924
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+
19251942 static int
19261943vim_regsub_both (
19271944 char_u * source ,
@@ -1941,7 +1958,8 @@ vim_regsub_both(
19411958 linenr_T clnum = 0 ; // init for GCC
19421959 int len = 0 ; // init for GCC
19431960#ifdef FEAT_EVAL
1944- static char_u * eval_result = NULL ;
1961+ static int nesting = 0 ;
1962+ int nested ;
19451963#endif
19461964 int copy = flags & REGSUB_COPY ;
19471965
@@ -1953,6 +1971,14 @@ vim_regsub_both(
19531971 }
19541972 if (prog_magic_wrong ())
19551973 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
19561982 src = source ;
19571983 dst = dest ;
19581984
@@ -1969,19 +1995,19 @@ vim_regsub_both(
19691995 // "flags & REGSUB_COPY" != 0.
19701996 if (copy )
19711997 {
1972- if (eval_result != NULL )
1998+ if (eval_result [ nested ] != NULL )
19731999 {
1974- STRCPY (dest , eval_result );
1975- dst += STRLEN (eval_result );
1976- VIM_CLEAR (eval_result );
2000+ STRCPY (dest , eval_result [ nested ] );
2001+ dst += STRLEN (eval_result [ nested ] );
2002+ VIM_CLEAR (eval_result [ nested ] );
19772003 }
19782004 }
19792005 else
19802006 {
19812007 int prev_can_f_submatch = can_f_submatch ;
19822008 regsubmatch_T rsm_save ;
19832009
1984- VIM_CLEAR (eval_result );
2010+ VIM_CLEAR (eval_result [ nested ] );
19852011
19862012 // The expression may contain substitute(), which calls us
19872013 // recursively. Make sure submatch() gets the text from the first
@@ -1995,6 +2021,11 @@ vim_regsub_both(
19952021 rsm .sm_maxline = rex .reg_maxline ;
19962022 rsm .sm_line_lbr = rex .reg_line_lbr ;
19972023
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 ;
2028+
19982029 if (expr != NULL )
19992030 {
20002031 typval_T argv [2 ];
@@ -2034,26 +2065,27 @@ vim_regsub_both(
20342065
20352066 if (rettv .v_type == VAR_UNKNOWN )
20362067 // something failed, no need to report another error
2037- eval_result = NULL ;
2068+ eval_result [ nested ] = NULL ;
20382069 else
20392070 {
2040- eval_result = tv_get_string_buf_chk (& rettv , buf );
2041- if (eval_result != NULL )
2042- eval_result = vim_strsave (eval_result );
2071+ eval_result [ nested ] = tv_get_string_buf_chk (& rettv , buf );
2072+ if (eval_result [ nested ] != NULL )
2073+ eval_result [ nested ] = vim_strsave (eval_result [ nested ] );
20432074 }
20442075 clear_tv (& rettv );
20452076 }
20462077 else if (substitute_instr != NULL )
20472078 // Execute instructions from ISN_SUBSTITUTE.
2048- eval_result = exe_substitute_instr ();
2079+ eval_result [ nested ] = exe_substitute_instr ();
20492080 else
2050- eval_result = eval_to_string (source + 2 , TRUE);
2081+ eval_result [nested ] = eval_to_string (source + 2 , TRUE);
2082+ -- nesting ;
20512083
2052- if (eval_result != NULL )
2084+ if (eval_result [ nested ] != NULL )
20532085 {
20542086 int had_backslash = FALSE;
20552087
2056- for (s = eval_result ; * s != NUL ; MB_PTR_ADV (s ))
2088+ for (s = eval_result [ nested ] ; * s != NUL ; MB_PTR_ADV (s ))
20572089 {
20582090 // Change NL to CR, so that it becomes a line break,
20592091 // unless called from vim_regexec_nl().
@@ -2077,15 +2109,15 @@ vim_regsub_both(
20772109 if (had_backslash && (flags & REGSUB_BACKSLASH ))
20782110 {
20792111 // 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 * )"\\" );
20812113 if (s != NULL )
20822114 {
2083- vim_free (eval_result );
2084- eval_result = s ;
2115+ vim_free (eval_result [ nested ] );
2116+ eval_result [ nested ] = s ;
20852117 }
20862118 }
20872119
2088- dst += STRLEN (eval_result );
2120+ dst += STRLEN (eval_result [ nested ] );
20892121 }
20902122
20912123 can_f_submatch = prev_can_f_submatch ;
0 commit comments