Patch 9.0.1400
Problem: find_file_in_path() is not reentrant.
Solution: Instead of global variables pass pointers to the functions.
(closes #12093)
Files: src/findfile.c, src/proto/
findfile.pro, src/filepath.c,
src/ex_docmd.c, src/misc2.c
*** ../vim-9.0.1399/src/findfile.c 2023-02-01 13:11:11.710991162 +0000
--- src/findfile.c 2023-03-11 13:42:42.523776690 +0000
***************
*** 1571,1593 ****
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
{
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);
}
- 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);
}
# endif
--- 1571,1591 ----
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 **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,
! file_to_find, search_ctx);
}
# if defined(EXITFREE) || defined(PROTO)
void
free_findfile(void)
{
! VIM_CLEAR(ff_expand_buffer);
}
# endif
***************
*** 1607,1616 ****
char_u *ptr, // file name
int len, // length of file name
int options,
! char_u *rel_fname) // file name searching relative to
{
return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
! FINDFILE_DIR, rel_fname, (char_u *)"");
}
char_u *
--- 1605,1617 ----
char_u *ptr, // file name
int len, // length of file name
int options,
! 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 *)"",
! file_to_find, search_ctx);
}
char_u *
***************
*** 1622,1629 ****
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
{
static char_u *dir;
static int did_findfile_init = FALSE;
char_u save_char;
--- 1623,1633 ----
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 **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,1657 ****
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
{
file_name = NULL;
goto theend;
--- 1653,1661 ----
expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, NULL);
ptr[len] = save_char;
! 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,1688 ****
if (options & FNAME_UNESC)
{
// Change all "\ " to " ".
! for (ptr = ff_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)
// "..", "../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])
// handle "c:name" as absolute path
! || (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
# endif
# ifdef AMIGA
// handle ":tmp" as absolute path
! || ff_file_to_find[0] == ':'
# endif
)
{
--- 1663,1692 ----
if (options & FNAME_UNESC)
{
// Change all "\ " to " ".
! for (ptr = *file_to_find; *ptr != NUL; ++ptr)
if (ptr[0] == '\\' && ptr[1] == ' ')
mch_memmove(ptr, ptr + 1, STRLEN(ptr));
}
}
! 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((*file_to_find)[0])
// handle "c:name" as absolute path
! || ((*file_to_find)[0] != NUL && (*file_to_find)[1] == ':')
# endif
# ifdef AMIGA
// handle ":tmp" as absolute path
! || (*file_to_find)[0] == ':'
# endif
)
{
***************
*** 1696,1704 ****
int l;
int run;
! if (path_with_url(ff_file_to_find))
{
! file_name = vim_strsave(ff_file_to_find);
goto theend;
}
--- 1700,1708 ----
int l;
int run;
! if (path_with_url(*file_to_find))
{
! file_name = vim_strsave(*file_to_find);
goto theend;
}
***************
*** 1706,1712 ****
// Otherwise or when this fails use the current directory.
for (run = 1; run <= 2; ++run)
{
! l = (int)STRLEN(ff_file_to_find);
if (run == 1
&& rel_to_curdir
&& (options & FNAME_REL)
--- 1710,1716 ----
// Otherwise or when this fails use the current directory.
for (run = 1; run <= 2; ++run)
{
! l = (int)STRLEN(*file_to_find);
if (run == 1
&& rel_to_curdir
&& (options & FNAME_REL)
***************
*** 1714,1725 ****
&& STRLEN(rel_fname) + l < MAXPATHL)
{
STRCPY(NameBuff, rel_fname);
! STRCPY(gettail(NameBuff), ff_file_to_find);
l = (int)STRLEN(NameBuff);
}
else
{
! STRCPY(NameBuff, ff_file_to_find);
run = 2;
}
--- 1718,1729 ----
&& STRLEN(rel_fname) + l < MAXPATHL)
{
STRCPY(NameBuff, rel_fname);
! STRCPY(gettail(NameBuff), *file_to_find);
l = (int)STRLEN(NameBuff);
}
else
{
! STRCPY(NameBuff, *file_to_find);
run = 2;
}
***************
*** 1753,1759 ****
if (first == TRUE)
{
// vim_findfile_free_visited can handle a possible NULL pointer
! vim_findfile_free_visited(fdip_search_ctx);
dir = path_option;
did_findfile_init = FALSE;
}
--- 1757,1763 ----
if (first == TRUE)
{
// vim_findfile_free_visited can handle a possible NULL pointer
! vim_findfile_free_visited(*search_ctx);
dir = path_option;
did_findfile_init = FALSE;
}
***************
*** 1762,1768 ****
{
if (did_findfile_init)
{
! file_name = vim_findfile(fdip_search_ctx);
if (file_name != NULL)
break;
--- 1766,1772 ----
{
if (did_findfile_init)
{
! file_name = vim_findfile(*search_ctx);
if (file_name != NULL)
break;
***************
*** 1776,1783 ****
{
// We searched all paths of the option, now we can
// free the search context.
! vim_findfile_cleanup(fdip_search_ctx);
! fdip_search_ctx = NULL;
break;
}
--- 1780,1787 ----
{
// We searched all paths of the option, now we can
// free the search context.
! vim_findfile_cleanup(*search_ctx);
! *search_ctx = NULL;
break;
}
***************
*** 1790,1799 ****
// get the stopdir string
r_ptr = vim_findfile_stopdir(buf);
! fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
r_ptr, 100, FALSE, find_what,
! fdip_search_ctx, FALSE, rel_fname);
! if (fdip_search_ctx != NULL)
did_findfile_init = TRUE;
vim_free(buf);
}
--- 1794,1803 ----
// get the stopdir string
r_ptr = vim_findfile_stopdir(buf);
! *search_ctx = vim_findfile_init(buf, *file_to_find,
r_ptr, 100, FALSE, find_what,
! *search_ctx, FALSE, rel_fname);
! if (*search_ctx != NULL)
did_findfile_init = TRUE;
vim_free(buf);
}
***************
*** 1804,1823 ****
if (first == TRUE)
{
if (find_what == FINDFILE_DIR)
! semsg(_(e_cant_find_directory_str_in_cdpath),
! ff_file_to_find);
else
! semsg(_(e_cant_find_file_str_in_path),
! ff_file_to_find);
}
else
{
if (find_what == FINDFILE_DIR)
semsg(_(e_no_more_directory_str_found_in_cdpath),
! ff_file_to_find);
else
! semsg(_(e_no_more_file_str_found_in_path),
! ff_file_to_find);
}
}
--- 1808,1824 ----
if (first == TRUE)
{
if (find_what == FINDFILE_DIR)
! semsg(_(e_cant_find_directory_str_in_cdpath), *file_to_find);
else
! 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),
! *file_to_find);
else
! semsg(_(e_no_more_file_str_found_in_path), *file_to_find);
}
}
***************
*** 2046,2053 ****
if (options & FNAME_EXP)
{
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
! TRUE, rel_fname);
# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
/*
--- 2047,2057 ----
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, &file_to_find, &search_ctx);
# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
/*
***************
*** 2063,2069 ****
ptr = tofree;
len = (int)STRLEN(ptr);
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
! TRUE, rel_fname);
}
}
# endif
--- 2067,2073 ----
ptr = tofree;
len = (int)STRLEN(ptr);
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
! TRUE, rel_fname, &file_to_find, &search_ctx);
}
}
# endif
***************
*** 2080,2087 ****
while (file_name != NULL && --count > 0)
{
vim_free(file_name);
! file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
}
}
else
file_name = vim_strnsave(ptr, len);
--- 2084,2095 ----
while (file_name != NULL && --count > 0)
{
vim_free(file_name);
! 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);
*** ../vim-9.0.1399/src/proto/
findfile.pro 2022-06-27 23:15:06.000000000 +0100
--- src/proto/
findfile.pro 2023-03-11 13:23:46.163820544 +0000
***************
*** 3,12 ****
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);
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 *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);
--- 3,12 ----
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 **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 **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);
*** ../vim-9.0.1399/src/filepath.c 2023-01-22 18:38:45.498261340 +0000
--- src/filepath.c 2023-03-11 13:18:31.812031442 +0000
***************
*** 982,987 ****
--- 982,990 ----
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,1004 ****
find_what,
curbuf->b_ffname,
find_what == FINDFILE_DIR
! ? (char_u *)"" : curbuf->b_p_sua);
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);
}
if (rettv->v_type == VAR_STRING)
--- 995,1011 ----
find_what,
curbuf->b_ffname,
find_what == FINDFILE_DIR
! ? (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)
*** ../vim-9.0.1399/src/ex_docmd.c 2023-02-21 14:27:34.516360384 +0000
--- src/ex_docmd.c 2023-03-11 13:22:11.687866787 +0000
***************
*** 6767,6774 ****
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind)
{
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
! FNAME_MESS, TRUE, curbuf->b_ffname);
if (fname == NULL)
goto theend;
eap->arg = fname;
--- 6767,6779 ----
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,
! &file_to_find, &search_ctx);
! vim_free(file_to_find);
! vim_findfile_cleanup(search_ctx);
if (fname == NULL)
goto theend;
eap->arg = fname;
***************
*** 7032,7052 ****
{
char_u *fname;
int count;
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
! TRUE, curbuf->b_ffname);
if (eap->addr_count > 0)
{
! // 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);
}
}
if (fname == NULL)
return;
--- 7037,7061 ----
{
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, &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.
count = eap->line2;
while (fname != NULL && --count > 0)
{
vim_free(fname);
fname = find_file_in_path(NULL, 0, FNAME_MESS,
! FALSE, curbuf->b_ffname, &file_to_find, &search_ctx);
}
}
+ VIM_CLEAR(file_to_find);
+ vim_findfile_cleanup(search_ctx);
if (fname == NULL)
return;
***************
*** 7057,7063 ****
}
/*
! * ":open" simulation: for now just work like ":visual".
*/
static void
ex_open(exarg_T *eap)
--- 7066,7072 ----
}
/*
! * ":open" simulation: for now works just like ":visual".
*/
static void
ex_open(exarg_T *eap)
***************
*** 7138,7150 ****
// 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);
--- 7147,7152 ----
***************
*** 7153,7163 ****
--- 7155,7169 ----
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,7176 ****
main_loop(FALSE, TRUE);
pending_exmode_active = FALSE;
! RedrawingDisabled = rd;
! no_wait_return = nwr;
! msg_scroll = ms;
#ifdef FEAT_GUI
! hold_gui_events = he;
#endif
}
return;
--- 7172,7182 ----
main_loop(FALSE, TRUE);
pending_exmode_active = FALSE;
! RedrawingDisabled = save_rd;
! no_wait_return = save_nwr;
! msg_scroll = save_ms;
#ifdef FEAT_GUI
! hold_gui_events = save_he;
#endif
}
return;
*** ../vim-9.0.1399/src/misc2.c 2023-03-04 20:47:32.304617857 +0000
--- src/misc2.c 2023-03-11 13:20:09.495946931 +0000
***************
*** 2473,2481 ****
{
char_u *dir_name;
int r;
dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
! FNAME_MESS, curbuf->b_ffname);
if (dir_name == NULL)
return -1;
r = mch_chdir((char *)dir_name);
--- 2473,2485 ----
{
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, &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);
*** ../vim-9.0.1399/src/version.c 2023-03-10 18:36:47.384425094 +0000
--- src/version.c 2023-03-11 13:51:01.159809854 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1400,
/**/
--
hundred-and-one symptoms of being an internet addict:
262. Your computer has it's own phone line - but your daughter doesn't.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///