To: vim_dev@googlegroups.com Subject: Patch 9.0.1400 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@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 ///