static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to);
static int sal_to_bool(char_u *s);
static int get_affix_flags(afffile_T *affile, char_u *afflist);
-static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist);
-static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist);
+static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist, int *cntp);
+static int get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist, int *cntp);
static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afffile_T *affile, hashtab_T *ht, hashtab_T *xht, int condit, int flags, char_u *pfxlist, int pfxlen);
static void *getroom(spellinfo_T *spin, size_t len, int align);
static char_u *getroom_save(spellinfo_T *spin, char_u *s);
}
}
+/*
+ * Append one affix or compound ID to "store_afflist".
+ * Returns FAIL when this would overrun the fixed-size buffer.
+ */
+ static int
+store_afflist_add(
+ char_u *store_afflist,
+ int *cntp,
+ int id)
+{
+ if (*cntp >= MAXWLEN - 1)
+ {
+ emsg(_(e_too_many_postponed_prefixes_spell));
+ return FAIL;
+ }
+ store_afflist[(*cntp)++] = id;
+ store_afflist[*cntp] = NUL;
+ return OK;
+}
+
/*
* Return TRUE if flag "flag" appears in affix list "afflist".
*/
char_u *afflist;
char_u store_afflist[MAXWLEN];
int pfxlen;
+ int totlen;
int need_affix;
char_u *dw;
char_u *pc;
flags = 0;
store_afflist[0] = NUL;
pfxlen = 0;
+ totlen = 0;
need_affix = FALSE;
if (afflist != NULL)
{
need_affix = TRUE;
if (affile->af_pfxpostpone)
+ {
// Need to store the list of prefix IDs with the word.
- pfxlen = get_pfxlist(affile, afflist, store_afflist);
+ if (get_pfxlist(affile, afflist, store_afflist, &totlen)
+ == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ pfxlen = totlen;
+ }
if (spin->si_compflags != NULL)
+ {
// Need to store the list of compound flags with the word.
// Concatenate them to the list of prefix IDs.
- get_compflags(affile, afflist, store_afflist + pfxlen);
+ if (get_compflags(affile, afflist, store_afflist, &totlen)
+ == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ }
}
// Add the word to the word tree(s).
/*
* Get the list of prefix IDs from the affix list "afflist".
* Used for PFXPOSTPONE.
- * Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
- * and return the number of affixes.
+ * Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL.
+ * Returns FAIL when the fixed-size buffer would overflow.
*/
static int
get_pfxlist(
afffile_T *affile,
char_u *afflist,
- char_u *store_afflist)
+ char_u *store_afflist,
+ int *cntp)
{
char_u *p;
char_u *prevp;
- int cnt = 0;
int id;
char_u key[AH_KEY_LEN];
hashitem_T *hi;
if (!HASHITEM_EMPTY(hi))
{
id = HI2AH(hi)->ah_newID;
- if (id != 0)
- store_afflist[cnt++] = id;
+ if (id != 0 && store_afflist_add(store_afflist, cntp, id) == FAIL)
+ return FAIL;
}
}
if (affile->af_flagtype == AFT_NUM && *p == ',')
++p;
}
- store_afflist[cnt] = NUL;
- return cnt;
+ return OK;
}
/*
* Get the list of compound IDs from the affix list "afflist" that are used
* for compound words.
* Puts the flags in "store_afflist[]".
+ * Returns FAIL when the fixed-size buffer would overflow.
*/
- static void
+ static int
get_compflags(
afffile_T *affile,
char_u *afflist,
- char_u *store_afflist)
+ char_u *store_afflist,
+ int *cntp)
{
char_u *p;
char_u *prevp;
- int cnt = 0;
char_u key[AH_KEY_LEN];
hashitem_T *hi;
// A flag is a compound flag if it appears in "af_comp".
vim_strncpy(key, prevp, p - prevp);
hi = hash_find(&affile->af_comp, key);
- if (!HASHITEM_EMPTY(hi))
- store_afflist[cnt++] = HI2CI(hi)->ci_newID;
+ if (!HASHITEM_EMPTY(hi)
+ && store_afflist_add(store_afflist, cntp,
+ HI2CI(hi)->ci_newID) == FAIL)
+ return FAIL;
}
if (affile->af_flagtype == AFT_NUM && *p == ',')
++p;
}
- store_afflist[cnt] = NUL;
+ return OK;
}
/*
if (affile->af_pfxpostpone
|| spin->si_compflags != NULL)
{
+ int listlen = 0;
+
if (affile->af_pfxpostpone)
+ {
// Get prefix IDS from the affix list.
- use_pfxlen = get_pfxlist(affile,
- ae->ae_flags, store_afflist);
+ if (get_pfxlist(affile, ae->ae_flags,
+ store_afflist, &listlen)
+ == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ use_pfxlen = listlen;
+ }
else
use_pfxlen = 0;
use_pfxlist = store_afflist;
for (j = 0; j < use_pfxlen; ++j)
if (pfxlist[i] == use_pfxlist[j])
break;
- if (j == use_pfxlen)
- use_pfxlist[use_pfxlen++] = pfxlist[i];
+ if (j == use_pfxlen
+ && store_afflist_add(use_pfxlist,
+ &listlen, pfxlist[i])
+ == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ use_pfxlen = listlen;
}
+ if (retval == FAIL)
+ break;
if (spin->si_compflags != NULL)
// Get compound IDS from the affix list.
- get_compflags(affile, ae->ae_flags,
- use_pfxlist + use_pfxlen);
+ if (get_compflags(affile, ae->ae_flags,
+ use_pfxlist, &listlen)
+ == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ if (retval == FAIL)
+ break;
// Combine the list of compound flags.
// Concatenate them to the prefix IDs list.
use_pfxlist[j] != NUL; ++j)
if (pfxlist[i] == use_pfxlist[j])
break;
- if (use_pfxlist[j] == NUL)
+ if (use_pfxlist[j] == NUL
+ && store_afflist_add(use_pfxlist,
+ &listlen, pfxlist[i])
+ == FAIL)
{
- use_pfxlist[j++] = pfxlist[i];
- use_pfxlist[j] = NUL;
+ retval = FAIL;
+ break;
}
}
+ if (retval == FAIL)
+ break;
}
}
char_u line[MAXWLEN * 2];
long fpos, fpos_next = 0;
int i;
+ size_t linelen;
char_u *spf;
if (!valid_spell_word(word, word + len))
fpos_next = ftell(fd);
if (fpos_next < 0)
break; // should never happen
- if (STRNCMP(word, line, len) == 0
+ linelen = STRLEN(line);
+ if (linelen >= (size_t)len
+ && STRNCMP(word, line, len) == 0
&& (line[len] == '/' || line[len] < ' '))
{
// Found duplicate word. Remove it by writing a '#' at
defer delete('Xbof2.spl')
endfunc
+func Test_mkspell_no_affixlist_overflow()
+ let aff_lines = [
+ \ 'SET ISO8859-1',
+ \ 'PFXPOSTPONE',
+ \ 'PFX A Y 1',
+ \ 'PFX A 0 pre .',
+ \ ]
+ call writefile(aff_lines, 'Xaffbof.aff', 'D')
+ call writefile(['1', 'word/' .. repeat('A', 300)], 'Xaffbof.dic', 'D')
+
+ call assert_fails('mkspell! Xaffbof.spl Xaffbof',
+ \ 'Too many postponed prefixes and/or compound flags')
+ call assert_false(filereadable('Xaffbof.spl'))
+endfunc
+
+func Test_mkspell_no_compflag_overflow()
+ " Overflow the compound-flag path in get_compflags(): a word whose
+ " affix list repeats a compound flag many times accumulates one ID per
+ " occurrence, overrunning store_afflist[MAXWLEN].
+ let aff_lines = [
+ \ 'SET ISO8859-1',
+ \ 'COMPOUNDFLAG c',
+ \ ]
+ call writefile(aff_lines, 'Xcompbof.aff', 'D')
+
+ " Repeat the compound flag 'c' far past MAXWLEN.
+ call writefile(['1', 'word/' .. repeat('c', 300)], 'Xcompbof.dic', 'D')
+
+ call assert_fails('mkspell! Xcompbof.spl Xcompbof',
+ \ 'Too many postponed prefixes and/or compound flags')
+ call assert_false(filereadable('Xcompbof.spl'))
+endfunc
" vim: shiftwidth=2 sts=2 expandtab