Mercurial > vim
changeset 32401:3bf4736649b7 v9.0.1532
patch 9.0.1532: crash when expanding "~" in substitute causes very long text
Commit: https://github.com/vim/vim/commit/ab9a2d884b3a4abe319606ea95a5a6d6b01cd73a
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue May 9 21:15:30 2023 +0100
patch 9.0.1532: crash when expanding "~" in substitute causes very long text
Problem: Crash when expanding "~" in substitute causes very long text.
Solution: Limit the text length to MAXCOL.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 09 May 2023 22:30:04 +0200 |
parents | f62f661344d6 |
children | 3a28456684b0 |
files | src/regexp.c src/testdir/test_substitute.vim src/version.c |
diffstat | 3 files changed, 35 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/src/regexp.c +++ b/src/regexp.c @@ -1767,10 +1767,7 @@ do_Lower(int *d, int c) regtilde(char_u *source, int magic) { char_u *newsub = source; - char_u *tmpsub; char_u *p; - int len; - int prevlen; for (p = newsub; *p; ++p) { @@ -1779,24 +1776,35 @@ regtilde(char_u *source, int magic) if (reg_prev_sub != NULL) { // length = len(newsub) - 1 + len(prev_sub) + 1 - prevlen = (int)STRLEN(reg_prev_sub); - tmpsub = alloc(STRLEN(newsub) + prevlen); + // Avoid making the text longer than MAXCOL, it will cause + // trouble at some point. + size_t prevsublen = STRLEN(reg_prev_sub); + size_t newsublen = STRLEN(newsub); + if (prevsublen > MAXCOL || newsublen > MAXCOL + || newsublen + prevsublen > MAXCOL) + { + emsg(_(e_resulting_text_too_long)); + break; + } + + char_u *tmpsub = alloc(newsublen + prevsublen); if (tmpsub != NULL) { // copy prefix - len = (int)(p - newsub); // not including ~ - mch_memmove(tmpsub, newsub, (size_t)len); + size_t prefixlen = p - newsub; // not including ~ + mch_memmove(tmpsub, newsub, prefixlen); // interpret tilde - mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen); + mch_memmove(tmpsub + prefixlen, reg_prev_sub, + prevsublen); // copy postfix if (!magic) ++p; // back off backslash - STRCPY(tmpsub + len + prevlen, p + 1); + STRCPY(tmpsub + prefixlen + prevsublen, p + 1); - if (newsub != source) // already allocated newsub + if (newsub != source) // allocated newsub before vim_free(newsub); newsub = tmpsub; - p = newsub + len + prevlen; + p = newsub + prefixlen + prevsublen; } } else if (magic)
--- a/src/testdir/test_substitute.vim +++ b/src/testdir/test_substitute.vim @@ -1414,6 +1414,20 @@ func Test_substitute_short_cmd() bw! endfunc +" Check handling expanding "~" resulting in extremely long text. +func Test_substitute_tilde_too_long() + enew! + + s/.*/ixxx + s//~~~~~~~~~AAAAAAA@( + + " Either fails with "out of memory" or "text too long". + " This can take a long time. + call assert_fails('sil! norm &&&&&&&&&', ['E1240:\|E342:']) + + bwipe! +endfunc + " This should be done last to reveal a memory leak when vim_regsub_both() is " called to evaluate an expression but it is not used in a second call. func Test_z_substitute_expr_leak()