macvim-dev / macvim-dev/macvim

[Security] MacVim affected by GHSA-q4jv-r9gj-6cwv — heap buffer overflow in spellfile.c read_compound() (vim < 9.2.0450)

Open
#1,660 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Vim Script
Stars
7.9k
Forks
691
PR merge metrics
No merged PRs in 30d

Description

Summary

MacVim's src/spellfile.c contains a heap buffer overflow in read_compound() when loading specially crafted spell files. An integer overflow in the allocation size computation allows a malicious .spl file to cause out-of-bounds writes. The fix from vim 9.2.0450 (92993329) has not been applied to macvim r183.

Vulnerability Details

  • GHSA: GHSA-q4jv-r9gj-6cwv
  • CVE: CVE-2026-45130
  • Upstream fix (vim): 9.2.0450 (commit 929933294a5c56ef8e9dab03e0b8c61bbb1dc3cd, 2026-05-07)
  • Affected code: src/spellfile.cread_compound() function
  • Vulnerability type: CWE-122 — Heap-based Buffer Overflow

Root Cause

In read_compound(), the todo variable (derived from the SN_COMPOUND section length in the spell file) is used directly in buffer size calculations without an upper bound check:

/* src/spellfile.c line 1278 (macvim r183) */
c = todo * 2 + 7;

A malicious spell file can set todo to a large value (e.g., 0x40000000), causing todo * 2 to overflow a 32-bit integer to 7, resulting in an undersized allocation. Subsequent writes to the buffer cause a heap overflow.

Attack Scenario
  1. Attacker provides a malicious .spl spell file (e.g., in a project's spell directory)
  2. Victim loads the spell file in MacVim (:setlocal spelllang=... or via modeline)
  3. read_compound() allocates an undersized buffer and writes beyond it, potentially enabling arbitrary code execution

Verification

$ grep -n 'todo.*2.*7\|read_compound\|COMPOUND_MAX_LEN' src/spellfile.c
1278:    c = todo * 2 + 7;

Missing the COMPOUND_MAX_LEN guard and safe size computation. Patch 9.2.0450 not present:

$ git log --all --oneline | grep -i '9.2.0450\|spellfile\|q4jv'
(no output)

Suggested Fix

Merge vim patches up to at least 9.2.0450. The fix adds an upper bound check and uses size_t arithmetic:

/* Fixed (vim 9.2.0450): */
#define COMPOUND_MAX_LEN 100000

if ((size_t)todo > COMPOUND_MAX_LEN)
    return SP_FORMERROR;
size_t patsize = (size_t)todo * 2 + 7;
size_t flagsize = (size_t)todo + 1;
pat = alloc(patsize);
cp = alloc(flagsize);
ap = alloc(flagsize);
crp = alloc(flagsize);

References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/spellfile.c at read_compound(), especially the todo-based allocation around line 1278, and compare it with Vim commit 929933294a5c56ef8e9dab03e0b8c61bbb1dc3cd. Apply the upstream fix for bounded, safe size calculations and verify that the vulnerable allocation is no longer present in MacVim r183.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, vim
Domain
desktop, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.