]> granicus.if.org Git - vim/commitdiff
patch 9.0.1400: find_file_in_path() is not reentrant v9.0.1400
authorBram Moolenaar <Bram@vim.org>
Sat, 11 Mar 2023 13:55:53 +0000 (13:55 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 11 Mar 2023 13:55:53 +0000 (13:55 +0000)
Problem:    find_file_in_path() is not reentrant.
Solution:   Instead of global variables pass pointers to the functions.
            (closes #12093)

src/ex_docmd.c
src/filepath.c
src/findfile.c
src/misc2.c
src/proto/findfile.pro
src/version.c

index 2c65bd8e59f9e41e211691b6717041334c243f08..f945b3805abb76b9da0e1820b5fdef730146f269 100644 (file)
@@ -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;
index c448edb0495fe65bfd2491ef4932039f412e32b4..57e9fb29571aaadf4f4a7c18a607dfa1bfc6fbea 100644 (file)
@@ -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)
index e0d9d6638252076db67292c83e978401122d5d4b..7287b10d73a3aef16d16235cffa9908e8448c3c6 100644 (file)
@@ -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);
index e793987aa2f3121e22c6b7f68da707b7d0b3b187..458e62b267ea41dc9560051cace40a6a59ecaa1a 100644 (file)
@@ -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);
index bffc1242ad7e8666ef2ad298c06cf6d0052c13ff..95601011aca608b875fd916ceea14725238ffd72 100644 (file)
@@ -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);
index 56f6cb4c9c1f72231740f789b5830c3d993135cf..b1d88f4851882cd45c924906650c2296e1e15b67 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1400,
 /**/
     1399,
 /**/