patch 9.1.1122: too many strlen() calls in findfile.c Commit: https://github.com/vim/vim/commit/d6e3c9048dfb7e8f08f8fadc820c7e2208c3f030 Author: John Marriott <basil...@internode.on.net> Date: Tue Feb 18 20:45:48 2025 +0100
patch 9.1.1122: too many strlen() calls in findfile.c Problem: too many strlen() calls in findfile.c Solution: refactor findfile.c and remove calls to strlen() (John Marriott) closes: #16595 Signed-off-by: John Marriott <basil...@internode.on.net> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/findfile.c b/src/findfile.c index b6ee0920f..ccb3ef885 100644 --- a/src/findfile.c +++ b/src/findfile.c @@ -66,8 +66,8 @@ typedef struct ff_stack // the fix part (no wildcards) and the part containing the wildcards // of the search path - char_u *ffs_fix_path; - char_u *ffs_wc_path; + string_T ffs_fix_path; + string_T ffs_wc_path; // files/dirs found in the above directory, matched by the first wildcard // of wc_part @@ -167,31 +167,31 @@ typedef struct ff_search_ctx_T ff_visited_list_hdr_T *ffsc_dir_visited_list; ff_visited_list_hdr_T *ffsc_visited_lists_list; ff_visited_list_hdr_T *ffsc_dir_visited_lists_list; - char_u *ffsc_file_to_search; - char_u *ffsc_start_dir; - char_u *ffsc_fix_path; - char_u *ffsc_wc_path; + string_T ffsc_file_to_search; + string_T ffsc_start_dir; + string_T ffsc_fix_path; + string_T ffsc_wc_path; int ffsc_level; - char_u **ffsc_stopdirs_v; + string_T *ffsc_stopdirs_v; int ffsc_find_what; int ffsc_tagfile; } ff_search_ctx_T; // locally needed functions -static int ff_check_visited(ff_visited_T **, char_u *, char_u *); +static int ff_check_visited(ff_visited_T **, char_u *, size_t, char_u *, size_t); static void vim_findfile_free_visited(void *search_ctx_arg); static void vim_findfile_free_visited_list(ff_visited_list_hdr_T **list_headp); static void ff_free_visited_list(ff_visited_T *vl); -static ff_visited_list_hdr_T* ff_get_visited_list(char_u *, ff_visited_list_hdr_T **list_headp); +static ff_visited_list_hdr_T* ff_get_visited_list(char_u *, size_t, ff_visited_list_hdr_T **list_headp); static void ff_push(ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr); static ff_stack_T *ff_pop(ff_search_ctx_T *search_ctx); static void ff_clear(ff_search_ctx_T *search_ctx); static void ff_free_stack_element(ff_stack_T *stack_ptr); -static ff_stack_T *ff_create_stack_element(char_u *, char_u *, int, int); -static int ff_path_in_stoplist(char_u *, int, char_u **); +static ff_stack_T *ff_create_stack_element(char_u *, size_t, char_u *, size_t, int, int); +static int ff_path_in_stoplist(char_u *, int, string_T *); -static char_u *ff_expand_buffer = NULL; // used for expanding filenames +static string_T ff_expand_buffer = {NULL, 0}; // used for expanding filenames #if 0 /* @@ -283,6 +283,7 @@ vim_findnext(void) vim_findfile_init( char_u *path, char_u *filename, + size_t filenamelen, char_u *stopdirs UNUSED, int level, int free_visited, @@ -294,6 +295,7 @@ vim_findfile_init( char_u *wc_part; ff_stack_T *sptr; ff_search_ctx_T *search_ctx; + int add_sep; // If a search context is given by the caller, reuse it, else allocate a // new one. @@ -320,19 +322,20 @@ vim_findfile_init( // filename. If no list for the current filename exists, creates a new // one. search_ctx->ffsc_visited_list = ff_get_visited_list(filename, - &search_ctx->ffsc_visited_lists_list); + filenamelen, &search_ctx->ffsc_visited_lists_list); if (search_ctx->ffsc_visited_list == NULL) goto error_return; search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename, - &search_ctx->ffsc_dir_visited_lists_list); + filenamelen, &search_ctx->ffsc_dir_visited_lists_list); if (search_ctx->ffsc_dir_visited_list == NULL) goto error_return; } - if (ff_expand_buffer == NULL) + if (ff_expand_buffer.string == NULL) { - ff_expand_buffer = alloc(MAXPATHL); - if (ff_expand_buffer == NULL) + ff_expand_buffer.length = 0; + ff_expand_buffer.string = alloc(MAXPATHL); + if (ff_expand_buffer.string == NULL) goto error_return; } @@ -348,13 +351,23 @@ vim_findfile_init( if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) { // Make the start dir an absolute path name. - vim_strncpy(ff_expand_buffer, rel_fname, len); - search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE); + vim_strncpy(ff_expand_buffer.string, rel_fname, len); + ff_expand_buffer.length = len; + + search_ctx->ffsc_start_dir.string = FullName_save(ff_expand_buffer.string, FALSE); + if (search_ctx->ffsc_start_dir.string == NULL) + goto error_return; + search_ctx->ffsc_start_dir.length = STRLEN(search_ctx->ffsc_start_dir.string); } else - search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len); - if (search_ctx->ffsc_start_dir == NULL) - goto error_return; + { + search_ctx->ffsc_start_dir.length = len; + search_ctx->ffsc_start_dir.string = vim_strnsave(rel_fname, + search_ctx->ffsc_start_dir.length); + if (search_ctx->ffsc_start_dir.string == NULL) + goto error_return; + } + if (*++path != NUL) ++path; } @@ -369,17 +382,21 @@ vim_findfile_init( drive[0] = path[0]; drive[1] = ':'; drive[2] = NUL; - if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) + if (vim_FullName(drive, ff_expand_buffer.string, MAXPATHL, TRUE) == FAIL) goto error_return; path += 2; } else #endif - if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL) + if (mch_dirname(ff_expand_buffer.string, MAXPATHL) == FAIL) goto error_return; - search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer); - if (search_ctx->ffsc_start_dir == NULL) + ff_expand_buffer.length = STRLEN(ff_expand_buffer.string); + + search_ctx->ffsc_start_dir.length = ff_expand_buffer.length; + search_ctx->ffsc_start_dir.string = vim_strnsave(ff_expand_buffer.string, + search_ctx->ffsc_start_dir.length); + if (search_ctx->ffsc_start_dir.string == NULL) goto error_return; #ifdef BACKSLASH_IN_FILENAME @@ -387,8 +404,11 @@ vim_findfile_init( // directory (but not for "//machine/dir"). Only use the drive name. if ((*path == '/' || *path == '\') && path[1] != path[0] - && search_ctx->ffsc_start_dir[1] == ':') - search_ctx->ffsc_start_dir[2] = NUL; + && search_ctx->ffsc_start_dir.string[1] == ':') + { + search_ctx->ffsc_start_dir.string[2] = NUL; + search_ctx->ffsc_start_dir.length = 2; + } #endif } @@ -410,10 +430,12 @@ vim_findfile_init( walker++; dircount = 1; - search_ctx->ffsc_stopdirs_v = ALLOC_ONE(char_u *); + search_ctx->ffsc_stopdirs_v = ALLOC_ONE(string_T); if (search_ctx->ffsc_stopdirs_v != NULL) { + string_T *tmp; // for convenience + do { char_u *helper; @@ -422,7 +444,7 @@ vim_findfile_init( helper = walker; ptr = vim_realloc(search_ctx->ffsc_stopdirs_v, - (dircount + 1) * sizeof(char_u *)); + (dircount + 1) * sizeof(string_T)); if (ptr) search_ctx->ffsc_stopdirs_v = ptr; else @@ -431,23 +453,36 @@ vim_findfile_init( walker = vim_strchr(walker, ';'); len = walker ? (size_t)(walker - helper) : STRLEN(helper); // "" means ascent till top of directory tree. + if (*helper != NUL && !vim_isAbsName(helper) && len + 1 < MAXPATHL) { // Make the stop dir an absolute path name. - vim_strncpy(ff_expand_buffer, helper, len); - search_ctx->ffsc_stopdirs_v[dircount-1] = - FullName_save(ff_expand_buffer, FALSE); + vim_strncpy(ff_expand_buffer.string, helper, len); + ff_expand_buffer.length = len; + + tmp = &search_ctx->ffsc_stopdirs_v[dircount - 1]; + tmp->string = FullName_save(ff_expand_buffer.string, FALSE); + if (tmp->string != NULL) + tmp->length = STRLEN(tmp->string); } else - search_ctx->ffsc_stopdirs_v[dircount-1] = - vim_strnsave(helper, len); + { + tmp = &search_ctx->ffsc_stopdirs_v[dircount - 1]; + tmp->length = len; + tmp->string = vim_strnsave(helper, tmp->length); + if (tmp->string == NULL) + tmp->length = 0; + } if (walker) walker++; dircount++; } while (walker != NULL); - search_ctx->ffsc_stopdirs_v[dircount-1] = NULL; + + tmp = &search_ctx->ffsc_stopdirs_v[dircount - 1]; + tmp->string = NULL; + tmp->length = 0; } } @@ -462,11 +497,14 @@ vim_findfile_init( if (wc_part != NULL) { int llevel; - int len; char *errpt; // save the fix part of the path - search_ctx->ffsc_fix_path = vim_strnsave(path, wc_part - path); + search_ctx->ffsc_fix_path.length = (size_t)(wc_part - path); + search_ctx->ffsc_fix_path.string = vim_strnsave(path, + search_ctx->ffsc_fix_path.length); + if (search_ctx->ffsc_fix_path.string == NULL) + goto error_return; /* * copy wc_path and add restricts to the '**' wildcard. @@ -477,27 +515,27 @@ vim_findfile_init( * Due to this technique the path looks awful if you print it as a * string. */ - len = 0; + ff_expand_buffer.length = 0; while (*wc_part != NUL) { - if (len + 5 >= MAXPATHL) + if (ff_expand_buffer.length + 5 >= MAXPATHL) { emsg(_(e_path_too_long_for_completion)); break; } if (STRNCMP(wc_part, "**", 2) == 0) { - ff_expand_buffer[len++] = *wc_part++; - ff_expand_buffer[len++] = *wc_part++; + ff_expand_buffer.string[ff_expand_buffer.length++] = *wc_part++; + ff_expand_buffer.string[ff_expand_buffer.length++] = *wc_part++; llevel = strtol((char *)wc_part, &errpt, 10); if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255) - ff_expand_buffer[len++] = llevel; + ff_expand_buffer.string[ff_expand_buffer.length++] = llevel; else if ((char_u *)errpt != wc_part && llevel == 0) // restrict is 0 -> remove already added '**' - len -= 2; + ff_expand_buffer.length -= 2; else - ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND; + ff_expand_buffer.string[ff_expand_buffer.length++] = FF_MAX_STAR_STAR_EXPAND; wc_part = (char_u *)errpt; if (*wc_part != NUL && !vim_ispathsep(*wc_part)) { @@ -506,107 +544,153 @@ vim_findfile_init( } } else - ff_expand_buffer[len++] = *wc_part++; + ff_expand_buffer.string[ff_expand_buffer.length++] = *wc_part++; } - ff_expand_buffer[len] = NUL; - search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer); + ff_expand_buffer.string[ff_expand_buffer.length] = NUL; - if (search_ctx->ffsc_wc_path == NULL) + search_ctx->ffsc_wc_path.length = ff_expand_buffer.length; + search_ctx->ffsc_wc_path.string = vim_strnsave(ff_expand_buffer.string, + search_ctx->ffsc_wc_path.length); + if (search_ctx->ffsc_wc_path.string == NULL) goto error_return; } else - search_ctx->ffsc_fix_path = vim_strsave(path); + { + search_ctx->ffsc_fix_path.length = STRLEN(path); + search_ctx->ffsc_fix_path.string = vim_strnsave(path, + search_ctx->ffsc_fix_path.length); + if (search_ctx->ffsc_fix_path.string == NULL) + goto error_return; + } - if (search_ctx->ffsc_start_dir == NULL) + if (search_ctx->ffsc_start_dir.string == NULL) { // store the fix part as startdir. // This is needed if the parameter path is fully qualified. - search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path); - if (search_ctx->ffsc_start_dir == NULL) + search_ctx->ffsc_start_dir.length = search_ctx->ffsc_fix_path.length; + search_ctx->ffsc_start_dir.string = vim_strnsave(search_ctx->ffsc_fix_path.string, + search_ctx->ffsc_start_dir.length); + if (search_ctx->ffsc_start_dir.string == NULL) goto error_return; - search_ctx->ffsc_fix_path[0] = NUL; + search_ctx->ffsc_fix_path.string[0] = NUL; + search_ctx->ffsc_fix_path.length = 0; } // create an absolute path - if (STRLEN(search_ctx->ffsc_start_dir) - + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) + if (search_ctx->ffsc_start_dir.length + + search_ctx->ffsc_fix_path.length + 3 >= MAXPATHL) { emsg(_(e_path_too_long_for_completion)); goto error_return; } - STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); - add_pathsep(ff_expand_buffer); + + add_sep = !after_pathsep(search_ctx->ffsc_start_dir.string, + search_ctx->ffsc_start_dir.string + search_ctx->ffsc_start_dir.length); + ff_expand_buffer.length = vim_snprintf( + (char *)ff_expand_buffer.string, + MAXPATHL, + "%s%s", + search_ctx->ffsc_start_dir.string, + add_sep ? PATHSEPSTR : ""); + { - int eb_len = (int)STRLEN(ff_expand_buffer); - char_u *buf = alloc(eb_len - + (int)STRLEN(search_ctx->ffsc_fix_path) + 1); + size_t bufsize = ff_expand_buffer.length + search_ctx->ffsc_fix_path.length + 1; + char_u *buf = alloc(bufsize); - STRCPY(buf, ff_expand_buffer); - STRCPY(buf + eb_len, search_ctx->ffsc_fix_path); + if (buf == NULL) + goto error_return; + + vim_snprintf( + (char *)buf, + bufsize, + "%s%s", + ff_expand_buffer.string, + search_ctx->ffsc_fix_path.string); if (mch_isdir(buf)) { - STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path); - add_pathsep(ff_expand_buffer); + if (search_ctx->ffsc_fix_path.length > 0) + { + add_sep = !after_pathsep(search_ctx->ffsc_fix_path.string, + search_ctx->ffsc_fix_path.string + search_ctx->ffsc_fix_path.length); + ff_expand_buffer.length += vim_snprintf( + (char *)ff_expand_buffer.string + ff_expand_buffer.length, + MAXPATHL - ff_expand_buffer.length, + "%s%s", + search_ctx->ffsc_fix_path.string, + add_sep ? PATHSEPSTR : ""); + } } else { - char_u *p = gettail(search_ctx->ffsc_fix_path); - char_u *wc_path = NULL; - char_u *temp = NULL; - int len = 0; + char_u *p = gettail(search_ctx->ffsc_fix_path.string); + int len = (int)search_ctx->ffsc_fix_path.length; - if (p > search_ctx->ffsc_fix_path) + if (p > search_ctx->ffsc_fix_path.string) { // do not add '..' to the path and start upwards searching - len = (int)(p - search_ctx->ffsc_fix_path) - 1; + len = (int)(p - search_ctx->ffsc_fix_path.string) - 1; if ((len >= 2 - && STRNCMP(search_ctx->ffsc_fix_path, "..", 2) == 0) - && (len == 2 - || search_ctx->ffsc_fix_path[2] == PATHSEP)) + && STRNCMP(search_ctx->ffsc_fix_path.string, "..", 2) == 0) + && (len == 2 || search_ctx->ffsc_fix_path.string[2] == PATHSEP)) { vim_free(buf); goto error_return; } - STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len); - add_pathsep(ff_expand_buffer); + + add_sep = !after_pathsep(search_ctx->ffsc_fix_path.string, + search_ctx->ffsc_fix_path.string + search_ctx->ffsc_fix_path.length); + ff_expand_buffer.length += vim_snprintf( + (char *)ff_expand_buffer.string + ff_expand_buffer.length, + MAXPATHL - ff_expand_buffer.length, + "%.*s%s", + len, + search_ctx->ffsc_fix_path.string, + add_sep ? PATHSEPSTR : ""); } - else - len = (int)STRLEN(search_ctx->ffsc_fix_path); - if (search_ctx->ffsc_wc_path != NULL) + if (search_ctx->ffsc_wc_path.string != NULL) { - wc_path = vim_strsave(search_ctx->ffsc_wc_path); - temp = alloc(STRLEN(search_ctx->ffsc_wc_path) - + STRLEN(search_ctx->ffsc_fix_path + len) - + 1); - if (temp == NULL || wc_path == NULL) + size_t tempsize = (search_ctx->ffsc_fix_path.length - len) + + search_ctx->ffsc_wc_path.length + + 1; + char_u *temp = alloc(tempsize); + + if (temp == NULL) { vim_free(buf); vim_free(temp); - vim_free(wc_path); goto error_return; } - STRCPY(temp, search_ctx->ffsc_fix_path + len); - STRCAT(temp, search_ctx->ffsc_wc_path); - vim_free(search_ctx->ffsc_wc_path); - vim_free(wc_path); - search_ctx->ffsc_wc_path = temp; + search_ctx->ffsc_wc_path.length = vim_snprintf( + (char *)temp, + tempsize, + "%s%s", + search_ctx->ffsc_fix_path.string + len, + search_ctx->ffsc_wc_path.string); + vim_free(search_ctx->ffsc_wc_path.string); + search_ctx->ffsc_wc_path.string = temp; } } vim_free(buf); } - sptr = ff_create_stack_element(ff_expand_buffer, - search_ctx->ffsc_wc_path, level, 0); + sptr = ff_create_stack_element(ff_expand_buffer.string, + ff_expand_buffer.length, + search_ctx->ffsc_wc_path.string, + search_ctx->ffsc_wc_path.length, + level, + 0); if (sptr == NULL) goto error_return; ff_push(search_ctx, sptr); - search_ctx->ffsc_file_to_search = vim_strsave(filename); - if (search_ctx->ffsc_file_to_search == NULL) + search_ctx->ffsc_file_to_search.length = filenamelen; + search_ctx->ffsc_file_to_search.string = vim_strnsave(filename, + search_ctx->ffsc_file_to_search.length); + if (search_ctx->ffsc_file_to_search.string == NULL) goto error_return; return search_ctx; @@ -628,6 +712,7 @@ error_return: vim_findfile_stopdir(char_u *buf) { char_u *r_ptr = buf; + char_u *r_ptr_end = NULL; // points to NUL at end of string "r_ptr" while (*r_ptr != NUL && *r_ptr != ';') { @@ -635,14 +720,18 @@ vim_findfile_stopdir(char_u *buf) { // Overwrite the escape char, // use STRLEN(r_ptr) to move the trailing ' - STRMOVE(r_ptr, r_ptr + 1); + if (r_ptr_end == NULL) + r_ptr_end = r_ptr + STRLEN(r_ptr); + mch_memmove(r_ptr, r_ptr + 1, + (size_t)(r_ptr_end - (r_ptr + 1)) + 1); // +1 for NUL r_ptr++; + --r_ptr_end; } r_ptr++; } if (*r_ptr == ';') { - *r_ptr = 0; + *r_ptr = NUL; r_ptr++; } else if (*r_ptr == NUL) @@ -679,14 +768,10 @@ vim_findfile_cleanup(void *ctx) char_u * vim_findfile(void *search_ctx_arg) { - char_u *file_path; - char_u *rest_of_wildcards; + string_T file_path; + string_T rest_of_wildcards; char_u *path_end = NULL; ff_stack_T *stackp; - int len; - int i; - char_u *p; - char_u *suf; ff_search_ctx_T *search_ctx; if (search_ctx_arg == NULL) @@ -698,13 +783,13 @@ vim_findfile(void *search_ctx_arg) * filepath is used as buffer for various actions and as the storage to * return a found filename. */ - if ((file_path = alloc(MAXPATHL)) == NULL) + if ((file_path.string = alloc(MAXPATHL)) == NULL) return NULL; // store the end of the start dir -- needed for upward search - if (search_ctx->ffsc_start_dir != NULL) - path_end = &search_ctx->ffsc_start_dir[ - STRLEN(search_ctx->ffsc_start_dir)]; + if (search_ctx->ffsc_start_dir.string != NULL) + path_end = &search_ctx->ffsc_start_dir.string[ + search_ctx->ffsc_start_dir.length]; // upward search loop for (;;) @@ -744,14 +829,17 @@ vim_findfile(void *search_ctx_arg) if (stackp->ffs_filearray == NULL && ff_check_visited(&search_ctx->ffsc_dir_visited_list ->ffvl_visited_list, - stackp->ffs_fix_path, stackp->ffs_wc_path) == FAIL) + stackp->ffs_fix_path.string, + stackp->ffs_fix_path.length, + stackp->ffs_wc_path.string, + stackp->ffs_wc_path.length) == FAIL) { #ifdef FF_VERBOSE if (p_verbose >= 5) { verbose_enter_scroll(); smsg("Already Searched: %s (%s)", - stackp->ffs_fix_path, stackp->ffs_wc_path); + stackp->ffs_fix_path.string, stackp->ffs_wc_path.string); // don't overwrite this either msg_puts(" "); verbose_leave_scroll(); @@ -765,7 +853,7 @@ vim_findfile(void *search_ctx_arg) { verbose_enter_scroll(); smsg("Searching: %s (%s)", - stackp->ffs_fix_path, stackp->ffs_wc_path); + stackp->ffs_fix_path.string, stackp->ffs_wc_path.string); // don't overwrite this either msg_puts(" "); verbose_leave_scroll(); @@ -779,7 +867,8 @@ vim_findfile(void *search_ctx_arg) continue; } - file_path[0] = NUL; + file_path.string[0] = NUL; + file_path.length = 0; /* * If no filearray till now expand wildcards @@ -793,17 +882,23 @@ vim_findfile(void *search_ctx_arg) // we use filepath to build the path expand_wildcards() should // expand. - dirptrs[0] = file_path; + dirptrs[0] = file_path.string; dirptrs[1] = NULL; // if we have a start dir copy it in - if (!vim_isAbsName(stackp->ffs_fix_path) - && search_ctx->ffsc_start_dir) + if (!vim_isAbsName(stackp->ffs_fix_path.string) + && search_ctx->ffsc_start_dir.string) { - if (STRLEN(search_ctx->ffsc_start_dir) + 1 < MAXPATHL) + if (search_ctx->ffsc_start_dir.length + 1 < MAXPATHL) { - STRCPY(file_path, search_ctx->ffsc_start_dir); - add_pathsep(file_path); + int add_sep = !after_pathsep(search_ctx->ffsc_start_dir.string, + search_ctx->ffsc_start_dir.string + search_ctx->ffsc_start_dir.length); + file_path.length = vim_snprintf( + (char *)file_path.string, + MAXPATHL, + "%s%s", + search_ctx->ffsc_start_dir.string, + add_sep ? PATHSEPSTR : ""); } else { @@ -813,11 +908,16 @@ vim_findfile(void *search_ctx_arg) } // append the fix part of the search path - if (STRLEN(file_path) + STRLEN(stackp->ffs_fix_path) + 1 - < MAXPATHL) + if (file_path.length + stackp->ffs_fix_path.length + 1 < MAXPATHL) { - STRCAT(file_path, stackp->ffs_fix_path); - add_pathsep(file_path); + int add_sep = !after_pathsep(stackp->ffs_fix_path.string, + stackp->ffs_fix_path.string + stackp->ffs_fix_path.length); + file_path.length += vim_snprintf( + (char *)file_path.string + file_path.length, + MAXPATHL - file_path.length, + "%s%s", + stackp->ffs_fix_path.string, + add_sep ? PATHSEPSTR : ""); } else { @@ -825,21 +925,23 @@ vim_findfile(void *search_ctx_arg) goto fail; } - rest_of_wildcards = stackp->ffs_wc_path; - if (*rest_of_wildcards != NUL) + rest_of_wildcards.string = stackp->ffs_wc_path.string; + rest_of_wildcards.length = stackp->ffs_wc_path.length; + if (*rest_of_wildcards.string != NUL) { - len = (int)STRLEN(file_path); - if (STRNCMP(rest_of_wildcards, "**", 2) == 0) + if (STRNCMP(rest_of_wildcards.string, "**", 2) == 0) { + char_u *p; + // pointer to the restrict byte // The restrict byte is not a character! - p = rest_of_wildcards + 2; + p = rest_of_wildcards.string + 2; if (*p > 0) { (*p)--; - if (len + 1 < MAXPATHL) - file_path[len++] = '*'; + if (file_path.length + 1 < MAXPATHL) + file_path.string[file_path.length++] = '*'; else { ff_free_stack_element(stackp); @@ -850,16 +952,23 @@ vim_findfile(void *search_ctx_arg) if (*p == 0) { // remove '**<numb> from wildcards - STRMOVE(rest_of_wildcards, rest_of_wildcards + 3); + mch_memmove(rest_of_wildcards.string, + rest_of_wildcards.string + 3, + (size_t)(rest_of_wildcards.length - 3) + 1); // +1 for NUL + rest_of_wildcards.length -= 3; + stackp->ffs_wc_path.length = rest_of_wildcards.length; } else - rest_of_wildcards += 3; + { + rest_of_wildcards.string += 3; + rest_of_wildcards.length -= 3; + } if (stackp->ffs_star_star_empty == 0) { // if not done before, expand '**' to empty stackp->ffs_star_star_empty = 1; - dirptrs[1] = stackp->ffs_fix_path; + dirptrs[1] = stackp->ffs_fix_path.string; } } @@ -870,19 +979,27 @@ vim_findfile(void *search_ctx_arg) * pushing every directory returned from expand_wildcards() * on the stack again for further search. */ - while (*rest_of_wildcards - && !vim_ispathsep(*rest_of_wildcards)) - if (len + 1 < MAXPATHL) - file_path[len++] = *rest_of_wildcards++; + while (*rest_of_wildcards.string + && !vim_ispathsep(*rest_of_wildcards.string)) + { + if (file_path.length + 1 < MAXPATHL) + { + file_path.string[file_path.length++] = *rest_of_wildcards.string++; + --rest_of_wildcards.length; + } else { ff_free_stack_element(stackp); goto fail; } + } - file_path[len] = NUL; - if (vim_ispathsep(*rest_of_wildcards)) - rest_of_wildcards++; + file_path.string[file_path.length] = NUL; + if (vim_ispathsep(*rest_of_wildcards.string)) + { + rest_of_wildcards.string++; + rest_of_wildcards.length--; + } } /* @@ -894,7 +1011,7 @@ vim_findfile(void *search_ctx_arg) stackp->ffs_filearray = ALLOC_ONE(char_u *); if (stackp->ffs_filearray != NULL && (stackp->ffs_filearray[0] - = vim_strsave(dirptrs[0])) != NULL) + = vim_strnsave(dirptrs[0], file_path.length)) != NULL) stackp->ffs_filearray_size = 1; else stackp->ffs_filearray_size = 0; @@ -912,14 +1029,22 @@ vim_findfile(void *search_ctx_arg) stackp->ffs_stage = 0; } else - rest_of_wildcards = &stackp->ffs_wc_path[ - STRLEN(stackp->ffs_wc_path)]; + { + rest_of_wildcards.string = &stackp->ffs_wc_path.string[ + stackp->ffs_wc_path.length]; + rest_of_wildcards.length = 0; + } if (stackp->ffs_stage == 0) { + int i; + // this is the first time we work on this directory - if (*rest_of_wildcards == NUL) + if (*rest_of_wildcards.string == NUL) { + size_t len; + char_u *suf; + /* * We don't have further wildcards to expand, so we have to * check for the final file now. @@ -933,13 +1058,19 @@ vim_findfile(void *search_ctx_arg) // prepare the filename to be checked for existence // below - if (STRLEN(stackp->ffs_filearray[i]) + 1 - + STRLEN(search_ctx->ffsc_file_to_search) - < MAXPATHL) + len = STRLEN(stackp->ffs_filearray[i]); + if (len + 1 + search_ctx->ffsc_file_to_search.length + < MAXPATHL) { - STRCPY(file_path, stackp->ffs_filearray[i]); - add_pathsep(file_path); - STRCAT(file_path, search_ctx->ffsc_file_to_search); + int add_sep = !after_pathsep(stackp->ffs_filearray[i], + stackp->ffs_filearray[i] + len); + file_path.length = vim_snprintf( + (char *)file_path.string, + MAXPATHL, + "%s%s%s", + stackp->ffs_filearray[i], + add_sep ? PATHSEPSTR : "", + search_ctx->ffsc_file_to_search.string); } else { @@ -951,7 +1082,6 @@ vim_findfile(void *search_ctx_arg) * Try without extra suffix and then with suffixes * from 'suffixesadd'. */ - len = (int)STRLEN(file_path); if (search_ctx->ffsc_tagfile) suf = (char_u *)""; else @@ -959,18 +1089,20 @@ vim_findfile(void *search_ctx_arg) for (;;) { // if file exists and we didn't already find it - if ((path_with_url(file_path) - || (mch_getperm(file_path) >= 0 + if ((path_with_url(file_path.string) + || (mch_getperm(file_path.string) >= 0 && (search_ctx->ffsc_find_what == FINDFILE_BOTH || ((search_ctx->ffsc_find_what == FINDFILE_DIR) - == mch_isdir(file_path))))) + == mch_isdir(file_path.string))))) #ifndef FF_VERBOSE && (ff_check_visited( &search_ctx->ffsc_visited_list ->ffvl_visited_list, - file_path, (char_u *)"") == OK) + file_path.string, + file_path.length, + (char_u *)"", 0) == OK) #endif ) { @@ -978,13 +1110,14 @@ vim_findfile(void *search_ctx_arg) if (ff_check_visited( &search_ctx->ffsc_visited_list ->ffvl_visited_list, - file_path, (char_u *)"") == FAIL) + file_path.string, + file_path.length, + (char_u *)"", 0) == FAIL) { if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("Already: %s", - file_path); + smsg("Already: %s", file_path.string); // don't overwrite this either msg_puts(" "); verbose_leave_scroll(); @@ -997,34 +1130,42 @@ vim_findfile(void *search_ctx_arg) stackp->ffs_filearray_cur = i + 1; ff_push(search_ctx, stackp); - if (!path_with_url(file_path)) - simplify_filename(file_path); - if (mch_dirname(ff_expand_buffer, MAXPATHL) + if (!path_with_url(file_path.string)) + file_path.length = simplify_filename(file_path.string); + + if (mch_dirname(ff_expand_buffer.string, MAXPATHL) == OK) { - p = shorten_fname(file_path, - ff_expand_buffer); + char_u *p; + + ff_expand_buffer.length = STRLEN(ff_expand_buffer.string); + p = shorten_fname(file_path.string, + ff_expand_buffer.string); if (p != NULL) - STRMOVE(file_path, p); + { + mch_memmove(file_path.string, p, + (size_t)((file_path.string + file_path.length) - p) + 1); // +1 for NUL + file_path.length -= (p - file_path.string); + } } #ifdef FF_VERBOSE if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("HIT: %s", file_path); + smsg("HIT: %s", file_path.string); // don't overwrite this either msg_puts(" "); verbose_leave_scroll(); } #endif - return file_path; + return file_path.string; } // Not found or found already, try next suffix. if (*suf == NUL) break; - copy_option_part(&suf, file_path + len, - MAXPATHL - len, ","); + file_path.length += copy_option_part(&suf, file_path.string + file_path.length, + MAXPATHL - file_path.length, ","); } } } @@ -1043,7 +1184,9 @@ vim_findfile(void *search_ctx_arg) ff_push(search_ctx, ff_create_stack_element( stackp->ffs_filearray[i], - rest_of_wildcards, + STRLEN(stackp->ffs_filearray[i]), + rest_of_wildcards.string, + rest_of_wildcards.length, stackp->ffs_level - 1, 0)); } } @@ -1055,68 +1198,83 @@ vim_findfile(void *search_ctx_arg) * if wildcards contains '**' we have to descent till we reach the * leaves of the directory tree. */ - if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) + if (STRNCMP(stackp->ffs_wc_path.string, "**", 2) == 0) { + int i; + for (i = stackp->ffs_filearray_cur; i < stackp->ffs_filearray_size; ++i) { if (fnamecmp(stackp->ffs_filearray[i], - stackp->ffs_fix_path) == 0) + stackp->ffs_fix_path.string) == 0) continue; // don't repush same directory if (!mch_isdir(stackp->ffs_filearray[i])) continue; // not a directory ff_push(search_ctx, - ff_create_stack_element(stackp->ffs_filearray[i], - stackp->ffs_wc_path, stackp->ffs_level - 1, 1)); + ff_create_stack_element( + stackp->ffs_filearray[i], + STRLEN(stackp->ffs_filearray[i]), + stackp->ffs_wc_path.string, + stackp->ffs_wc_path.length, + stackp->ffs_level - 1, 1)); } } // we are done with the current directory ff_free_stack_element(stackp); - } // If we reached this, we didn't find anything downwards. // Let's check if we should do an upward search. - if (search_ctx->ffsc_start_dir + if (search_ctx->ffsc_start_dir.string && search_ctx->ffsc_stopdirs_v != NULL && !got_int) { ff_stack_T *sptr; // path_end may point to the NUL or the previous path separator - int plen = (path_end - search_ctx->ffsc_start_dir) + int plen = (path_end - search_ctx->ffsc_start_dir.string) + (*path_end != NUL); // is the last starting directory in the stop list? - if (ff_path_in_stoplist(search_ctx->ffsc_start_dir, + if (ff_path_in_stoplist(search_ctx->ffsc_start_dir.string, plen, search_ctx->ffsc_stopdirs_v) == TRUE) break; // cut of last dir - while (path_end > search_ctx->ffsc_start_dir + while (path_end > search_ctx->ffsc_start_dir.string && vim_ispathsep(*path_end)) path_end--; - while (path_end > search_ctx->ffsc_start_dir + while (path_end > search_ctx->ffsc_start_dir.string && !vim_ispathsep(path_end[-1])) path_end--; - *path_end = 0; + *path_end = NUL; + + // we may have shortened search_ctx->ffsc_start_dir, so update it's length + search_ctx->ffsc_start_dir.length = (size_t)(path_end - search_ctx->ffsc_start_dir.string); path_end--; - if (*search_ctx->ffsc_start_dir == 0) + if (*search_ctx->ffsc_start_dir.string == NUL) break; - if (STRLEN(search_ctx->ffsc_start_dir) + 1 - + STRLEN(search_ctx->ffsc_fix_path) < MAXPATHL) + if (search_ctx->ffsc_start_dir.length + 1 + + search_ctx->ffsc_fix_path.length < MAXPATHL) { - STRCPY(file_path, search_ctx->ffsc_start_dir); - add_pathsep(file_path); - STRCAT(file_path, search_ctx->ffsc_fix_path); + int add_sep = !after_pathsep(search_ctx->ffsc_start_dir.string, + search_ctx->ffsc_start_dir.string + search_ctx->ffsc_start_dir.length); + file_path.length = vim_snprintf( + (char *)file_path.string, + MAXPATHL, + "%s%s%s", + search_ctx->ffsc_start_dir.string, + add_sep ? PATHSEPSTR : "", + search_ctx->ffsc_fix_path.string); } else goto fail; // create a new stack entry - sptr = ff_create_stack_element(file_path, - search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0); + sptr = ff_create_stack_element(file_path.string, file_path.length, + search_ctx->ffsc_wc_path.string, search_ctx->ffsc_wc_path.length, + search_ctx->ffsc_level, 0); if (sptr == NULL) break; ff_push(search_ctx, sptr); @@ -1126,7 +1284,7 @@ vim_findfile(void *search_ctx_arg) } fail: - vim_free(file_path); + vim_free(file_path.string); return NULL; } @@ -1186,6 +1344,7 @@ ff_free_visited_list(ff_visited_T *vl) static ff_visited_list_hdr_T* ff_get_visited_list( char_u *filename, + size_t filenamelen, ff_visited_list_hdr_T **list_headp) { ff_visited_list_hdr_T *retptr = NULL; @@ -1234,7 +1393,7 @@ ff_get_visited_list( return NULL; retptr->ffvl_visited_list = NULL; - retptr->ffvl_filename = vim_strsave(filename); + retptr->ffvl_filename = vim_strnsave(filename, filenamelen); if (retptr->ffvl_filename == NULL) { vim_free(retptr); @@ -1300,7 +1459,9 @@ ff_wc_equal(char_u *s1, char_u *s2) ff_check_visited( ff_visited_T **visited_list, char_u *fname, - char_u *wc_path) + size_t fnamelen, + char_u *wc_path, + size_t wc_pathlen) { ff_visited_T *vp; #ifdef UNIX @@ -1312,20 +1473,24 @@ ff_check_visited( // device/inode (unix) or the full path name (not Unix). if (path_with_url(fname)) { - vim_strncpy(ff_expand_buffer, fname, MAXPATHL - 1); + vim_strncpy(ff_expand_buffer.string, fname, fnamelen); + ff_expand_buffer.length = fnamelen; #ifdef UNIX url = TRUE; #endif } else { - ff_expand_buffer[0] = NUL; + ff_expand_buffer.string[0] = NUL; + ff_expand_buffer.length = 0; #ifdef UNIX if (mch_stat((char *)fname, &st) < 0) + return FAIL; #else - if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) -#endif + if (vim_FullName(fname, ff_expand_buffer.string, MAXPATHL, TRUE) == FAIL) return FAIL; + ff_expand_buffer.length = STRLEN(ff_expand_buffer.string); +#endif } // check against list of already visited files @@ -1337,7 +1502,7 @@ ff_check_visited( && vp->ffv_ino == st.st_ino) : #endif - fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0 + fnamecmp(vp->ffv_fname, ff_expand_buffer.string) == 0 ) { // are the wildcard parts equal @@ -1351,7 +1516,7 @@ ff_check_visited( * New file/dir. Add it to the list of visited files/dirs. */ vp = alloc( - offsetof(ff_visited_T, ffv_fname) + STRLEN(ff_expand_buffer) + 1); + offsetof(ff_visited_T, ffv_fname) + ff_expand_buffer.length + 1); if (vp == NULL) return OK; @@ -1359,20 +1524,20 @@ ff_check_visited( if (!url) { vp->ffv_dev_valid = TRUE; - vp->ffv_ino = st.st_ino; vp->ffv_dev = st.st_dev; + vp->ffv_ino = st.st_ino; vp->ffv_fname[0] = NUL; } else { vp->ffv_dev_valid = FALSE; #endif - STRCPY(vp->ffv_fname, ff_expand_buffer); + STRCPY(vp->ffv_fname, ff_expand_buffer.string); #ifdef UNIX } #endif if (wc_path != NULL) - vp->ffv_wc_path = vim_strsave(wc_path); + vp->ffv_wc_path = vim_strnsave(wc_path, wc_pathlen); else vp->ffv_wc_path = NULL; @@ -1388,7 +1553,9 @@ ff_check_visited( static ff_stack_T * ff_create_stack_element( char_u *fix_part, + size_t fix_partlen, char_u *wc_part, + size_t wc_partlen, int level, int star_star_empty) { @@ -1408,14 +1575,22 @@ ff_create_stack_element( // the following saves NULL pointer checks in vim_findfile if (fix_part == NULL) + { fix_part = (char_u *)""; - new->ffs_fix_path = vim_strsave(fix_part); + fix_partlen = 0; + } + new->ffs_fix_path.string = vim_strnsave(fix_part, fix_partlen); + new->ffs_fix_path.length = fix_partlen; if (wc_part == NULL) - wc_part = (char_u *)""; - new->ffs_wc_path = vim_strsave(wc_part); + { + wc_part = (char_u *)""; + wc_partlen = 0; + } + new->ffs_wc_path.string = vim_strnsave(wc_part, wc_partlen); + new->ffs_wc_path.length = wc_partlen; - if (new->ffs_fix_path == NULL || new->ffs_wc_path == NULL) + if (new->ffs_fix_path.string == NULL || new->ffs_wc_path.string == NULL) { ff_free_stack_element(new); new = NULL; @@ -1461,9 +1636,9 @@ ff_pop(ff_search_ctx_T *search_ctx) static void ff_free_stack_element(ff_stack_T *stack_ptr) { - // vim_free handles possible NULL pointers - vim_free(stack_ptr->ffs_fix_path); - vim_free(stack_ptr->ffs_wc_path); + // VIM_CLEAR_STRING handles possible NULL pointers + VIM_CLEAR_STRING(stack_ptr->ffs_fix_path); + VIM_CLEAR_STRING(stack_ptr->ffs_wc_path); if (stack_ptr->ffs_filearray != NULL) FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray); @@ -1483,29 +1658,23 @@ ff_clear(ff_search_ctx_T *search_ctx) while ((sptr = ff_pop(search_ctx)) != NULL) ff_free_stack_element(sptr); - vim_free(search_ctx->ffsc_file_to_search); - vim_free(search_ctx->ffsc_start_dir); - vim_free(search_ctx->ffsc_fix_path); - vim_free(search_ctx->ffsc_wc_path); - if (search_ctx->ffsc_stopdirs_v != NULL) { int i = 0; - while (search_ctx->ffsc_stopdirs_v[i] != NULL) + while (search_ctx->ffsc_stopdirs_v[i].string != NULL) { - vim_free(search_ctx->ffsc_stopdirs_v[i]); + vim_free(search_ctx->ffsc_stopdirs_v[i].string); i++; } - vim_free(search_ctx->ffsc_stopdirs_v); + VIM_CLEAR(search_ctx->ffsc_stopdirs_v); } - search_ctx->ffsc_stopdirs_v = NULL; // reset everything - search_ctx->ffsc_file_to_search = NULL; - search_ctx->ffsc_start_dir = NULL; - search_ctx->ffsc_fix_path = NULL; - search_ctx->ffsc_wc_path = NULL; + VIM_CLEAR_STRING(search_ctx->ffsc_file_to_search); + VIM_CLEAR_STRING(search_ctx->ffsc_start_dir); + VIM_CLEAR_STRING(search_ctx->ffsc_fix_path); + VIM_CLEAR_STRING(search_ctx->ffsc_wc_path); search_ctx->ffsc_level = 0; } @@ -1514,7 +1683,7 @@ ff_clear(ff_search_ctx_T *search_ctx) * returns TRUE if yes else FALSE */ static int -ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v) +ff_path_in_stoplist(char_u *path, int path_len, string_T *stopdirs_v) { int i = 0; @@ -1526,13 +1695,13 @@ ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v) if (path_len == 0) return TRUE; - for (i = 0; stopdirs_v[i] != NULL; i++) + for (i = 0; stopdirs_v[i].string != NULL; i++) // match for parent directory. So '/home' also matches // '/home/rks'. Check for PATHSEP in stopdirs_v[i], else // '/home/r' would also match '/home/rks' - if (fnamencmp(stopdirs_v[i], path, path_len) == 0 - && ((int)STRLEN(stopdirs_v[i]) <= path_len - || vim_ispathsep(stopdirs_v[i][path_len]))) + if (fnamencmp(stopdirs_v[i].string, path, path_len) == 0 + && ((int)stopdirs_v[i].length <= path_len + || vim_ispathsep(stopdirs_v[i].string[path_len]))) return TRUE; return FALSE; @@ -1583,7 +1752,7 @@ find_file_in_path( void free_findfile(void) { - VIM_CLEAR(ff_expand_buffer); + VIM_CLEAR_STRING(ff_expand_buffer); } # endif @@ -1628,9 +1797,7 @@ find_file_in_path_option( 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; char_u *file_name = NULL; - char_u *buf = NULL; int rel_to_curdir; # ifdef AMIGA struct Process *proc = (struct Process *)FindTask(0L); @@ -1639,9 +1806,12 @@ find_file_in_path_option( // Avoid a requester here for a volume that doesn't exist. proc->pr_WindowPtr = (APTR)-1L; # endif + static size_t file_to_findlen = 0; if (first == TRUE) { + char_u save_char; + if (len == 0) return NULL; @@ -1652,10 +1822,12 @@ find_file_in_path_option( ptr[len] = save_char; vim_free(*file_to_find); - *file_to_find = vim_strsave(NameBuff); + file_to_findlen = STRLEN(NameBuff); + *file_to_find = vim_strnsave(NameBuff, file_to_findlen); if (*file_to_find == NULL) // out of memory { file_name = NULL; + file_to_findlen = 0; goto theend; } if (options & FNAME_UNESC) @@ -1663,7 +1835,11 @@ find_file_in_path_option( // Change all "\ " to " ". for (ptr = *file_to_find; *ptr != NUL; ++ptr) if (ptr[0] == '\' && ptr[1] == ' ') - mch_memmove(ptr, ptr + 1, STRLEN(ptr)); + { + mch_memmove(ptr, ptr + 1, + (size_t)((*file_to_find + file_to_findlen) - (ptr + 1)) + 1); + --file_to_findlen; + } } } @@ -1697,27 +1873,36 @@ find_file_in_path_option( { int l; int run; + size_t rel_fnamelen = 0; + char_u *suffix; if (path_with_url(*file_to_find)) { - file_name = vim_strsave(*file_to_find); + file_name = vim_strnsave(*file_to_find, file_to_findlen); goto theend; } + if (rel_fname != NULL) + rel_fnamelen = STRLEN(rel_fname); + // When FNAME_REL flag given first use the directory of the file. // Otherwise or when this fails use the current directory. for (run = 1; run <= 2; ++run) { - l = (int)STRLEN(*file_to_find); + l = (int)file_to_findlen; if (run == 1 && rel_to_curdir && (options & FNAME_REL) && rel_fname != NULL - && STRLEN(rel_fname) + l < MAXPATHL) + && rel_fnamelen + l < MAXPATHL) { - STRCPY(NameBuff, rel_fname); - STRCPY(gettail(NameBuff), *file_to_find); - l = (int)STRLEN(NameBuff); + l = vim_snprintf( + (char *)NameBuff, + MAXPATHL, + "%.*s%s", + (int)(gettail(rel_fname) - rel_fname), + rel_fname, + *file_to_find); } else { @@ -1727,7 +1912,7 @@ find_file_in_path_option( // When the file doesn't exist, try adding parts of // 'suffixesadd'. - buf = suffixes; + suffix = suffixes; for (;;) { if (mch_getperm(NameBuff) >= 0 @@ -1735,12 +1920,12 @@ find_file_in_path_option( || ((find_what == FINDFILE_DIR) == mch_isdir(NameBuff)))) { - file_name = vim_strsave(NameBuff); + file_name = vim_strnsave(NameBuff, l); goto theend; } - if (*buf == NUL) + if (*suffix == NUL) break; - copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ","); + l += copy_option_part(&suffix, NameBuff + l, MAXPATHL - l, ","); } } } @@ -1772,6 +1957,7 @@ find_file_in_path_option( } else { + char_u *buf; char_u *r_ptr; if (dir == NULL || *dir == NUL) @@ -1787,12 +1973,12 @@ find_file_in_path_option( break; // copy next path - buf[0] = 0; + buf[0] = NUL; copy_option_part(&dir, buf, MAXPATHL, " ,"); // get the stopdir string r_ptr = vim_findfile_stopdir(buf); - *search_ctx = vim_findfile_init(buf, *file_to_find, + *search_ctx = vim_findfile_init(buf, *file_to_find, file_to_findlen, r_ptr, 100, FALSE, find_what, *search_ctx, FALSE, rel_fname); if (*search_ctx != NULL) @@ -1963,20 +2149,27 @@ file_name_in_line( if (file_lnum != NULL) { - char_u *p; - char *line_english = " line "; - char *line_transl = _(line_msg); + char_u *p; + char *match_text = " line "; // english + size_t match_textlen = 6; // Get the number after the file name and a separator character. // Also accept " line 999" with and without the same translation as // used in last_set_msg(). p = ptr + len; - if (STRNCMP(p, line_english, STRLEN(line_english)) == 0) - p += STRLEN(line_english); - else if (STRNCMP(p, line_transl, STRLEN(line_transl)) == 0) - p += STRLEN(line_transl); + if (STRNCMP(p, match_text, match_textlen) == 0) + p += match_textlen; else - p = skipwhite(p); + { + // no match with english, try localized + match_text = _(line_msg); + match_textlen = STRLEN(match_text); + + if (STRNCMP(p, match_text, match_textlen) == 0) + p += match_textlen; + else + p = skipwhite(p); + } if (*p != NUL) { if (!SAFE_isdigit(*p)) @@ -2177,7 +2370,7 @@ find_previous_pathsep(char_u *path, char_u **psep) is_unique(char_u *maybe_unique, garray_T *gap, int i) { int j; - int candidate_len; + int candidate_len = (int)STRLEN(maybe_unique); int other_path_len; char_u **other_paths = (char_u **)gap->ga_data; char_u *rival; @@ -2187,7 +2380,6 @@ is_unique(char_u *maybe_unique, garray_T *gap, int i) if (j == i) continue; // don't compare it with itself - candidate_len = (int)STRLEN(maybe_unique); other_path_len = (int)STRLEN(other_paths[j]); if (other_path_len < candidate_len) continue; // it's different when it's shorter @@ -2217,50 +2409,60 @@ expand_path_option( garray_T *gap) { char_u *buf; + size_t buflen; char_u *p; - int len; + size_t curdirlen = 0; if ((buf = alloc(MAXPATHL)) == NULL) return; while (*path_option != NUL) { - copy_option_part(&path_option, buf, MAXPATHL, " ,"); + buflen = copy_option_part(&path_option, buf, MAXPATHL, " ,"); if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) { + size_t plen; + // Relative to current buffer: // "/path/file" + "." -> "/path/" // "/path/file" + "./subdir" -> "/path/subdir" if (curbuf->b_ffname == NULL) continue; p = gettail(curbuf->b_ffname); - len = (int)(p - curbuf->b_ffname); - if (len + (int)STRLEN(buf) >= MAXPATHL) + plen = (size_t)(p - curbuf->b_ffname); + if (plen + buflen >= MAXPATHL) continue; if (buf[1] == NUL) - buf[len] = NUL; + buf[plen] = NUL; else - STRMOVE(buf + len, buf + 2); - mch_memmove(buf, curbuf->b_ffname, len); - simplify_filename(buf); + mch_memmove(buf + plen, buf + 2, (buflen - 2) + 1); // +1 for NUL + mch_memmove(buf, curbuf->b_ffname, plen); + buflen = simplify_filename(buf); } else if (buf[0] == NUL) + { // relative to current directory STRCPY(buf, curdir); + if (curdirlen == 0) + curdirlen = STRLEN(curdir); + buflen = curdirlen; + } else if (path_with_url(buf)) // URL can't be used here continue; else if (!mch_isFullName(buf)) { // Expand relative path to their full path equivalent - len = (int)STRLEN(curdir); - if (len + (int)STRLEN(buf) + 3 > MAXPATHL) + if (curdirlen == 0) + curdirlen = STRLEN(curdir); + if (curdirlen + buflen + 3 > MAXPATHL) continue; - STRMOVE(buf + len + 1, buf); + + mch_memmove(buf + curdirlen + 1, buf, buflen + 1); // +1 for NUL STRCPY(buf, curdir); - buf[len] = PATHSEP; - simplify_filename(buf); + buf[curdirlen] = PATHSEP; + buflen = simplify_filename(buf); } if (ga_grow(gap, 1) == FAIL) @@ -2269,12 +2471,11 @@ expand_path_option( # if defined(MSWIN) // Avoid the path ending in a backslash, it fails when a comma is // appended. - len = (int)STRLEN(buf); - if (buf[len - 1] == '\') - buf[len - 1] = '/'; + if (buf[buflen - 1] == '\') + buf[buflen - 1] = '/'; # endif - p = vim_strsave(buf); + p = vim_strnsave(buf, buflen); if (p == NULL) break; ((char_u **)gap->ga_data)[gap->ga_len++] = p; @@ -2360,8 +2561,7 @@ uniquefy_paths( if (file_pattern == NULL) return; file_pattern[0] = '*'; - file_pattern[1] = NUL; - STRCAT(file_pattern, pattern); + STRCPY(file_pattern + 1, pattern); pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, FALSE); vim_free(file_pattern); if (pat == NULL) @@ -2387,14 +2587,13 @@ uniquefy_paths( char_u *path = fnames[i]; int is_in_curdir; char_u *dir_end = gettail_dir(path); - char_u *pathsep_p; char_u *path_cutoff; len = (int)STRLEN(path); is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0 && curdir[dir_end - path] == NUL; if (is_in_curdir) - in_curdir[i] = vim_strsave(path); + in_curdir[i] = vim_strnsave(path, len); // Shorten the filename while maintaining its uniqueness path_cutoff = get_path_cutoff(path, &path_ga); @@ -2415,17 +2614,20 @@ uniquefy_paths( { // Here all files can be reached without path, so get shortest // unique path. We start at the end of the path. - pathsep_p = path + len - 1; + char_u *pathsep_p = path + len - 1; while (find_previous_pathsep(path, &pathsep_p)) + { if (vim_regexec(®match, pathsep_p + 1, (colnr_T)0) && is_unique(pathsep_p + 1, gap, i) && path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) { sort_again = TRUE; - mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p)); + mch_memmove(path, pathsep_p + 1, + (size_t)((path + len) - (pathsep_p + 1)) + 1); // +1 for NUL break; } + } } if (mch_isFullName(path)) @@ -2453,9 +2655,7 @@ uniquefy_paths( # endif ) { - STRCPY(path, "."); - add_pathsep(path); - STRMOVE(path + STRLEN(path), short_name); + vim_snprintf((char *)path, MAXPATHL, ".%s%s", PATHSEPSTR, short_name); } } ui_breakcheck(); @@ -2464,8 +2664,9 @@ uniquefy_paths( // Shorten filenames in /in/current/directory/{filename} for (i = 0; i < gap->ga_len && !got_int; i++) { - char_u *rel_path; - char_u *path = in_curdir[i]; + size_t rel_pathsize; + char_u *rel_path; + char_u *path = in_curdir[i]; if (path == NULL) continue; @@ -2481,12 +2682,12 @@ uniquefy_paths( continue; } - rel_path = alloc(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2); + rel_pathsize = 1 + STRLEN_LITERAL(PATHSEPSTR) + STRLEN(short_name) + 1; + rel_path = alloc(rel_pathsize); if (rel_path == NULL) goto theend; - STRCPY(rel_path, "."); - add_pathsep(rel_path); - STRCAT(rel_path, short_name); + + vim_snprintf((char *)rel_path, rel_pathsize, ".%s%s", PATHSEPSTR, short_name); vim_free(fnames[i]); fnames[i] = rel_path; @@ -2561,12 +2762,13 @@ expand_in_path( * resulting file name is simplified in place and will either be the same * length as that supplied, or shorter. */ - void + size_t simplify_filename(char_u *filename) { #ifndef AMIGA // Amiga doesn't have "..", it uses "/" int components = 0; char_u *p, *tail, *start; + char_u *p_end; // point to NUL at end of string "p" int stripping_disabled = FALSE; int relative = TRUE; @@ -2584,11 +2786,13 @@ simplify_filename(char_u *filename) while (vim_ispathsep(*p)); } start = p; // remember start after "c:/" or "/" or "///" + p_end = p + STRLEN(p); #ifdef UNIX // Posix says that "//path" is unchanged but "///path" is "/path". if (start > filename + 2) { - STRMOVE(filename + 1, p); + mch_memmove(filename + 1, p, (size_t)(p_end - p) + 1); // +1 for NUL + p_end -= (size_t)(p - (filename + 1)); start = p = filename + 1; } #endif @@ -2614,8 +2818,11 @@ simplify_filename(char_u *filename) } else # endif - if (vim_ispathsep(*p)) - STRMOVE(p, p + 1); // remove duplicate "/" + if (vim_ispathsep(*p)) + { + mch_memmove(p, p + 1, (size_t)(p_end - (p + 1)) + 1); // remove duplicate "/" + --p_end; + } else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL)) { if (p == start && relative) @@ -2632,7 +2839,9 @@ simplify_filename(char_u *filename) MB_PTR_ADV(tail); else if (p > start) --p; // strip preceding path separator - STRMOVE(p, tail); + + mch_memmove(p, tail, (size_t)(p_end - tail) + 1); + p_end -= (size_t)(tail - p); } } else if (p[0] == '.' && p[1] == '.' && @@ -2748,19 +2957,25 @@ simplify_filename(char_u *filename) { if (p > start && tail[-1] == '.') --p; - STRMOVE(p, tail); // strip previous component + + mch_memmove(p, tail, (size_t)(p_end - tail) + 1); // strip previous component + p_end -= (size_t)(tail - p); } --components; } } else if (p == start && !relative) // leading "/.." or "/../" - STRMOVE(p, tail); // strip ".." or "../" + { + mch_memmove(p, tail, (size_t)(p_end - tail) + 1); // strip ".." or "../" + p_end -= (size_t)(tail - p); + } else { if (p == start + 2 && p[-2] == '.') // leading "./../" { - STRMOVE(p - 2, p); // strip leading "./" + mch_memmove(p - 2, p, (size_t)(p_end - p) + 1); // strip leading "./" + p_end -= 2; tail -= 2; } p = tail; // skip to char after ".." or "../" @@ -2773,6 +2988,8 @@ simplify_filename(char_u *filename) } } while (*p != NUL); #endif // !AMIGA + + return (size_t)(p_end - filename); } #if defined(FEAT_EVAL) || defined(PROTO) diff --git a/src/proto/findfile.pro b/src/proto/findfile.pro index 1c2822157..628042c13 100644 --- a/src/proto/findfile.pro +++ b/src/proto/findfile.pro @@ -1,5 +1,5 @@ /* findfile.c */ -void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int level, int free_visited, int find_what, void *search_ctx_arg, int tagfile, char_u *rel_fname); +void *vim_findfile_init(char_u *path, char_u *filename, size_t filenamelen, char_u *stopdirs, int level, int free_visited, int find_what, void *search_ctx_arg, int tagfile, char_u *rel_fname); char_u *vim_findfile_stopdir(char_u *buf); void vim_findfile_cleanup(void *ctx); char_u *vim_findfile(void *search_ctx_arg); @@ -14,6 +14,6 @@ char_u *find_file_name_in_path(char_u *ptr, int len, int options, long count, ch int vim_ispathlistsep(int c); void uniquefy_paths(garray_T *gap, char_u *pattern, char_u *path_option); int expand_in_path(garray_T *gap, char_u *pattern, int flags); -void simplify_filename(char_u *filename); +size_t simplify_filename(char_u *filename); void f_simplify(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/tag.c b/src/tag.c index f94d3eb9d..21ff5636a 100644 --- a/src/tag.c +++ b/src/tag.c @@ -3421,6 +3421,7 @@ get_tagfname( *filename++ = NUL; tnp->tn_search_ctx = vim_findfile_init(buf, filename, + STRLEN(filename), r_ptr, 100, FALSE, // don't free visited list FINDFILE_FILE, // we search for a file diff --git a/src/version.c b/src/version.c index ba99dde61..f400ca9e6 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1122, /**/ 1121, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1tkTlD-00GiXW-Gg%40256bit.org.