Skip to content

Commit 5145c9a

Browse files
committed
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)
1 parent 4df0772 commit 5145c9a

File tree

6 files changed

+96
-69
lines changed

6 files changed

+96
-69
lines changed

src/ex_docmd.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6767,8 +6767,13 @@ ex_splitview(exarg_T *eap)
67676767

67686768
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind)
67696769
{
6770+
char_u *file_to_find = NULL;
6771+
char *search_ctx = NULL;
67706772
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
6771-
FNAME_MESS, TRUE, curbuf->b_ffname);
6773+
FNAME_MESS, TRUE, curbuf->b_ffname,
6774+
&file_to_find, &search_ctx);
6775+
vim_free(file_to_find);
6776+
vim_findfile_cleanup(search_ctx);
67726777
if (fname == NULL)
67736778
goto theend;
67746779
eap->arg = fname;
@@ -7032,21 +7037,25 @@ ex_find(exarg_T *eap)
70327037
{
70337038
char_u *fname;
70347039
int count;
7040+
char_u *file_to_find = NULL;
7041+
char *search_ctx = NULL;
70357042

70367043
fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
7037-
TRUE, curbuf->b_ffname);
7044+
TRUE, curbuf->b_ffname, &file_to_find, &search_ctx);
70387045
if (eap->addr_count > 0)
70397046
{
7040-
// Repeat finding the file "count" times. This matters when it
7041-
// appears several times in the path.
7047+
// Repeat finding the file "count" times. This matters when it appears
7048+
// several times in the path.
70427049
count = eap->line2;
70437050
while (fname != NULL && --count > 0)
70447051
{
70457052
vim_free(fname);
70467053
fname = find_file_in_path(NULL, 0, FNAME_MESS,
7047-
FALSE, curbuf->b_ffname);
7054+
FALSE, curbuf->b_ffname, &file_to_find, &search_ctx);
70487055
}
70497056
}
7057+
VIM_CLEAR(file_to_find);
7058+
vim_findfile_cleanup(search_ctx);
70507059

70517060
if (fname == NULL)
70527061
return;
@@ -7057,7 +7066,7 @@ ex_find(exarg_T *eap)
70577066
}
70587067

