]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0932: NFA engine fallback can double free the compiled program v9.2.0932
authorSamuel Schlesinger <sgschlesinger@gmail.com>
Mon, 10 Aug 2026 20:17:42 +0000 (20:17 +0000)
committerChristian Brabandt <cb@256bit.org>
Mon, 10 Aug 2026 20:17:42 +0000 (20:17 +0000)
Problem:  When the automatic regexp engine falls back to the
          backtracking engine in vim_regexec_string(), the compiled
          program is freed before the replacement is compiled; when
          saving the pattern fails from being out of memory the
          caller's "regprog" is left pointing to freed memory and
          is freed again.
Solution: Free the previous program only after compiling the
          replacement succeeded, like vim_regexec_multi() already
          does (Samuel Schlesinger).

closes: #20986

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Samuel Schlesinger <sgschlesinger@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/regexp.c
src/version.c

index 7f52f9a955a07b98f27cd32bd92b1ece4055e616..6da2e66a779958e11f7afc6ae820d94ca33c12bd 100644 (file)
@@ -3114,15 +3114,23 @@ vim_regexec_string(
        char_u *pat = vim_strsave(((nfa_regprog_T *)rmp->regprog)->pattern);
 
        p_re = BACKTRACKING_ENGINE;
-       vim_regfree(rmp->regprog);
        if (pat != NULL)
        {
+           regprog_T *prev_prog = rmp->regprog;
+
 #ifdef FEAT_EVAL
            report_re_switch(pat);
 #endif
            rmp->regprog = vim_regcomp(pat, re_flags);
-           if (rmp->regprog != NULL)
+           if (rmp->regprog == NULL)
+           {
+               // Somehow compiling the pattern failed now, put back the
+               // previous one to avoid "regprog" becoming NULL.
+               rmp->regprog = prev_prog;
+           }
+           else
            {
+               vim_regfree(prev_prog);
                rmp->regprog->re_in_use = TRUE;
                result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
                rmp->regprog->re_in_use = FALSE;
index 41fe299eea920fc8550da1fe4bd4a1c92e4e6c1c..a33437590f7833e095897e76c30c7ff59e117787 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    932,
 /**/
     931,
 /**/