vim-patch:9.2.0131: potential buffer overflow in regdump() (#38217)

Problem:  Potential buffer overflow in regdump()
Solution: Add the size to the compiled regular expression and ensure we
          don't read over the limit.

Note: this is not a security issue, because regdump() is typically not
compiled in any version of Vim, so should not affect anybody.

supported by AI claude.

9360647715

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2026-03-10 10:47:07 +08:00
committed by GitHub
parent 9734a6ce47
commit c1dcb8dac2

View File

@@ -99,6 +99,9 @@ typedef struct {
uint8_t reganch; uint8_t reganch;
uint8_t *regmust; uint8_t *regmust;
int regmlen; int regmlen;
#ifdef REGEXP_DEBUG
int regsz;
#endif
uint8_t reghasz; uint8_t reghasz;
uint8_t program[]; uint8_t program[];
} bt_regprog_T; } bt_regprog_T;
@@ -5449,6 +5452,9 @@ static regprog_T *bt_regcomp(uint8_t *expr, int re_flags)
// Allocate space. // Allocate space.
bt_regprog_T *r = xmalloc(offsetof(bt_regprog_T, program) + (size_t)regsize); bt_regprog_T *r = xmalloc(offsetof(bt_regprog_T, program) + (size_t)regsize);
r->re_in_use = false; r->re_in_use = false;
#ifdef REGEXP_DEBUG
r->regsz = regsize;
#endif
// Second pass: emit code. // Second pass: emit code.
regcomp_start(expr, re_flags); regcomp_start(expr, re_flags);
@@ -7832,10 +7838,10 @@ static void regdump(uint8_t *pattern, bt_regprog_T *r)
s = &r->program[1]; s = &r->program[1];
// Loop until we find the END that isn't before a referred next (an END // Loop until we find the END that isn't before a referred next (an END
// can also appear in a NOMATCH operand). // can also appear in a NOMATCH operand).
while (op != END || s <= end) { while ((op != END || s <= end) && s < r->program + r->regsz) {
op = OP(s); op = OP(s);
fprintf(f, "%2d%s", (int)(s - r->program), regprop(s)); // Where, what. fprintf(f, "%2d%s", (int)(s - r->program), regprop(s)); // Where, what.
next = regnext(s); next = (s + 3 <= r->program + r->regsz) ? regnext(s) : NULL;
if (next == NULL) { // Next ptr. if (next == NULL) { // Next ptr.
fprintf(f, "(0)"); fprintf(f, "(0)");
} else { } else {
@@ -7859,13 +7865,18 @@ static void regdump(uint8_t *pattern, bt_regprog_T *r)
s += 5; s += 5;
} }
s += 3; s += 3;
if (op == MULTIBYTECODE) {
fprintf(f, " mbc=%d", utf_ptr2char(s));
s += utfc_ptr2len(s);
}
if (op == ANYOF || op == ANYOF + ADD_NL if (op == ANYOF || op == ANYOF + ADD_NL
|| op == ANYBUT || op == ANYBUT + ADD_NL || op == ANYBUT || op == ANYBUT + ADD_NL
|| op == EXACTLY) { || op == EXACTLY) {
// Literal string, where present. // Literal string, where present.
fprintf(f, "\nxxxxxxxxx\n"); fprintf(f, "\nxxxxxxxxx\n");
while (*s != NUL) { while (*s != NUL && s < r->program + r->regsz) {
fprintf(f, "%c", *s++); fprintf(f, "%c", *s);
s += utfc_ptr2len(s); // advance by full char including combining
} }
fprintf(f, "\nxxxxxxxxx\n"); fprintf(f, "\nxxxxxxxxx\n");
s++; s++;