70597068
/*
7060-
* ":open" simulation: for now just work like ":visual".
7069+
* ":open" simulation: for now works just like ":visual".
70617070
*/
70627071
static void
70637072
ex_open(exarg_T *eap)
@@ -7138,13 +7147,6 @@ do_exedit(
71387147
// Special case: ":global/pat/visual\NLvi-commands"
71397148
if (global_busy)
71407149
{
7141-
int rd = RedrawingDisabled;
7142-
int nwr = no_wait_return;
7143-
int ms = msg_scroll;
7144-
#ifdef FEAT_GUI
7145-
int he = hold_gui_events;
7146-
#endif
7147-
71487150
if (eap->nextcmd != NULL)
71497151
{
71507152
stuffReadbuff(eap->nextcmd);
@@ -7153,11 +7155,15 @@ do_exedit(
71537155

71547156
if (exmode_was != EXMODE_VIM)
71557157
settmode(TMODE_RAW);
7158+
int save_rd = RedrawingDisabled;
71567159
RedrawingDisabled = 0;
7160+
int save_nwr = no_wait_return;
71577161
no_wait_return = 0;
71587162
need_wait_return = FALSE;
7163+
int save_ms = msg_scroll;
71597164
msg_scroll = 0;
71607165
#ifdef FEAT_GUI
7166+
int save_he = hold_gui_events;
71617167
hold_gui_events = 0;
71627168
#endif
71637169
set_must_redraw(UPD_CLEAR);
@@ -7166,11 +7172,11 @@ do_exedit(
71667172
main_loop(FALSE, TRUE);
71677173

71687174
pending_exmode_active = FALSE;
7169-
RedrawingDisabled = rd;
7170-
no_wait_return = nwr;
7171-
msg_scroll = ms;
7175+
RedrawingDisabled = save_rd;
7176+
no_wait_return = save_nwr;
7177+
msg_scroll = save_ms;
71727178
#ifdef FEAT_GUI
7173-
hold_gui_events = he;
7179+
hold_gui_events = save_he;
71747180
#endif
71757181
}
71767182
return;

src/filepath.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,9 @@ findfilendir(
982982

983983
if (*fname != NUL && !error)
984984
{
985+
char_u *file_to_find = NULL;
986+
char *search_ctx = NULL;
987+
985988
do
986989
{
987990
if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST)
@@ -992,13 +995,17 @@ findfilendir(
992995
find_what,
993996
curbuf->b_ffname,
994997
find_what == FINDFILE_DIR
995-
? (char_u *)"" : curbuf->b_p_sua);
998+
? (char_u *)"" : curbuf->b_p_sua,
999+
&file_to_find, &search_ctx);
9961000
first = FALSE;
9971001

9981002
if (fresult != NULL && rettv->v_type == VAR_LIST)
9991003
list_append_string(rettv->vval.v_list, fresult, -1);
10001004

10011005
} while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
1006+
1007+
vim_free(file_to_find);
1008+
vim_findfile_cleanup(search_ctx);
10021009
}
10031010

10041011
if (rettv->v_type == VAR_STRING)

src/findfile.c

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,23 +1571,21 @@ find_file_in_path(
15711571
int len, // length of file name
15721572
int options,
15731573
int first, // use count'th matching file name
1574-
char_u *rel_fname) // file name searching relative to
1574+
char_u *rel_fname, // file name searching relative to
1575+
char_u **file_to_find, // in/out: modified copy of file name
1576+
char **search_ctx) // in/out: state of the search
15751577
{
15761578
return find_file_in_path_option(ptr, len, options, first,
15771579
*curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
1578-
FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
1580+
FINDFILE_BOTH, rel_fname, curbuf->b_p_sua,
1581+
file_to_find, search_ctx);
15791582
}
15801583

1581-
static char_u *ff_file_to_find = NULL;
1582-
static void *fdip_search_ctx = NULL;
1583-
15841584
# if defined(EXITFREE) || defined(PROTO)
15851585
void
15861586
free_findfile(void)
15871587
{
1588-
vim_free(ff_file_to_find);
1589-
vim_findfile_cleanup(fdip_search_ctx);
1590-
vim_free(ff_expand_buffer);
1588+
VIM_CLEAR(ff_expand_buffer);
15911589
}
15921590
# endif
15931591

@@ -1607,10 +1605,13 @@ find_directory_in_path(
16071605
char_u *ptr, // file name
16081606
int len, // length of file name
16091607
int options,
1610-
char_u *rel_fname) // file name searching relative to
1608+
char_u *rel_fname, // file name searching relative to
1609+
char_u **file_to_find, // in/out: modified copy of file name
1610+
char **search_ctx) // in/out: state of the search
16111611
{
16121612
return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
1613-
FINDFILE_DIR, rel_fname, (char_u *)"");
1613+
FINDFILE_DIR, rel_fname, (char_u *)"",
1614+
file_to_find, search_ctx);
16141615
}
16151616

16161617
char_u *
@@ -1622,8 +1623,11 @@ find_file_in_path_option(
16221623
char_u *path_option, // p_path or p_cdpath
16231624
int find_what, // FINDFILE_FILE, _DIR or _BOTH
16241625
char_u *rel_fname, // file name we are looking relative to.
1625-
char_u *suffixes) // list of suffixes, 'suffixesadd' option
1626+
char_u *suffixes, // list of suffixes, 'suffixesadd' option
1627+
char_u **file_to_find, // in/out: modified copy of file name
1628+
char **search_ctx_arg) // in/out: state of the search
16261629
{
1630+
ff_search_ctx_T **search_ctx = (ff_search_ctx_T **)search_ctx_arg;
16271631
static char_u *dir;
16281632
static int did_findfile_init = FALSE;
16291633
char_u save_char;
@@ -1649,40 +1653,40 @@ find_file_in_path_option(
16491653
expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, NULL);
16501654
ptr[len] = save_char;
16511655

1652-
vim_free(ff_file_to_find);
1653-
ff_file_to_find = vim_strsave(NameBuff);
1654-
if (ff_file_to_find == NULL) // out of memory
1656+
vim_free(*file_to_find);
1657+
*file_to_find = vim_strsave(NameBuff);
1658+
if (*file_to_find == NULL) // out of memory
16551659
{
16561660
file_name = NULL;
16571661
goto theend;
16581662
}
16591663
if (options & FNAME_UNESC)
16601664
{
16611665
// Change all "\ " to " ".
1662-
for (ptr = ff_file_to_find; *ptr != NUL; ++ptr)
1666+
for (ptr = *file_to_find; *ptr != NUL; ++ptr)
16631667
if (ptr[0] == '\\' && ptr[1] == ' ')
16641668
mch_memmove(ptr, ptr + 1, STRLEN(ptr));
16651669
}
16661670
}
16671671

