diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 021a891eee..a2a06e451c 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -331,6 +331,9 @@ enum { CF_UPPER = 0x02, }; +// Max allowed length for COMPOUND section +#define COMPOUND_MAX_LEN 100000 + static const char *e_spell_trunc = N_("E758: Truncated spell file"); static const char e_error_while_reading_sug_file_str[] = N_("E782: Error while reading .sug file: %s"); @@ -1431,24 +1434,28 @@ static int read_compound(FILE *fd, slang_T *slang, int len) // "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$". // Inserting backslashes may double the length, "^\(\)$" is 7 bytes. // Conversion to utf-8 may double the size. - c = todo * 2 + 7; - c += todo * 2; - char *pat = xmalloc((size_t)c); + if ((size_t)todo > COMPOUND_MAX_LEN) { + return SP_FORMERROR; + } + size_t patsize = (size_t)todo * 2 + 7; + patsize += (size_t)todo * 2; + size_t flagsize = (size_t)todo + 1; + char *pat = xmalloc(patsize); // We also need a list of all flags that can appear at the start and one // for all flags. - uint8_t *cp = xmalloc((size_t)todo + 1); + uint8_t *cp = xmalloc(flagsize); slang->sl_compstartflags = cp; *cp = NUL; - uint8_t *ap = xmalloc((size_t)todo + 1); + uint8_t *ap = xmalloc(flagsize); slang->sl_compallflags = ap; *ap = NUL; // And a list of all patterns in their original form, for checking whether // compounding may work in match_compoundrule(). This is freed when we // encounter a wildcard, the check doesn't work then. - uint8_t *crp = xmalloc((size_t)todo + 1); + uint8_t *crp = xmalloc(flagsize); slang->sl_comprules = crp; char *pp = pat; diff --git a/test/old/testdir/test_spellfile.vim b/test/old/testdir/test_spellfile.vim index 02878877b1..510953f4c9 100644 --- a/test/old/testdir/test_spellfile.vim +++ b/test/old/testdir/test_spellfile.vim @@ -337,6 +337,10 @@ func Test_spellfile_format_error() " SN_COMPOUND: incorrect comppatlen call Spellfile_Test(0z080000000007040101000000020165, 'E758:') + " SN_COMPOUND: oversized sectionlen + let v = eval('0z08004000000803010161' .. repeat('61', 50) .. 'FF') + call Spellfile_Test(v, 'E759:') + " SN_INFO: missing info call Spellfile_Test(0z0F0000000005040101, '')