forked from aniani/vim
patch 9.0.1400: find_file_in_path() is not reentrant
Problem: find_file_in_path() is not reentrant. Solution: Instead of global variables pass pointers to the functions. (closes #12093)
This commit is contained in:
@@ -6767,8 +6767,13 @@ ex_splitview(exarg_T *eap)
|
||||
|
||||
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind)
|
||||
{
|
||||
char_u *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
|
||||
FNAME_MESS, TRUE, curbuf->b_ffname);
|
||||
FNAME_MESS, TRUE, curbuf->b_ffname,
|
||||
&file_to_find, &search_ctx);
|
||||
vim_free(file_to_find);
|
||||
vim_findfile_cleanup(search_ctx);
|
||||
if (fname == NULL)
|
||||
goto theend;
|
||||
eap->arg = fname;
|
||||
@@ -7032,21 +7037,25 @@ ex_find(exarg_T *eap)
|
||||
{
|
||||
char_u *fname;
|
||||
int count;
|
||||
char_u *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
|
||||
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
|
||||
TRUE, curbuf->b_ffname);
|
||||
TRUE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
||||
if (eap->addr_count > 0)
|
||||
{
|
||||
// Repeat finding the file "count" times. This matters when it
|
||||
// appears several times in the path.
|
||||
// Repeat finding the file "count" times. This matters when it appears
|
||||
// several times in the path.
|
||||
count = eap->line2;
|
||||
while (fname != NULL && --count > 0)
|
||||
{
|
||||
vim_free(fname);
|
||||
fname = find_file_in_path(NULL, 0, FNAME_MESS,
|
||||
FALSE, curbuf->b_ffname);
|
||||
FALSE, curbuf->b_ffname, &file_to_find, &search_ctx);
|
||||
}
|
||||
}
|
||||
VIM_CLEAR(file_to_find);
|
||||
vim_findfile_cleanup(search_ctx);
|
||||
|
||||
if (fname == NULL)
|
||||
return;
|
||||
@@ -7057,7 +7066,7 @@ ex_find(exarg_T *eap)
|
||||
}
|
||||
|
||||
/*
|
||||
* ":open" simulation: for now just work like ":visual".
|
||||
* ":open" simulation: for now works just like ":visual".
|
||||
*/
|
||||
static void
|
||||
ex_open(exarg_T *eap)
|
||||
@@ -7138,13 +7147,6 @@ do_exedit(
|
||||
// Special case: ":global/pat/visual\NLvi-commands"
|
||||
if (global_busy)
|
||||
{
|
||||
int rd = RedrawingDisabled;
|
||||
int nwr = no_wait_return;
|
||||
int ms = msg_scroll;
|
||||
#ifdef FEAT_GUI
|
||||
int he = hold_gui_events;
|
||||
#endif
|
||||
|
||||
if (eap->nextcmd != NULL)
|
||||
{
|
||||
stuffReadbuff(eap->nextcmd);
|
||||
@@ -7153,11 +7155,15 @@ do_exedit(
|
||||
|
||||
if (exmode_was != EXMODE_VIM)
|
||||
settmode(TMODE_RAW);
|
||||
int save_rd = RedrawingDisabled;
|
||||
RedrawingDisabled = 0;
|
||||
int save_nwr = no_wait_return;
|
||||
no_wait_return = 0;
|
||||
need_wait_return = FALSE;
|
||||
int save_ms = msg_scroll;
|
||||
msg_scroll = 0;
|
||||
#ifdef FEAT_GUI
|
||||
int save_he = hold_gui_events;
|
||||
hold_gui_events = 0;
|
||||
#endif
|
||||
set_must_redraw(UPD_CLEAR);
|
||||
@@ -7166,11 +7172,11 @@ do_exedit(
|
||||
main_loop(FALSE, TRUE);
|
||||
|
||||
pending_exmode_active = FALSE;
|
||||
RedrawingDisabled = rd;
|
||||
no_wait_return = nwr;
|
||||
msg_scroll = ms;
|
||||
RedrawingDisabled = save_rd;
|
||||
no_wait_return = save_nwr;
|
||||
msg_scroll = save_ms;
|
||||
#ifdef FEAT_GUI
|
||||
hold_gui_events = he;
|
||||
hold_gui_events = save_he;
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
@@ -982,6 +982,9 @@ findfilendir(
|
||||
|
||||
if (*fname != NUL && !error)
|
||||
{
|
||||
char_u *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST)
|
||||
@@ -992,13 +995,17 @@ findfilendir(
|
||||
find_what,
|
||||
curbuf->b_ffname,
|
||||
find_what == FINDFILE_DIR
|
||||
? (char_u *)"" : curbuf->b_p_sua);
|
||||
? (char_u *)"" : curbuf->b_p_sua,
|
||||
&file_to_find, &search_ctx);
|
||||
first = FALSE;
|
||||
|
||||
if (fresult != NULL && rettv->v_type == VAR_LIST)
|
||||
list_append_string(rettv->vval.v_list, fresult, -1);
|
||||
|
||||
} while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
|
||||
|
||||
vim_free(file_to_find);
|
||||
vim_findfile_cleanup(search_ctx);
|
||||
}
|
||||
|
||||
if (rettv->v_type == VAR_STRING)
|
||||
|
102
src/findfile.c
102
src/findfile.c
@@ -1571,23 +1571,21 @@ find_file_in_path(
|
||||
int len, // length of file name
|
||||
int options,
|
||||
int first, // use count'th matching file name
|
||||
char_u *rel_fname) // file name searching relative to
|
||||
char_u *rel_fname, // file name searching relative to
|
||||
char_u **file_to_find, // in/out: modified copy of file name
|
||||
char **search_ctx) // in/out: state of the search
|
||||
{
|
||||
return find_file_in_path_option(ptr, len, options, first,
|
||||
*curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
|
||||
FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
|
||||
FINDFILE_BOTH, rel_fname, curbuf->b_p_sua,
|
||||
file_to_find, search_ctx);
|
||||
}
|
||||
|
||||
static char_u *ff_file_to_find = NULL;
|
||||
static void *fdip_search_ctx = NULL;
|
||||
|
||||
# if defined(EXITFREE) || defined(PROTO)
|
||||
void
|
||||
free_findfile(void)
|
||||
{
|
||||
vim_free(ff_file_to_find);
|
||||
vim_findfile_cleanup(fdip_search_ctx);
|
||||
vim_free(ff_expand_buffer);
|
||||
VIM_CLEAR(ff_expand_buffer);
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -1607,10 +1605,13 @@ find_directory_in_path(
|
||||
char_u *ptr, // file name
|
||||
int len, // length of file name
|
||||
int options,
|
||||
char_u *rel_fname) // file name searching relative to
|
||||
char_u *rel_fname, // file name searching relative to
|
||||
char_u **file_to_find, // in/out: modified copy of file name
|
||||
char **search_ctx) // in/out: state of the search
|
||||
{
|
||||
return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
|
||||
FINDFILE_DIR, rel_fname, (char_u *)"");
|
||||
FINDFILE_DIR, rel_fname, (char_u *)"",
|
||||
file_to_find, search_ctx);
|
||||
}
|
||||
|
||||
char_u *
|
||||
@@ -1622,8 +1623,11 @@ find_file_in_path_option(
|
||||
char_u *path_option, // p_path or p_cdpath
|
||||
int find_what, // FINDFILE_FILE, _DIR or _BOTH
|
||||
char_u *rel_fname, // file name we are looking relative to.
|
||||
char_u *suffixes) // list of suffixes, 'suffixesadd' option
|
||||
char_u *suffixes, // list of suffixes, 'suffixesadd' option
|
||||
char_u **file_to_find, // in/out: modified copy of file name
|
||||
char **search_ctx_arg) // in/out: state of the search
|
||||
{
|
||||
ff_search_ctx_T **search_ctx = (ff_search_ctx_T **)search_ctx_arg;
|
||||
static char_u *dir;
|
||||
static int did_findfile_init = FALSE;
|
||||
char_u save_char;
|
||||
@@ -1649,9 +1653,9 @@ find_file_in_path_option(
|
||||
expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, NULL);
|
||||
ptr[len] = save_char;
|
||||
|
||||
vim_free(ff_file_to_find);
|
||||
ff_file_to_find = vim_strsave(NameBuff);
|
||||
if (ff_file_to_find == NULL) // out of memory
|
||||
vim_free(*file_to_find);
|
||||
*file_to_find = vim_strsave(NameBuff);
|
||||
if (*file_to_find == NULL) // out of memory
|
||||
{
|
||||
file_name = NULL;
|
||||
goto theend;
|
||||
@@ -1659,30 +1663,30 @@ find_file_in_path_option(
|
||||
if (options & FNAME_UNESC)
|
||||
{
|
||||
// Change all "\ " to " ".
|
||||
for (ptr = ff_file_to_find; *ptr != NUL; ++ptr)
|
||||
for (ptr = *file_to_find; *ptr != NUL; ++ptr)
|
||||
if (ptr[0] == '\\' && ptr[1] == ' ')
|
||||
mch_memmove(ptr, ptr + 1, STRLEN(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
rel_to_curdir = (ff_file_to_find[0] == '.'
|
||||
&& (ff_file_to_find[1] == NUL
|
||||
|| vim_ispathsep(ff_file_to_find[1])
|
||||
|| (ff_file_to_find[1] == '.'
|
||||
&& (ff_file_to_find[2] == NUL
|
||||
|| vim_ispathsep(ff_file_to_find[2])))));
|
||||
if (vim_isAbsName(ff_file_to_find)
|
||||
rel_to_curdir = ((*file_to_find)[0] == '.'
|
||||
&& ((*file_to_find)[1] == NUL
|
||||
|| vim_ispathsep((*file_to_find)[1])
|
||||
|| ((*file_to_find)[1] == '.'
|
||||
&& ((*file_to_find)[2] == NUL
|
||||
|| vim_ispathsep((*file_to_find)[2])))));
|
||||
if (vim_isAbsName(*file_to_find)
|
||||
// "..", "../path", "." and "./path": don't use the path_option
|
||||
|| rel_to_curdir
|
||||
# if defined(MSWIN)
|
||||
// handle "\tmp" as absolute path
|
||||
|| vim_ispathsep(ff_file_to_find[0])
|
||||
|| vim_ispathsep((*file_to_find)[0])
|
||||
// handle "c:name" as absolute path
|
||||
|| (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
|
||||
|| ((*file_to_find)[0] != NUL && (*file_to_find)[1] == ':')
|
||||
# endif
|
||||
# ifdef AMIGA
|
||||
// handle ":tmp" as absolute path
|
||||
|| ff_file_to_find[0] == ':'
|
||||
|| (*file_to_find)[0] == ':'
|
||||
# endif
|
||||
)
|
||||
{
|
||||
@@ -1696,9 +1700,9 @@ find_file_in_path_option(
|
||||
int l;
|
||||
int run;
|
||||
|
||||
if (path_with_url(ff_file_to_find))
|
||||
if (path_with_url(*file_to_find))
|
||||
{
|
||||
file_name = vim_strsave(ff_file_to_find);
|
||||
file_name = vim_strsave(*file_to_find);
|
||||
goto theend;
|
||||
}
|
||||
|
||||
@@ -1706,7 +1710,7 @@ find_file_in_path_option(
|
||||
// Otherwise or when this fails use the current directory.
|
||||
for (run = 1; run <= 2; ++run)
|
||||
{
|
||||
l = (int)STRLEN(ff_file_to_find);
|
||||
l = (int)STRLEN(*file_to_find);
|
||||
if (run == 1
|
||||
&& rel_to_curdir
|
||||
&& (options & FNAME_REL)
|
||||
@@ -1714,12 +1718,12 @@ find_file_in_path_option(
|
||||
&& STRLEN(rel_fname) + l < MAXPATHL)
|
||||
{
|
||||
STRCPY(NameBuff, rel_fname);
|
||||
STRCPY(gettail(NameBuff), ff_file_to_find);
|
||||
STRCPY(gettail(NameBuff), *file_to_find);
|
||||
l = (int)STRLEN(NameBuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
STRCPY(NameBuff, ff_file_to_find);
|
||||
STRCPY(NameBuff, *file_to_find);
|
||||
run = 2;
|
||||
}
|
||||
|
||||
@@ -1753,7 +1757,7 @@ find_file_in_path_option(
|
||||
if (first == TRUE)
|
||||
{
|
||||
// vim_findfile_free_visited can handle a possible NULL pointer
|
||||
vim_findfile_free_visited(fdip_search_ctx);
|
||||
vim_findfile_free_visited(*search_ctx);
|
||||
dir = path_option;
|
||||
did_findfile_init = FALSE;
|
||||
}
|
||||
@@ -1762,7 +1766,7 @@ find_file_in_path_option(
|
||||
{
|
||||
if (did_findfile_init)
|
||||
{
|
||||
file_name = vim_findfile(fdip_search_ctx);
|
||||
file_name = vim_findfile(*search_ctx);
|
||||
if (file_name != NULL)
|
||||
break;
|
||||
|
||||
@@ -1776,8 +1780,8 @@ find_file_in_path_option(
|
||||
{
|
||||
// We searched all paths of the option, now we can
|
||||
// free the search context.
|
||||
vim_findfile_cleanup(fdip_search_ctx);
|
||||
fdip_search_ctx = NULL;
|
||||
vim_findfile_cleanup(*search_ctx);
|
||||
*search_ctx = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1790,10 +1794,10 @@ find_file_in_path_option(
|
||||
|
||||
// get the stopdir string
|
||||
r_ptr = vim_findfile_stopdir(buf);
|
||||
fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
|
||||
*search_ctx = vim_findfile_init(buf, *file_to_find,
|
||||
r_ptr, 100, FALSE, find_what,
|
||||
fdip_search_ctx, FALSE, rel_fname);
|
||||
if (fdip_search_ctx != NULL)
|
||||
*search_ctx, FALSE, rel_fname);
|
||||
if (*search_ctx != NULL)
|
||||
did_findfile_init = TRUE;
|
||||
vim_free(buf);
|
||||
}
|
||||
@@ -1804,20 +1808,17 @@ find_file_in_path_option(
|
||||
if (first == TRUE)
|
||||
{
|
||||
if (find_what == FINDFILE_DIR)
|
||||
semsg(_(e_cant_find_directory_str_in_cdpath),
|
||||
ff_file_to_find);
|
||||
semsg(_(e_cant_find_directory_str_in_cdpath), *file_to_find);
|
||||
else
|
||||
semsg(_(e_cant_find_file_str_in_path),
|
||||
ff_file_to_find);
|
||||
semsg(_(e_cant_find_file_str_in_path), *file_to_find);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (find_what == FINDFILE_DIR)
|
||||
semsg(_(e_no_more_directory_str_found_in_cdpath),
|
||||
ff_file_to_find);
|
||||
*file_to_find);
|
||||
else
|
||||
semsg(_(e_no_more_file_str_found_in_path),
|
||||
ff_file_to_find);
|
||||
semsg(_(e_no_more_file_str_found_in_path), *file_to_find);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2046,8 +2047,11 @@ find_file_name_in_path(
|
||||
|
||||
if (options & FNAME_EXP)
|
||||
{
|
||||
char_u *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
|
||||
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
||||
TRUE, rel_fname);
|
||||
TRUE, rel_fname, &file_to_find, &search_ctx);
|
||||
|
||||
# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
|
||||
/*
|
||||
@@ -2063,7 +2067,7 @@ find_file_name_in_path(
|
||||
ptr = tofree;
|
||||
len = (int)STRLEN(ptr);
|
||||
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
||||
TRUE, rel_fname);
|
||||
TRUE, rel_fname, &file_to_find, &search_ctx);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
@@ -2080,8 +2084,12 @@ find_file_name_in_path(
|
||||
while (file_name != NULL && --count > 0)
|
||||
{
|
||||
vim_free(file_name);
|
||||
file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
|
||||
file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname,
|
||||
&file_to_find, &search_ctx);
|
||||
}
|
||||
|
||||
vim_free(file_to_find);
|
||||
vim_findfile_cleanup(search_ctx);
|
||||
}
|
||||
else
|
||||
file_name = vim_strnsave(ptr, len);
|
||||
|
@@ -2473,9 +2473,13 @@ vim_chdir(char_u *new_dir)
|
||||
{
|
||||
char_u *dir_name;
|
||||
int r;
|
||||
char_u *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
|
||||
dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
|
||||
FNAME_MESS, curbuf->b_ffname);
|
||||
FNAME_MESS, curbuf->b_ffname, &file_to_find, &search_ctx);
|
||||
vim_free(file_to_find);
|
||||
vim_findfile_cleanup(search_ctx);
|
||||
if (dir_name == NULL)
|
||||
return -1;
|
||||
r = mch_chdir((char *)dir_name);
|
||||
|
@@ -3,10 +3,10 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
|
||||
char_u *vim_findfile_stopdir(char_u *buf);
|
||||
void vim_findfile_cleanup(void *ctx);
|
||||
char_u *vim_findfile(void *search_ctx_arg);
|
||||
char_u *find_file_in_path(char_u *ptr, int len, int options, int first, char_u *rel_fname);
|
||||
char_u *find_file_in_path(char_u *ptr, int len, int options, int first, char_u *rel_fname, char_u **file_to_find, char **search_ctx);
|
||||
void free_findfile(void);
|
||||
char_u *find_directory_in_path(char_u *ptr, int len, int options, char_u *rel_fname);
|
||||
char_u *find_file_in_path_option(char_u *ptr, int len, int options, int first, char_u *path_option, int find_what, char_u *rel_fname, char_u *suffixes);
|
||||
char_u *find_directory_in_path(char_u *ptr, int len, int options, char_u *rel_fname, char_u **file_to_find, char **search_ctx);
|
||||
char_u *find_file_in_path_option(char_u *ptr, int len, int options, int first, char_u *path_option, int find_what, char_u *rel_fname, char_u *suffixes, char_u **file_to_find, char **search_ctx_arg);
|
||||
char_u *grab_file_name(long count, linenr_T *file_lnum);
|
||||
char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum);
|
||||
char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u *rel_fname, linenr_T *file_lnum);
|
||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1400,
|
||||
/**/
|
||||
1399,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user