diff --git a/src/spellfile.c b/src/spellfile.c index a9a347a89a..5102dad5b6 100644 --- a/src/spellfile.c +++ b/src/spellfile.c @@ -290,6 +290,9 @@ #define CF_WORD 0x01 #define CF_UPPER 0x02 +// Max allowed length for COMPOUND section +#define COMPOUND_MAX_LEN 100000 + /* * Loop through all the siblings of a node (including the node) */ @@ -1219,6 +1222,8 @@ read_compound(FILE *fd, slang_T *slang, int len) char_u *crp; int cnt; garray_T *gap; + size_t patsize; + size_t flagsize; if (todo < 2) return SP_FORMERROR; // need at least two bytes @@ -1275,16 +1280,19 @@ 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; + if ((size_t)todo > COMPOUND_MAX_LEN) + return SP_FORMERROR; + patsize = (size_t)todo * 2 + 7; if (enc_utf8) - c += todo * 2; - pat = alloc(c); + patsize += (size_t)todo * 2; + flagsize = (size_t)todo + 1; + pat = alloc(patsize); if (pat == NULL) return SP_OTHERERROR; // We also need a list of all flags that can appear at the start and one // for all flags. - cp = alloc(todo + 1); + cp = alloc(flagsize); if (cp == NULL) { vim_free(pat); @@ -1293,7 +1301,7 @@ read_compound(FILE *fd, slang_T *slang, int len) slang->sl_compstartflags = cp; *cp = NUL; - ap = alloc(todo + 1); + ap = alloc(flagsize); if (ap == NULL) { vim_free(pat); @@ -1305,7 +1313,7 @@ read_compound(FILE *fd, slang_T *slang, int len) // 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. - crp = alloc(todo + 1); + crp = alloc(flagsize); slang->sl_comprules = crp; pp = pat; diff --git a/src/testdir/test_spellfile.vim b/src/testdir/test_spellfile.vim index f46a25d99e..8f3ef4907d 100644 --- a/src/testdir/test_spellfile.vim +++ b/src/testdir/test_spellfile.vim @@ -334,6 +334,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, '') diff --git a/src/version.c b/src/version.c index 3cbce87d87..ff0960c227 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 450, /**/ 449, /**/