1668-
rel_to_curdir = (ff_file_to_find[0] == '.'
1669-
&& (ff_file_to_find[1] == NUL
1670-
|| vim_ispathsep(ff_file_to_find[1])
1671-
|| (ff_file_to_find[1] == '.'
1672-
&& (ff_file_to_find[2] == NUL
1673-
|| vim_ispathsep(ff_file_to_find[2])))));
1674-
if (vim_isAbsName(ff_file_to_find)
1672+
rel_to_curdir = ((*file_to_find)[0] == '.'
1673+
&& ((*file_to_find)[1] == NUL
1674+
|| vim_ispathsep((*file_to_find)[1])
1675+
|| ((*file_to_find)[1] == '.'
1676+
&& ((*file_to_find)[2] == NUL
1677+
|| vim_ispathsep((*file_to_find)[2])))));
1678+
if (vim_isAbsName(*file_to_find)
16751679
// "..", "../path", "." and "./path": don't use the path_option
16761680
|| rel_to_curdir
16771681
# if defined(MSWIN)
16781682
// handle "\tmp" as absolute path
1679-
|| vim_ispathsep(ff_file_to_find[0])
1683+
|| vim_ispathsep((*file_to_find)[0])
16801684
// handle "c:name" as absolute path
1681-
|| (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
1685+
|| ((*file_to_find)[0] != NUL && (*file_to_find)[1] == ':')
16821686
# endif
16831687
# ifdef AMIGA
16841688
// handle ":tmp" as absolute path
1685-
|| ff_file_to_find[0] == ':'
1689+
|| (*file_to_find)[0] == ':'
16861690
# endif
16871691
)
16881692
{
@@ -1696,30 +1700,30 @@ find_file_in_path_option(
16961700
int l;
16971701
int run;
16981702

1699-
if (path_with_url(ff_file_to_find))
1703+
if (path_with_url(*file_to_find))
17001704
{
1701-
file_name = vim_strsave(ff_file_to_find);
1705+
file_name = vim_strsave(*file_to_find);
17021706
goto theend;
17031707
}
17041708

17051709
// When FNAME_REL flag given first use the directory of the file.
17061710
// Otherwise or when this fails use the current directory.
17071711
for (run = 1; run <= 2; ++run)
17081712
{
1709-
l = (int)STRLEN(ff_file_to_find);
1713+
l = (int)STRLEN(*file_to_find);
17101714
if (run == 1
17111715
&& rel_to_curdir
17121716
&& (options & FNAME_REL)
17131717
&& rel_fname != NULL
17141718
&& STRLEN(rel_fname) + l < MAXPATHL)
17151719
{
17161720
STRCPY(NameBuff, rel_fname);
1717-
STRCPY(gettail(NameBuff), ff_file_to_find);
1721+
STRCPY(gettail(NameBuff), *file_to_find);
17181722
l = (int)STRLEN(NameBuff);
17191723
}
17201724
else
17211725
{
1722-
STRCPY(NameBuff, ff_file_to_find);
1726+
STRCPY(NameBuff, *file_to_find);
17231727
run = 2;
17241728
}
17251729

@@ -1753,7 +1757,7 @@ find_file_in_path_option(
17531757
if (first == TRUE)
17541758
{
17551759
// vim_findfile_free_visited can handle a possible NULL pointer
1756-
vim_findfile_free_visited(fdip_search_ctx);
1760+
vim_findfile_free_visited(*search_ctx);
17571761
dir = path_option;
17581762
did_findfile_init = FALSE;
17591763
}
@@ -1762,7 +1766,7 @@ find_file_in_path_option(
17621766
{
17631767
if (did_findfile_init)
17641768
{
1765-
file_name = vim_findfile(fdip_search_ctx);
1769+
file_name = vim_findfile(*search_ctx);
17661770
if (file_name != NULL)
17671771
break;
17681772

@@ -1776,8 +1780,8 @@ find_file_in_path_option(
17761780
{
17771781
// We searched all paths of the option, now we can
17781782
// free the search context.
1779-
vim_findfile_cleanup(fdip_search_ctx);
1780-
fdip_search_ctx = NULL;
1783+
vim_findfile_cleanup(*search_ctx);
1784+
*search_ctx = NULL;
17811785
break;
17821786
}
17831787

@@ -1790,10 +1794,10 @@ find_file_in_path_option(
17901794

17911795
// get the stopdir string
17921796
r_ptr = vim_findfile_stopdir(buf);
1793-
fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
1797+
*search_ctx = vim_findfile_init(buf, *file_to_find,
17941798
r_ptr, 100, FALSE, find_what,
1795-
fdip_search_ctx, FALSE, rel_fname);
1796-
if (fdip_search_ctx != NULL)
1799+
*search_ctx, FALSE, rel_fname);
1800+
if (*search_ctx != NULL)
17971801
did_findfile_init = TRUE;
17981802
vim_free(buf);
17991803
}
@@ -1804,20 +1808,17 @@ find_file_in_path_option(
18041808
if (first == TRUE)
18051809
{
18061810
if (find_what == FINDFILE_DIR)
1807-
semsg(_(e_cant_find_directory_str_in_cdpath),
1808-
ff_file_to_find);
1811+
semsg(_(e_cant_find_directory_str_in_cdpath), *file_to_find);
18091812
else
1810-
semsg(_(e_cant_find_file_str_in_path),
1811-
ff_file_to_find);
1813+
semsg(_(e_cant_find_file_str_in_path), *file_to_find);
18121814
}
18131815
else
18141816
{
18151817
if (find_what == FINDFILE_DIR)
18161818
semsg(_(e_no_more_directory_str_found_in_cdpath),
1817-
ff_file_to_find);
1819+
*file_to_find);
18181820
else
1819-
semsg(_(e_no_more_file_str_found_in_path),
1820-
ff_file_to_find);
1821+
semsg(_(e_no_more_file_str_found_in_path), *file_to_find);
18211822
}
18221823
}
18231824

@@ -2046,8 +2047,11 @@ find_file_name_in_path(
20462047

20472048
if (options & FNAME_EXP)
20482049
{
2050+
char_u *file_to_find = NULL;
2051+
char *search_ctx = NULL;
2052+
20492053
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
2050-
TRUE, rel_fname);
2054+
TRUE, rel_fname, &file_to_find, &search_ctx);
20512055

20522056
# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
20532057
/*
@@ -2063,7 +2067,7 @@ find_file_name_in_path(
20632067
ptr = tofree;
20642068
len = (int)STRLEN(ptr);
20652069
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
2066-
TRUE, rel_fname);
2070+
TRUE, rel_fname, &file_to_find, &search_ctx);
20672071
}
20682072
}
20692073
# endif
@@ -2080,8 +2084,12 @@ find_file_name_in_path(
20802084
while (file_name != NULL && --count > 0)
20812085
{
20822086
vim_free(file_name);
2083-
file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
2087+
file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname,
2088+
&file_to_find, &search_ctx);
20842089
}
2090+
2091+
vim_free(file_to_find);
2092+
vim_findfile_cleanup(search_ctx);
20852093
}
20862094
else
20872095
file_name = vim_strnsave(ptr, len);

src/misc2.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2473,9 +2473,13 @@ vim_chdir(char_u *new_dir)
24732473
{
24742474
char_u *dir_name;
24752475
int r;
2476+
char_u *file_to_find = NULL;
2477+
char *search_ctx = NULL;
24762478

24772479
dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
2478-
FNAME_MESS, curbuf->b_ffname);
2480+
FNAME_MESS, curbuf->b_ffname, &file_to_find, &search_ctx);
2481+
vim_free(file_to_find);
2482+
vim_findfile_cleanup(search_ctx);
24792483
if (dir_name == NULL)
24802484
return -1;
24812485
r = mch_chdir((char *)dir_name);

0 commit comments

Comments
 (0)