Compare commits

..

2 Commits

Author SHA1 Message Date
2c7b906afb patch 8.0.1470: integer overflow when using regexp pattern
Problem:    Integer overflow when using regexp pattern. (geeknik)
Solution:   Use a long instead of int. (Christian Brabandt, closes #2251)
2018-02-04 18:22:46 +01:00
2374faae11 patch 8.0.1469: when package path is a symlink 'runtimepath' is wrong
Problem:    When package path is a symlink adding it to 'runtimepath' happens
            at the end.
Solution:   Do not resolve symlinks before locating the position in
            'runtimepath'. (Ozaki Kiichi, closes #2604)
2018-02-04 17:47:42 +01:00
4 changed files with 201 additions and 126 deletions

View File

@ -3567,13 +3567,11 @@ source_all_matches(char_u *pat)
}
}
/* used for "cookie" of add_pack_plugin() */
static int APP_ADD_DIR;
static int APP_LOAD;
static int APP_BOTH;
static void
add_pack_plugin(char_u *fname, void *cookie)
/*
* Add the package directory to 'runtimepath'.
*/
static int
add_pack_dir_to_rtp(char_u *fname)
{
char_u *p4, *p3, *p2, *p1, *p;
char_u *insp;
@ -3582,125 +3580,154 @@ add_pack_plugin(char_u *fname, void *cookie)
int keep;
size_t oldlen;
size_t addlen;
char_u *afterdir;
char_u *afterdir = NULL;
size_t afterlen = 0;
char_u *ffname = fix_fname(fname);
char_u *ffname = NULL;
size_t fname_len;
char_u *buf = NULL;
char_u *rtp_ffname;
int match;
int retval = FAIL;
p4 = p3 = p2 = p1 = get_past_head(fname);
for (p = p1; *p; MB_PTR_ADV(p))
if (vim_ispathsep_nocolon(*p))
{
p4 = p3; p3 = p2; p2 = p1; p1 = p;
}
/* now we have:
* rtp/pack/name/start/name
* p4 p3 p2 p1
*
* find the part up to "pack" in 'runtimepath' */
c = *++p4; /* append pathsep in order to expand symlink */
*p4 = NUL;
ffname = fix_fname(fname);
*p4 = c;
if (ffname == NULL)
return;
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL)
return FAIL;
/* Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. */
fname_len = STRLEN(ffname);
insp = p_rtp;
buf = alloc(MAXPATHL);
if (buf == NULL)
goto theend;
while (*insp != NUL)
{
/* directory is not yet in 'runtimepath', add it */
p4 = p3 = p2 = p1 = get_past_head(ffname);
for (p = p1; *p; MB_PTR_ADV(p))
if (vim_ispathsep_nocolon(*p))
{
p4 = p3; p3 = p2; p2 = p1; p1 = p;
}
/* now we have:
* rtp/pack/name/start/name
* p4 p3 p2 p1
*
* find the part up to "pack" in 'runtimepath' */
c = *p4;
*p4 = NUL;
/* Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. */
fname_len = STRLEN(ffname);
insp = p_rtp;
buf = alloc(MAXPATHL);
if (buf == NULL)
copy_option_part(&insp, buf, MAXPATHL, ",");
add_pathsep(buf);
rtp_ffname = fix_fname(buf);
if (rtp_ffname == NULL)
goto theend;
while (*insp != NUL)
{
copy_option_part(&insp, buf, MAXPATHL, ",");
add_pathsep(buf);
rtp_ffname = fix_fname(buf);
if (rtp_ffname == NULL)
goto theend;
match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0;
vim_free(rtp_ffname);
if (match)
break;
}
if (*insp == NUL)
/* not found, append at the end */
insp = p_rtp + STRLEN(p_rtp);
else
/* append after the matching directory. */
--insp;
*p4 = c;
/* check if rtp/pack/name/start/name/after exists */
afterdir = concat_fnames(ffname, (char_u *)"after", TRUE);
if (afterdir != NULL && mch_isdir(afterdir))
afterlen = STRLEN(afterdir) + 1; /* add one for comma */
oldlen = STRLEN(p_rtp);
addlen = STRLEN(ffname) + 1; /* add one for comma */
new_rtp = alloc((int)(oldlen + addlen + afterlen + 1));
/* add one for NUL */
if (new_rtp == NULL)
goto theend;
keep = (int)(insp - p_rtp);
mch_memmove(new_rtp, p_rtp, keep);
new_rtp[keep] = ',';
mch_memmove(new_rtp + keep + 1, ffname, addlen);
if (p_rtp[keep] != NUL)
mch_memmove(new_rtp + keep + addlen, p_rtp + keep,
oldlen - keep + 1);
if (afterlen > 0)
{
STRCAT(new_rtp, ",");
STRCAT(new_rtp, afterdir);
}
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
vim_free(new_rtp);
vim_free(afterdir);
match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0;
vim_free(rtp_ffname);
if (match)
break;
}
if (cookie != &APP_ADD_DIR)
if (*insp == NUL)
/* not found, append at the end */
insp = p_rtp + STRLEN(p_rtp);
else
/* append after the matching directory. */
--insp;
/* check if rtp/pack/name/start/name/after exists */
afterdir = concat_fnames(fname, (char_u *)"after", TRUE);
if (afterdir != NULL && mch_isdir(afterdir))
afterlen = STRLEN(afterdir) + 1; /* add one for comma */
oldlen = STRLEN(p_rtp);
addlen = STRLEN(fname) + 1; /* add one for comma */
new_rtp = alloc((int)(oldlen + addlen + afterlen + 1));
/* add one for NUL */
if (new_rtp == NULL)
goto theend;
keep = (int)(insp - p_rtp);
mch_memmove(new_rtp, p_rtp, keep);
new_rtp[keep] = ',';
mch_memmove(new_rtp + keep + 1, fname, addlen);
if (p_rtp[keep] != NUL)
mch_memmove(new_rtp + keep + addlen, p_rtp + keep, oldlen - keep + 1);
if (afterlen > 0)
{
static char *plugpat = "%s/plugin/**/*.vim";
static char *ftpat = "%s/ftdetect/*.vim";
int len;
char_u *pat;
len = (int)STRLEN(ffname) + (int)STRLEN(ftpat);
pat = alloc(len);
if (pat == NULL)
goto theend;
vim_snprintf((char *)pat, len, plugpat, ffname);
source_all_matches(pat);
#ifdef FEAT_AUTOCMD
{
char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes");
/* If runtime/filetype.vim wasn't loaded yet, the scripts will be
* found when it loads. */
if (cmd != NULL && eval_to_number(cmd) > 0)
{
do_cmdline_cmd((char_u *)"augroup filetypedetect");
vim_snprintf((char *)pat, len, ftpat, ffname);
source_all_matches(pat);
do_cmdline_cmd((char_u *)"augroup END");
}
vim_free(cmd);
}
#endif
vim_free(pat);
STRCAT(new_rtp, ",");
STRCAT(new_rtp, afterdir);
}
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
vim_free(new_rtp);
retval = OK;
theend:
vim_free(buf);
vim_free(ffname);
vim_free(afterdir);
return retval;
}
/*
* Load scripts in "plugin" and "ftdetect" directories of the package.
*/
static int
load_pack_plugin(char_u *fname)
{
static char *plugpat = "%s/plugin/**/*.vim";
static char *ftpat = "%s/ftdetect/*.vim";
int len;
char_u *ffname = fix_fname(fname);
char_u *pat = NULL;
int retval = FAIL;
if (ffname == NULL)
return FAIL;
len = (int)STRLEN(ffname) + (int)STRLEN(ftpat);
pat = alloc(len);
if (pat == NULL)
goto theend;
vim_snprintf((char *)pat, len, plugpat, ffname);
source_all_matches(pat);
#ifdef FEAT_AUTOCMD
{
char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes");
/* If runtime/filetype.vim wasn't loaded yet, the scripts will be
* found when it loads. */
if (cmd != NULL && eval_to_number(cmd) > 0)
{
do_cmdline_cmd((char_u *)"augroup filetypedetect");
vim_snprintf((char *)pat, len, ftpat, ffname);
source_all_matches(pat);
do_cmdline_cmd((char_u *)"augroup END");
}
vim_free(cmd);
}
#endif
vim_free(pat);
retval = OK;
theend:
vim_free(ffname);
return retval;
}
/* used for "cookie" of add_pack_plugin() */
static int APP_ADD_DIR;
static int APP_LOAD;
static int APP_BOTH;
static void
add_pack_plugin(char_u *fname, void *cookie)
{
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)fname) == NULL)
/* directory is not yet in 'runtimepath', add it */
if (add_pack_dir_to_rtp(fname) == FAIL)
return;
if (cookie != &APP_ADD_DIR)
load_pack_plugin(fname);
}
/*

View File

@ -1600,7 +1600,7 @@ nfa_regatom(void)
default:
{
int n = 0;
long n = 0;
int cmp = c;
if (c == '<' || c == '>')
@ -1628,7 +1628,14 @@ nfa_regatom(void)
/* \%{n}v \%{n}<v \%{n}>v */
EMIT(cmp == '<' ? NFA_VCOL_LT :
cmp == '>' ? NFA_VCOL_GT : NFA_VCOL);
EMIT(n);
#if VIM_SIZEOF_INT < VIM_SIZEOF_LONG
if (n > INT_MAX)
{
EMSG(_("E951: \\% value too large"));
return FAIL;
}
#endif
EMIT((int)n);
break;
}
else if (c == '\'' && n == 0)
@ -3970,7 +3977,7 @@ static int nfa_match;
#ifdef FEAT_RELTIME
static proftime_T *nfa_time_limit;
static int *nfa_timed_out;
static int nfa_time_count;
static int nfa_time_count;
#endif
static void copy_pim(nfa_pim_T *to, nfa_pim_T *from);
@ -4068,10 +4075,10 @@ copy_ze_off(regsub_T *to, regsub_T *from)
if (REG_MULTI)
{
if (from->list.multi[0].end_lnum >= 0)
{
{
to->list.multi[0].end_lnum = from->list.multi[0].end_lnum;
to->list.multi[0].end_col = from->list.multi[0].end_col;
}
}
}
else
{
@ -5124,9 +5131,9 @@ recursive_regmatch(
}
if (state->c == NFA_START_INVISIBLE_BEFORE
|| state->c == NFA_START_INVISIBLE_BEFORE_FIRST
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG_FIRST)
|| state->c == NFA_START_INVISIBLE_BEFORE_FIRST
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG_FIRST)
{
/* The recursive match must end at the current position. When "pim" is
* not NULL it specifies the current position. */
@ -6302,7 +6309,7 @@ nfa_regmatch(
}
}
else if (state->c < 0 ? check_char_class(state->c, curc)
: (curc == state->c
: (curc == state->c
|| (rex.reg_ic && MB_TOLOWER(curc)
== MB_TOLOWER(state->c))))
{
@ -6863,7 +6870,7 @@ nfa_regmatch(
&& (REG_MULTI
? (reglnum < nfa_endp->se_u.pos.lnum
|| (reglnum == nfa_endp->se_u.pos.lnum
&& (int)(reginput - regline)
&& (int)(reginput - regline)
< nfa_endp->se_u.pos.col))
: reginput < nfa_endp->se_u.ptr))))
{

View File

@ -37,8 +37,8 @@ func Test_packadd()
call assert_equal(77, g:plugin_also_works)
call assert_equal(17, g:ftdetect_works)
call assert_true(len(&rtp) > len(rtp))
call assert_true(&rtp =~ '/testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
call assert_true(&rtp =~ '/testdir/Xdir/pack/mine/opt/mytest/after$')
call assert_match('/testdir/Xdir/pack/mine/opt/mytest\($\|,\)', &rtp)
call assert_match('/testdir/Xdir/pack/mine/opt/mytest/after$', &rtp)
" Check exception
call assert_fails("packadd directorynotfound", 'E919:')
@ -60,7 +60,7 @@ func Test_packadd_start()
call assert_equal(24, g:plugin_works)
call assert_true(len(&rtp) > len(rtp))
call assert_true(&rtp =~ '/testdir/Xdir/pack/mine/start/other\($\|,\)')
call assert_match('/testdir/Xdir/pack/mine/start/other\($\|,\)', &rtp)
endfunc
func Test_packadd_noload()
@ -77,7 +77,7 @@ func Test_packadd_noload()
packadd! mytest
call assert_true(len(&rtp) > len(rtp))
call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
call assert_match('testdir/Xdir/pack/mine/opt/mytest\($\|,\)', &rtp)
call assert_equal(0, g:plugin_works)
" check the path is not added twice
@ -108,7 +108,7 @@ func Test_packadd_symlink_dir()
packadd mytest
" Must have been inserted in the middle, not at the end
call assert_true(&rtp =~ '/pack/mine/opt/mytest,')
call assert_match('/pack/mine/opt/mytest,', &rtp)
call assert_equal(44, g:plugin_works)
" No change when doing it again.
@ -121,6 +121,43 @@ func Test_packadd_symlink_dir()
exec "silent !rm" top2_dir
endfunc
func Test_packadd_symlink_dir2()
if !has('unix')
return
endif
let top2_dir = s:topdir . '/Xdir2'
let real_dir = s:topdir . '/Xsym/pack'
call mkdir(top2_dir, 'p')
call mkdir(real_dir, 'p')
let &rtp = top2_dir . ',' . top2_dir . '/after'
let &packpath = &rtp
exec "silent !ln -s ../Xsym/pack" top2_dir . '/pack'
let s:plugdir = top2_dir . '/pack/mine/opt/mytest'
call mkdir(s:plugdir . '/plugin', 'p')
exe 'split ' . s:plugdir . '/plugin/test.vim'
call setline(1, 'let g:plugin_works = 48')
wq
let g:plugin_works = 0
packadd mytest
" Must have been inserted in the middle, not at the end
call assert_match('/Xdir2/pack/mine/opt/mytest,', &rtp)
call assert_equal(48, g:plugin_works)
" No change when doing it again.
let rtp_before = &rtp
packadd mytest
call assert_equal(rtp_before, &rtp)
set rtp&
let rtp = &rtp
exec "silent !rm" top2_dir . '/pack'
exec "silent !rmdir" top2_dir
endfunc
" Check command-line completion for 'packadd'
func Test_packadd_completion()
let optdir1 = &packpath . '/pack/mine/opt'
@ -196,9 +233,9 @@ func Test_helptags()
helptags ALL
let tags1 = readfile(docdir1 . '/tags')
call assert_true(tags1[0] =~ 'look-here')
call assert_match('look-here', tags1[0])
let tags2 = readfile(docdir2 . '/tags')
call assert_true(tags2[0] =~ 'look-away')
call assert_match('look-away', tags2[0])
endfunc
func Test_colorscheme()

View File

@ -771,6 +771,10 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1470,
/**/
1469,
/**/
1468,
/**/