VYPR
Unrated severityNVD Advisory· Published Jul 8, 2022· Updated Aug 3, 2024

Use After Free in vim/vim

CVE-2022-2345

Description

Use after free in Vim's substitute command (prior to 9.0.0046) can lead to crash or arbitrary code execution via a crafted recursive substitute expression.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Use after free in Vim's substitute command (prior to 9.0.0046) can lead to crash or arbitrary code execution via a crafted recursive substitute expression.

Vulnerability

A use-after-free vulnerability exists in Vim's ex_substitute function (file src/ex_docmd.c) prior to version 9.0.0046. The issue occurs when a recursive substitute expression is used, causing the regtilde() function to allocate new memory and free the previous reg_prev_sub pointer. However, the sub variable in ex_substitute is not updated to point to the newly allocated string, leading to a use-after-free when the freed memory is subsequently accessed.

Exploitation

An attacker must be able to craft a specially crafted substitute command that includes a recursive expression (e.g., :s/pattern/\=Repl()/). The attacker does not require authentication or special privileges beyond the ability to open and edit a file in Vim. By triggering the recursive substitute, the attacker can cause Vim to read from freed heap memory, potentially leading to a crash or allowing further memory corruption.

Impact

Successful exploitation results in a use-after-free condition, which can cause Vim to crash (denial of service) or potentially allow arbitrary code execution within the context of the Vim process. The scope of compromise is limited to the Vim session, but if Vim runs with elevated privileges, further system compromise may be possible.

Mitigation

The vulnerability is fixed in Vim version 9.0.0047 [1]. Users should upgrade to at least 9.0.0047 or later. Distributions have backported the fix: Gentoo advises upgrading to >=app-editors/vim-9.0.0060 (GLSA 202208-32) or >=app-editors/vim-9.0.1157 (GLSA 202305-16) [3][4]. No workarounds are available if upgrading is not possible.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

39

Patches

0

No patches discovered yet.

Vulnerability mechanics

Root cause

"Use-after-free in `ex_substitute()` when `regtilde()` frees and reallocates `reg_prev_sub` during recursive substitute expression evaluation, but the caller continues using the old freed pointer."

Attack vector

An attacker can trigger a use-after-free by crafting a recursive substitute expression (e.g., `s/\%')/~\=Repl()` where `Repl()` itself calls `:s`). When `regtilde()` is called, it may free and reallocate `reg_prev_sub`, but the caller `ex_substitute()` continues to use the old `sub` pointer, which now points to freed memory [ref_id=1]. The attack requires the ability to supply a substitute command with a recursive expression.

Affected code

The vulnerability is in the `ex_substitute()` function in `src/ex_cmds.c` and the `regtilde()` function in `src/regexp.c`. The patch modifies the logic around `regtilde()` calls and how `reg_prev_sub` is managed [ref_id=1].

What the fix does

The patch fixes the use-after-free by ensuring that when `regtilde()` returns a newly allocated string (different from the input `sub`), the caller `ex_substitute()` updates `sub` to point to the new allocation and stores it in `sub_copy` for later freeing [ref_id=1]. Additionally, `regtilde()` is changed to always store a copy of the result in `reg_prev_sub` via `vim_strsave()`, rather than conditionally keeping the returned pointer, because recursive calls may invalidate the previously stored pointer [ref_id=1].

Preconditions

  • inputAttacker must be able to supply a substitute command with a recursive expression (e.g., via a crafted file or command input)
  • inputThe substitute expression must trigger a recursive call to :substitute within the expression evaluation

Reproduction

The test case added in the patch demonstrates reproduction: create a new buffer, define a function `Repl()` that calls `:s`, then run `silent! s/\%')/~\=Repl()` [ref_id=1].

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.