aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-02-19 17:14:38 +0800
committerGitHub <noreply@github.com>2025-02-19 17:14:38 +0800
commita3eb49f6382ba6fd6a61ecfebd7b526fa9730e29 (patch)
tree75d17475af326e178cbecaf73c02e475eaaeb271 /src
parent9005134cdc8e578201b90192253171a9bc261752 (diff)
downloadrneovim-a3eb49f6382ba6fd6a61ecfebd7b526fa9730e29.tar.gz
rneovim-a3eb49f6382ba6fd6a61ecfebd7b526fa9730e29.tar.bz2
rneovim-a3eb49f6382ba6fd6a61ecfebd7b526fa9730e29.zip
vim-patch:9.1.1122: too many strlen() calls in findfile.c (#32516)
Problem: too many strlen() calls in findfile.c Solution: refactor findfile.c and remove calls to strlen() (John Marriott) closes: vim/vim#16595 https://github.com/vim/vim/commit/d6e3c9048dfb7e8f08f8fadc820c7e2208c3f030 Co-authored-by: John Marriott <basilisk@internode.on.net>
Diffstat (limited to 'src')
-rw-r--r--src/nvim/file_search.c542
-rw-r--r--src/nvim/path.c82
-rw-r--r--src/nvim/tag.c2
3 files changed, 368 insertions, 258 deletions
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 1e6153bf8d..c374322d22 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -50,6 +50,8 @@
#include <stdlib.h>
#include <string.h>
+#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/autocmd_defs.h"
@@ -80,7 +82,7 @@
#include "nvim/strings.h"
#include "nvim/vim_defs.h"
-static char *ff_expand_buffer = NULL; // used for expanding filenames
+static String ff_expand_buffer = STRING_INIT; // used for expanding filenames
// type for the directory search stack
typedef struct ff_stack {
@@ -88,8 +90,8 @@ typedef struct ff_stack {
// the fix part (no wildcards) and the part containing the wildcards
// of the search path
- char *ffs_fix_path;
- char *ffs_wc_path;
+ String ffs_fix_path;
+ String ffs_wc_path;
// files/dirs found in the above directory, matched by the first wildcard
// of wc_part
@@ -172,12 +174,12 @@ typedef struct {
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 *ffsc_file_to_search;
- char *ffsc_start_dir;
- char *ffsc_fix_path;
- char *ffsc_wc_path;
+ String ffsc_file_to_search;
+ String ffsc_start_dir;
+ String ffsc_fix_path;
+ String ffsc_wc_path;
int ffsc_level;
- char **ffsc_stopdirs_v;
+ String *ffsc_stopdirs_v;
int ffsc_find_what;
int ffsc_tagfile;
} ff_search_ctx_T;
@@ -244,8 +246,9 @@ static const char e_path_too_long_for_completion[]
///
/// @param tagfile expanding names of tags files
/// @param rel_fname file name to use for "."
-void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, int free_visited,
- int find_what, void *search_ctx_arg, int tagfile, char *rel_fname)
+void *vim_findfile_init(char *path, char *filename, size_t filenamelen, char *stopdirs, int level,
+ int free_visited, int find_what, void *search_ctx_arg, int tagfile,
+ char *rel_fname)
{
ff_stack_T *sptr;
ff_search_ctx_T *search_ctx;
@@ -270,20 +273,23 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
// Reuse old visited lists. Get the visited list for the given
// 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);
+ search_ctx->ffsc_visited_list
+ = ff_get_visited_list(filename, 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);
+ search_ctx->ffsc_dir_visited_list
+ = ff_get_visited_list(filename, filenamelen,
+ &search_ctx->ffsc_dir_visited_lists_list);
if (search_ctx->ffsc_dir_visited_list == NULL) {
goto error_return;
}
}
- if (ff_expand_buffer == NULL) {
- ff_expand_buffer = xmalloc(MAXPATHL);
+ if (ff_expand_buffer.data == NULL) {
+ ff_expand_buffer.size = 0;
+ ff_expand_buffer.data = xmalloc(MAXPATHL);
}
// Store information on starting dir now if path is relative.
@@ -296,10 +302,11 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) {
// Make the start dir an absolute path name.
- xmemcpyz(ff_expand_buffer, rel_fname, len);
- search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, false);
+ xmemcpyz(ff_expand_buffer.data, rel_fname, len);
+ ff_expand_buffer.size = len;
+ search_ctx->ffsc_start_dir = cstr_as_string(FullName_save(ff_expand_buffer.data, false));
} else {
- search_ctx->ffsc_start_dir = xmemdupz(rel_fname, len);
+ search_ctx->ffsc_start_dir = cbuf_to_string(rel_fname, len);
}
if (*++path != NUL) {
path++;
@@ -313,25 +320,27 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
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.data, MAXPATHL, true) == FAIL) {
goto error_return;
}
path += 2;
} else
#endif
- if (os_dirname(ff_expand_buffer, MAXPATHL) == FAIL) {
+ if (os_dirname(ff_expand_buffer.data, MAXPATHL) == FAIL) {
goto error_return;
}
+ ff_expand_buffer.size = strlen(ff_expand_buffer.data);
- search_ctx->ffsc_start_dir = xstrdup(ff_expand_buffer);
+ search_ctx->ffsc_start_dir = copy_string(ff_expand_buffer, NULL);
#ifdef BACKSLASH_IN_FILENAME
// A path that starts with "/dir" is relative to the drive, not to the
// 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.data[1] == ':') {
+ search_ctx->ffsc_start_dir.data[2] = NUL;
+ search_ctx->ffsc_start_dir.size = 2;
}
#endif
}
@@ -351,12 +360,12 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
}
size_t dircount = 1;
- search_ctx->ffsc_stopdirs_v = xmalloc(sizeof(char *));
+ search_ctx->ffsc_stopdirs_v = xmalloc(sizeof(String));
do {
char *helper = walker;
void *ptr = xrealloc(search_ctx->ffsc_stopdirs_v,
- (dircount + 1) * sizeof(char *));
+ (dircount + 1) * sizeof(String));
search_ctx->ffsc_stopdirs_v = ptr;
walker = vim_strchr(walker, ';');
assert(!walker || walker - helper >= 0);
@@ -364,17 +373,19 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
// "" means ascent till top of directory tree.
if (*helper != NUL && !vim_isAbsName(helper) && len + 1 < MAXPATHL) {
// Make the stop dir an absolute path name.
- xmemcpyz(ff_expand_buffer, helper, len);
- search_ctx->ffsc_stopdirs_v[dircount - 1] = FullName_save(helper, len);
+ xmemcpyz(ff_expand_buffer.data, helper, len);
+ ff_expand_buffer.size = len;
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = cstr_as_string(FullName_save(helper, len));
} else {
- search_ctx->ffsc_stopdirs_v[dircount - 1] = xmemdupz(helper, len);
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = cbuf_to_string(helper, len);
}
if (walker) {
walker++;
}
dircount++;
} while (walker != NULL);
- search_ctx->ffsc_stopdirs_v[dircount - 1] = NULL;
+
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = NULL_STRING;
}
search_ctx->ffsc_level = level;
@@ -385,12 +396,11 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
char *wc_part = vim_strchr(path, '*');
if (wc_part != NULL) {
int64_t llevel;
- int len;
char *errpt;
// save the fix part of the path
assert(wc_part - path >= 0);
- search_ctx->ffsc_fix_path = xstrnsave(path, (size_t)(wc_part - path));
+ search_ctx->ffsc_fix_path = cbuf_to_string(path, (size_t)(wc_part - path));
// copy wc_path and add restricts to the '**' wildcard.
// The octet after a '**' is used as a (binary) counter.
@@ -399,24 +409,24 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
// If no restrict is given after '**' the default is used.
// Due to this technique the path looks awful if you print it as a
// string.
- len = 0;
+ ff_expand_buffer.size = 0;
while (*wc_part != NUL) {
- if (len + 5 >= MAXPATHL) {
+ if (ff_expand_buffer.size + 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.data[ff_expand_buffer.size++] = *wc_part++;
+ ff_expand_buffer.data[ff_expand_buffer.size++] = *wc_part++;
llevel = strtol(wc_part, &errpt, 10);
if (errpt != wc_part && llevel > 0 && llevel < 255) {
- ff_expand_buffer[len++] = (char)llevel;
+ ff_expand_buffer.data[ff_expand_buffer.size++] = (char)llevel;
} else if (errpt != wc_part && llevel == 0) {
// restrict is 0 -> remove already added '**'
- len -= 2;
+ ff_expand_buffer.size -= 2;
} else {
- ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
+ ff_expand_buffer.data[ff_expand_buffer.size++] = FF_MAX_STAR_STAR_EXPAND;
}
wc_part = errpt;
if (*wc_part != NUL && !vim_ispathsep(*wc_part)) {
@@ -426,78 +436,108 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
goto error_return;
}
} else {
- ff_expand_buffer[len++] = *wc_part++;
+ ff_expand_buffer.data[ff_expand_buffer.size++] = *wc_part++;
}
}
- ff_expand_buffer[len] = NUL;
- search_ctx->ffsc_wc_path = xstrdup(ff_expand_buffer);
+ ff_expand_buffer.data[ff_expand_buffer.size] = NUL;
+ search_ctx->ffsc_wc_path = copy_string(ff_expand_buffer, false);
} else {
- search_ctx->ffsc_fix_path = xstrdup(path);
+ search_ctx->ffsc_fix_path = cstr_to_string(path);
}
- if (search_ctx->ffsc_start_dir == NULL) {
+ if (search_ctx->ffsc_start_dir.data == NULL) {
// store the fix part as startdir.
// This is needed if the parameter path is fully qualified.
- search_ctx->ffsc_start_dir = xstrdup(search_ctx->ffsc_fix_path);
- search_ctx->ffsc_fix_path[0] = NUL;
+ search_ctx->ffsc_start_dir = copy_string(search_ctx->ffsc_fix_path, false);
+ search_ctx->ffsc_fix_path.data[0] = NUL;
+ search_ctx->ffsc_fix_path.size = 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.size
+ + search_ctx->ffsc_fix_path.size + 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);
- {
- size_t eb_len = strlen(ff_expand_buffer);
- char *buf = xmalloc(eb_len + strlen(search_ctx->ffsc_fix_path) + 1);
- STRCPY(buf, ff_expand_buffer);
- STRCPY(buf + eb_len, search_ctx->ffsc_fix_path);
+ bool add_sep = !after_pathsep(search_ctx->ffsc_start_dir.data,
+ search_ctx->ffsc_start_dir.data + search_ctx->ffsc_start_dir.size);
+ ff_expand_buffer.size = (size_t)vim_snprintf(ff_expand_buffer.data,
+ MAXPATHL,
+ "%s%s",
+ search_ctx->ffsc_start_dir.data,
+ add_sep ? PATHSEPSTR : "");
+ assert(ff_expand_buffer.size < MAXPATHL);
+
+ {
+ size_t bufsize = ff_expand_buffer.size + search_ctx->ffsc_fix_path.size + 1;
+ char *buf = xmalloc(bufsize);
+
+ vim_snprintf(buf,
+ bufsize,
+ "%s%s",
+ ff_expand_buffer.data,
+ search_ctx->ffsc_fix_path.data);
if (os_isdir(buf)) {
- strcat(ff_expand_buffer, search_ctx->ffsc_fix_path);
- add_pathsep(ff_expand_buffer);
+ if (search_ctx->ffsc_fix_path.size > 0) {
+ add_sep = !after_pathsep(search_ctx->ffsc_fix_path.data,
+ search_ctx->ffsc_fix_path.data + search_ctx->ffsc_fix_path.size);
+ ff_expand_buffer.size += (size_t)vim_snprintf(ff_expand_buffer.data + ff_expand_buffer.size,
+ MAXPATHL - ff_expand_buffer.size,
+ "%s%s",
+ search_ctx->ffsc_fix_path.data,
+ add_sep ? PATHSEPSTR : "");
+ assert(ff_expand_buffer.size < MAXPATHL);
+ }
} else {
- char *p = path_tail(search_ctx->ffsc_fix_path);
- char *wc_path = NULL;
- char *temp = NULL;
- int len = 0;
+ char *p = path_tail(search_ctx->ffsc_fix_path.data);
+ int len = (int)search_ctx->ffsc_fix_path.size;
- if (p > search_ctx->ffsc_fix_path) {
+ if (p > search_ctx->ffsc_fix_path.data) {
// do not add '..' to the path and start upwards searching
- len = (int)(p - search_ctx->ffsc_fix_path) - 1;
- if ((len >= 2 && strncmp(search_ctx->ffsc_fix_path, "..", 2) == 0)
- && (len == 2 || search_ctx->ffsc_fix_path[2] == PATHSEP)) {
+ len = (int)(p - search_ctx->ffsc_fix_path.data) - 1;
+ if ((len >= 2 && strncmp(search_ctx->ffsc_fix_path.data, "..", 2) == 0)
+ && (len == 2 || search_ctx->ffsc_fix_path.data[2] == PATHSEP)) {
xfree(buf);
goto error_return;
}
- xstrlcat(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1);
- add_pathsep(ff_expand_buffer);
- } else {
- len = (int)strlen(search_ctx->ffsc_fix_path);
+
+ add_sep = !after_pathsep(search_ctx->ffsc_fix_path.data,
+ search_ctx->ffsc_fix_path.data + search_ctx->ffsc_fix_path.size);
+ ff_expand_buffer.size += (size_t)vim_snprintf(ff_expand_buffer.data + ff_expand_buffer.size,
+ MAXPATHL - ff_expand_buffer.size,
+ "%.*s%s",
+ len,
+ search_ctx->ffsc_fix_path.data,
+ add_sep ? PATHSEPSTR : "");
+ assert(ff_expand_buffer.size < MAXPATHL);
}
- if (search_ctx->ffsc_wc_path != NULL) {
- wc_path = xstrdup(search_ctx->ffsc_wc_path);
- temp = xmalloc(strlen(search_ctx->ffsc_wc_path)
- + strlen(search_ctx->ffsc_fix_path + len)
- + 1);
- STRCPY(temp, search_ctx->ffsc_fix_path + len);
- strcat(temp, search_ctx->ffsc_wc_path);
- xfree(search_ctx->ffsc_wc_path);
- xfree(wc_path);
- search_ctx->ffsc_wc_path = temp;
+ if (search_ctx->ffsc_wc_path.data != NULL) {
+ size_t tempsize = (search_ctx->ffsc_fix_path.size - (size_t)len)
+ + search_ctx->ffsc_wc_path.size + 1;
+ char *temp = xmalloc(tempsize);
+ search_ctx->ffsc_wc_path.size = (size_t)vim_snprintf(temp,
+ tempsize,
+ "%s%s",
+ search_ctx->ffsc_fix_path.data + len,
+ search_ctx->ffsc_wc_path.data);
+ assert(search_ctx->ffsc_wc_path.size < tempsize);
+ xfree(search_ctx->ffsc_wc_path.data);
+ search_ctx->ffsc_wc_path.data = temp;
}
}
xfree(buf);
}
- sptr = ff_create_stack_element(ff_expand_buffer, search_ctx->ffsc_wc_path, level, 0);
+ sptr = ff_create_stack_element(ff_expand_buffer.data,
+ ff_expand_buffer.size,
+ search_ctx->ffsc_wc_path.data,
+ search_ctx->ffsc_wc_path.size,
+ level, 0);
ff_push(search_ctx, sptr);
- search_ctx->ffsc_file_to_search = xstrdup(filename);
+ search_ctx->ffsc_file_to_search = cbuf_to_string(filename, filenamelen);
return search_ctx;
error_return:
@@ -570,12 +610,9 @@ void vim_findfile_cleanup(void *ctx)
/// NULL if nothing found.
char *vim_findfile(void *search_ctx_arg)
{
- char *rest_of_wildcards;
+ String rest_of_wildcards;
char *path_end = NULL;
ff_stack_T *stackp = NULL;
- size_t len;
- char *p;
- char *suf;
if (search_ctx_arg == NULL) {
return NULL;
@@ -585,11 +622,11 @@ char *vim_findfile(void *search_ctx_arg)
// filepath is used as buffer for various actions and as the storage to
// return a found filename.
- char *file_path = xmalloc(MAXPATHL);
+ String file_path = { .data = xmalloc(MAXPATHL) };
// 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.data != NULL) {
+ path_end = &search_ctx->ffsc_start_dir.data[search_ctx->ffsc_start_dir.size];
}
// upward search loop
@@ -627,12 +664,13 @@ char *vim_findfile(void *search_ctx_arg)
// first time (hence stackp->ff_filearray == NULL)
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.data, stackp->ffs_fix_path.size,
+ stackp->ffs_wc_path.data, stackp->ffs_wc_path.size) == FAIL) {
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
smsg(0, "Already Searched: %s (%s)",
- stackp->ffs_fix_path, stackp->ffs_wc_path);
+ stackp->ffs_fix_path.data, stackp->ffs_wc_path.data);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
@@ -643,7 +681,7 @@ char *vim_findfile(void *search_ctx_arg)
} else if (p_verbose >= 5) {
verbose_enter_scroll();
smsg(0, "Searching: %s (%s)",
- stackp->ffs_fix_path, stackp->ffs_wc_path);
+ stackp->ffs_fix_path.data, stackp->ffs_wc_path.data);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
#endif
@@ -655,7 +693,8 @@ char *vim_findfile(void *search_ctx_arg)
continue;
}
- file_path[0] = NUL;
+ file_path.data[0] = NUL;
+ file_path.size = 0;
// If no filearray till now expand wildcards
// The function expand_wildcards() can handle an array of paths
@@ -665,62 +704,79 @@ char *vim_findfile(void *search_ctx_arg)
char *dirptrs[2];
// we use filepath to build the path expand_wildcards() should expand.
- dirptrs[0] = file_path;
+ dirptrs[0] = file_path.data;
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 (strlen(search_ctx->ffsc_start_dir) + 1 >= MAXPATHL) {
+ if (!vim_isAbsName(stackp->ffs_fix_path.data)
+ && search_ctx->ffsc_start_dir.data) {
+ if (search_ctx->ffsc_start_dir.size + 1 >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- STRCPY(file_path, search_ctx->ffsc_start_dir);
- if (!add_pathsep(file_path)) {
+ bool add_sep = !after_pathsep(search_ctx->ffsc_start_dir.data,
+ search_ctx->ffsc_start_dir.data
+ + search_ctx->ffsc_start_dir.size);
+ file_path.size = (size_t)vim_snprintf(file_path.data,
+ MAXPATHL,
+ "%s%s",
+ search_ctx->ffsc_start_dir.data,
+ add_sep ? PATHSEPSTR : "");
+ if (file_path.size >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
}
// append the fix part of the search path
- if (strlen(file_path) + strlen(stackp->ffs_fix_path) + 1 >= MAXPATHL) {
+ if (file_path.size + stackp->ffs_fix_path.size + 1 >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- strcat(file_path, stackp->ffs_fix_path);
- if (!add_pathsep(file_path)) {
+ bool add_sep = !after_pathsep(stackp->ffs_fix_path.data,
+ stackp->ffs_fix_path.data + stackp->ffs_fix_path.size);
+ file_path.size += (size_t)vim_snprintf(file_path.data + file_path.size,
+ MAXPATHL - file_path.size,
+ "%s%s",
+ stackp->ffs_fix_path.data,
+ add_sep ? PATHSEPSTR : "");
+ if (file_path.size >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
rest_of_wildcards = stackp->ffs_wc_path;
- if (*rest_of_wildcards != NUL) {
- len = strlen(file_path);
- if (strncmp(rest_of_wildcards, "**", 2) == 0) {
+ if (*rest_of_wildcards.data != NUL) {
+ if (strncmp(rest_of_wildcards.data, "**", 2) == 0) {
// pointer to the restrict byte
// The restrict byte is not a character!
- p = rest_of_wildcards + 2;
+ char *p = rest_of_wildcards.data + 2;
if (*p > 0) {
(*p)--;
- if (len + 1 >= MAXPATHL) {
+ if (file_path.size + 1 >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- file_path[len++] = '*';
+ file_path.data[file_path.size++] = '*';
}
if (*p == 0) {
// remove '**<numb> from wildcards
- STRMOVE(rest_of_wildcards, rest_of_wildcards + 3);
+ memmove(rest_of_wildcards.data,
+ rest_of_wildcards.data + 3,
+ (rest_of_wildcards.size - 3) + 1); // +1 for NUL
+ rest_of_wildcards.size -= 3;
+ stackp->ffs_wc_path.size = rest_of_wildcards.size;
} else {
- rest_of_wildcards += 3;
+ rest_of_wildcards.data += 3;
+ rest_of_wildcards.size -= 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.data;
}
}
@@ -729,18 +785,20 @@ char *vim_findfile(void *search_ctx_arg)
// still something else left. This is handled below by
// 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) {
+ while (*rest_of_wildcards.data
+ && !vim_ispathsep(*rest_of_wildcards.data)) {
+ if (file_path.size + 1 >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- file_path[len++] = *rest_of_wildcards++;
+ file_path.data[file_path.size++] = *rest_of_wildcards.data++;
+ rest_of_wildcards.size--;
}
- file_path[len] = NUL;
- if (vim_ispathsep(*rest_of_wildcards)) {
- rest_of_wildcards++;
+ file_path.data[file_path.size] = NUL;
+ if (vim_ispathsep(*rest_of_wildcards.data)) {
+ rest_of_wildcards.data++;
+ rest_of_wildcards.size--;
}
}
@@ -748,7 +806,7 @@ char *vim_findfile(void *search_ctx_arg)
// If the path is a URL don't try this.
if (path_with_url(dirptrs[0])) {
stackp->ffs_filearray = xmalloc(sizeof(char *));
- stackp->ffs_filearray[0] = xstrdup(dirptrs[0]);
+ stackp->ffs_filearray[0] = xmemdupz(dirptrs[0], file_path.size);
stackp->ffs_filearray_size = 1;
} else {
// Add EW_NOTWILD because the expanded path may contain
@@ -763,12 +821,13 @@ char *vim_findfile(void *search_ctx_arg)
stackp->ffs_filearray_cur = 0;
stackp->ffs_stage = 0;
} else {
- rest_of_wildcards = &stackp->ffs_wc_path[strlen(stackp->ffs_wc_path)];
+ rest_of_wildcards.data = &stackp->ffs_wc_path.data[stackp->ffs_wc_path.size];
+ rest_of_wildcards.size = 0;
}
if (stackp->ffs_stage == 0) {
// this is the first time we work on this directory
- if (*rest_of_wildcards == NUL) {
+ if (*rest_of_wildcards.data == NUL) {
// We don't have further wildcards to expand, so we have to
// check for the final file now.
for (int i = stackp->ffs_filearray_cur; i < stackp->ffs_filearray_size; i++) {
@@ -777,44 +836,45 @@ char *vim_findfile(void *search_ctx_arg)
continue; // not a directory
}
// prepare the filename to be checked for existence below
- if (strlen(stackp->ffs_filearray[i]) + 1
- + strlen(search_ctx->ffsc_file_to_search) >= MAXPATHL) {
+ size_t len = strlen(stackp->ffs_filearray[i]);
+ if (len + 1 + search_ctx->ffsc_file_to_search.size >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- STRCPY(file_path, stackp->ffs_filearray[i]);
- if (!add_pathsep(file_path)) {
+ bool add_sep = !after_pathsep(stackp->ffs_filearray[i],
+ stackp->ffs_filearray[i] + len);
+ file_path.size = (size_t)vim_snprintf(file_path.data,
+ MAXPATHL,
+ "%s%s%s",
+ stackp->ffs_filearray[i],
+ add_sep ? PATHSEPSTR : "",
+ search_ctx->ffsc_file_to_search.data);
+ if (file_path.size >= MAXPATHL) {
ff_free_stack_element(stackp);
goto fail;
}
- strcat(file_path, search_ctx->ffsc_file_to_search);
// Try without extra suffix and then with suffixes
// from 'suffixesadd'.
- len = strlen(file_path);
- if (search_ctx->ffsc_tagfile) {
- suf = "";
- } else {
- suf = curbuf->b_p_sua;
- }
+ char *suf = search_ctx->ffsc_tagfile ? "" : curbuf->b_p_sua;
while (true) {
// if file exists and we didn't already find it
- if ((path_with_url(file_path)
- || (os_path_exists(file_path)
+ if ((path_with_url(file_path.data)
+ || (os_path_exists(file_path.data)
&& (search_ctx->ffsc_find_what == FINDFILE_BOTH
|| ((search_ctx->ffsc_find_what == FINDFILE_DIR)
- == os_isdir(file_path)))))
+ == os_isdir(file_path.data)))))
#ifndef FF_VERBOSE
&& (ff_check_visited(&search_ctx->ffsc_visited_list->ffvl_visited_list,
- file_path, "") == OK)
+ file_path.data, file_path.size, "", 0) == OK)
#endif
) {
#ifdef FF_VERBOSE
if (ff_check_visited(&search_ctx->ffsc_visited_list->ffvl_visited_list,
- file_path, "") == FAIL) {
+ file_path.data, file_path.size, "", 0) == FAIL) {
if (p_verbose >= 5) {
verbose_enter_scroll();
- smsg(0, "Already: %s", file_path);
+ smsg(0, "Already: %s", file_path.data);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
@@ -827,32 +887,37 @@ char *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 (!path_with_url(file_path.data)) {
+ file_path.size = simplify_filename(file_path.data);
}
- if (os_dirname(ff_expand_buffer, MAXPATHL) == OK) {
- p = path_shorten_fname(file_path, ff_expand_buffer);
+
+ if (os_dirname(ff_expand_buffer.data, MAXPATHL) == OK) {
+ ff_expand_buffer.size = strlen(ff_expand_buffer.data);
+ char *p = path_shorten_fname(file_path.data, ff_expand_buffer.data);
if (p != NULL) {
- STRMOVE(file_path, p);
+ memmove(file_path.data, p,
+ (size_t)((file_path.data + file_path.size) - p) + 1); // +1 for NUL
+ file_path.size -= (size_t)(p - file_path.data);
}
}
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
- smsg(0, "HIT: %s", file_path);
+ smsg(0, "HIT: %s", file_path.data);
msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
}
#endif
- return file_path;
+ return file_path.data;
}
// Not found or found already, try next suffix.
if (*suf == NUL) {
break;
}
- assert(MAXPATHL >= len);
- copy_option_part(&suf, file_path + len, MAXPATHL - len, ",");
+ assert(MAXPATHL >= file_path.size);
+ file_path.size += copy_option_part(&suf, file_path.data + file_path.size,
+ MAXPATHL - file_path.size, ",");
}
}
} else {
@@ -863,7 +928,9 @@ char *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.data,
+ rest_of_wildcards.size,
stackp->ffs_level - 1, 0));
}
}
@@ -873,11 +940,11 @@ char *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.data, "**", 2) == 0) {
for (int i = stackp->ffs_filearray_cur;
i < stackp->ffs_filearray_size; i++) {
if (path_fnamecmp(stackp->ffs_filearray[i],
- stackp->ffs_fix_path) == 0) {
+ stackp->ffs_fix_path.data) == 0) {
continue; // don't repush same directory
}
if (!os_isdir(stackp->ffs_filearray[i])) {
@@ -885,7 +952,10 @@ char *vim_findfile(void *search_ctx_arg)
}
ff_push(search_ctx,
ff_create_stack_element(stackp->ffs_filearray[i],
- stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
+ strlen(stackp->ffs_filearray[i]),
+ stackp->ffs_wc_path.data,
+ stackp->ffs_wc_path.size,
+ stackp->ffs_level - 1, 1));
}
}
@@ -895,45 +965,58 @@ char *vim_findfile(void *search_ctx_arg)
// 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.data
&& search_ctx->ffsc_stopdirs_v != NULL && !got_int) {
ff_stack_T *sptr;
// path_end may point to the NUL or the previous path separator
- ptrdiff_t plen = (path_end - search_ctx->ffsc_start_dir) + (*path_end != NUL);
+ ptrdiff_t plen = (path_end - search_ctx->ffsc_start_dir.data) + (*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.data,
(size_t)plen, search_ctx->ffsc_stopdirs_v)) {
break;
}
// cut of last dir
- while (path_end > search_ctx->ffsc_start_dir && vim_ispathsep(*path_end)) {
+ while (path_end > search_ctx->ffsc_start_dir.data && vim_ispathsep(*path_end)) {
path_end--;
}
- while (path_end > search_ctx->ffsc_start_dir && !vim_ispathsep(path_end[-1])) {
+ while (path_end > search_ctx->ffsc_start_dir.data && !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.size = (size_t)(path_end - search_ctx->ffsc_start_dir.data);
path_end--;
- if (*search_ctx->ffsc_start_dir == 0) {
+ if (*search_ctx->ffsc_start_dir.data == NUL) {
break;
}
- if (strlen(search_ctx->ffsc_start_dir) + 1
- + strlen(search_ctx->ffsc_fix_path) >= MAXPATHL) {
+ if (search_ctx->ffsc_start_dir.size + 1
+ + search_ctx->ffsc_fix_path.size >= MAXPATHL) {
goto fail;
}
- STRCPY(file_path, search_ctx->ffsc_start_dir);
- if (!add_pathsep(file_path)) {
+ bool add_sep = !after_pathsep(search_ctx->ffsc_start_dir.data,
+ search_ctx->ffsc_start_dir.data
+ + search_ctx->ffsc_start_dir.size);
+ file_path.size = (size_t)vim_snprintf(file_path.data,
+ MAXPATHL,
+ "%s%s%s",
+ search_ctx->ffsc_start_dir.data,
+ add_sep ? PATHSEPSTR : "",
+ search_ctx->ffsc_fix_path.data);
+ if (file_path.size >= MAXPATHL) {
goto fail;
}
- strcat(file_path, search_ctx->ffsc_fix_path);
// 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.data,
+ file_path.size,
+ search_ctx->ffsc_wc_path.data,
+ search_ctx->ffsc_wc_path.size,
+ search_ctx->ffsc_level, 0);
ff_push(search_ctx, sptr);
} else {
break;
@@ -941,7 +1024,7 @@ char *vim_findfile(void *search_ctx_arg)
}
fail:
- xfree(file_path);
+ xfree(file_path.data);
return NULL;
}
@@ -988,7 +1071,7 @@ static void ff_free_visited_list(ff_visited_T *vl)
/// @return the already visited list for the given filename. If none is found it
/// allocates a new one.
-static ff_visited_list_hdr_T *ff_get_visited_list(char *filename,
+static ff_visited_list_hdr_T *ff_get_visited_list(char *filename, size_t filenamelen,
ff_visited_list_hdr_T **list_headp)
{
ff_visited_list_hdr_T *retptr = NULL;
@@ -1025,7 +1108,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char *filename,
retptr = xmalloc(sizeof(*retptr));
retptr->ffvl_visited_list = NULL;
- retptr->ffvl_filename = xstrdup(filename);
+ retptr->ffvl_filename = xmemdupz(filename, filenamelen);
retptr->ffvl_next = *list_headp;
*list_headp = retptr;
@@ -1074,7 +1157,8 @@ static bool ff_wc_equal(char *s1, char *s2)
///
/// @return FAIL if the given file/dir is already in the list or,
/// OK if it is newly added
-static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_path)
+static int ff_check_visited(ff_visited_T **visited_list, char *fname, size_t fnamelen,
+ char *wc_path, size_t wc_pathlen)
{
ff_visited_T *vp;
bool url = false;
@@ -1083,10 +1167,12 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
// For a URL we only compare the name, otherwise we compare the
// device/inode.
if (path_with_url(fname)) {
- xstrlcpy(ff_expand_buffer, fname, MAXPATHL);
+ xmemcpyz(ff_expand_buffer.data, fname, fnamelen);
+ ff_expand_buffer.size = fnamelen;
url = true;
} else {
- ff_expand_buffer[0] = NUL;
+ ff_expand_buffer.data[0] = NUL;
+ ff_expand_buffer.size = 0;
if (!os_fileid(fname, &file_id)) {
return FAIL;
}
@@ -1094,7 +1180,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
// check against list of already visited files
for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) {
- if ((url && path_fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0)
+ if ((url && path_fnamecmp(vp->ffv_fname, ff_expand_buffer.data) == 0)
|| (!url && vp->file_id_valid
&& os_fileid_equal(&(vp->file_id), &file_id))) {
// are the wildcard parts equal
@@ -1106,7 +1192,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
}
// New file/dir. Add it to the list of visited files/dirs.
- vp = xmalloc(offsetof(ff_visited_T, ffv_fname) + strlen(ff_expand_buffer) + 1);
+ vp = xmalloc(offsetof(ff_visited_T, ffv_fname) + ff_expand_buffer.size + 1);
if (!url) {
vp->file_id_valid = true;
@@ -1114,11 +1200,11 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
vp->ffv_fname[0] = NUL;
} else {
vp->file_id_valid = false;
- STRCPY(vp->ffv_fname, ff_expand_buffer);
+ STRCPY(vp->ffv_fname, ff_expand_buffer.data);
}
if (wc_path != NULL) {
- vp->ffv_wc_path = xstrdup(wc_path);
+ vp->ffv_wc_path = xmemdupz(wc_path, wc_pathlen);
} else {
vp->ffv_wc_path = NULL;
}
@@ -1130,8 +1216,8 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
}
/// create stack element from given path pieces
-static ff_stack_T *ff_create_stack_element(char *fix_part, char *wc_part, int level,
- int star_star_empty)
+static ff_stack_T *ff_create_stack_element(char *fix_part, size_t fix_partlen, char *wc_part,
+ size_t wc_partlen, int level, int star_star_empty)
{
ff_stack_T *stack = xmalloc(sizeof(ff_stack_T));
@@ -1146,13 +1232,15 @@ static ff_stack_T *ff_create_stack_element(char *fix_part, char *wc_part, int le
// the following saves NULL pointer checks in vim_findfile
if (fix_part == NULL) {
fix_part = "";
+ fix_partlen = 0;
}
- stack->ffs_fix_path = xstrdup(fix_part);
+ stack->ffs_fix_path = cbuf_to_string(fix_part, fix_partlen);
if (wc_part == NULL) {
wc_part = "";
+ wc_partlen = 0;
}
- stack->ffs_wc_path = xstrdup(wc_part);
+ stack->ffs_wc_path = cbuf_to_string(wc_part, wc_partlen);
return stack;
}
@@ -1190,9 +1278,9 @@ static void ff_free_stack_element(ff_stack_T *const stack_ptr)
return;
}
- // free handles possible NULL pointers
- xfree(stack_ptr->ffs_fix_path);
- xfree(stack_ptr->ffs_wc_path);
+ // API_CLEAR_STRING handles possible NULL pointers
+ API_CLEAR_STRING(stack_ptr->ffs_fix_path);
+ API_CLEAR_STRING(stack_ptr->ffs_wc_path);
if (stack_ptr->ffs_filearray != NULL) {
FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray);
@@ -1211,34 +1299,28 @@ static void ff_clear(ff_search_ctx_T *search_ctx)
ff_free_stack_element(sptr);
}
- xfree(search_ctx->ffsc_file_to_search);
- xfree(search_ctx->ffsc_start_dir);
- xfree(search_ctx->ffsc_fix_path);
- xfree(search_ctx->ffsc_wc_path);
-
if (search_ctx->ffsc_stopdirs_v != NULL) {
int i = 0;
- while (search_ctx->ffsc_stopdirs_v[i] != NULL) {
- xfree(search_ctx->ffsc_stopdirs_v[i]);
+ while (search_ctx->ffsc_stopdirs_v[i].data != NULL) {
+ xfree(search_ctx->ffsc_stopdirs_v[i].data);
i++;
}
- xfree(search_ctx->ffsc_stopdirs_v);
+ XFREE_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;
+ API_CLEAR_STRING(search_ctx->ffsc_file_to_search);
+ API_CLEAR_STRING(search_ctx->ffsc_start_dir);
+ API_CLEAR_STRING(search_ctx->ffsc_fix_path);
+ API_CLEAR_STRING(search_ctx->ffsc_wc_path);
search_ctx->ffsc_level = 0;
}
/// check if the given path is in the stopdirs
///
/// @return true if yes else false
-static bool ff_path_in_stoplist(char *path, size_t path_len, char **stopdirs_v)
+static bool ff_path_in_stoplist(char *path, size_t path_len, String *stopdirs_v)
{
// eat up trailing path separators, except the first
while (path_len > 1 && vim_ispathsep(path[path_len - 1])) {
@@ -1250,13 +1332,13 @@ static bool ff_path_in_stoplist(char *path, size_t path_len, char **stopdirs_v)
return true;
}
- for (int i = 0; stopdirs_v[i] != NULL; i++) {
+ for (int i = 0; stopdirs_v[i].data != 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 (path_fnamencmp(stopdirs_v[i], path, path_len) == 0
- && (strlen(stopdirs_v[i]) <= path_len
- || vim_ispathsep(stopdirs_v[i][path_len]))) {
+ if (path_fnamencmp(stopdirs_v[i].data, path, path_len) == 0
+ && (stopdirs_v[i].size <= path_len
+ || vim_ispathsep(stopdirs_v[i].data[path_len]))) {
return true;
}
}
@@ -1307,7 +1389,7 @@ char *find_file_in_path(char *ptr, size_t len, int options, int first, char *rel
#if defined(EXITFREE)
void free_findfile(void)
{
- XFREE_CLEAR(ff_expand_buffer);
+ API_CLEAR_STRING(ff_expand_buffer);
}
#endif
@@ -1351,7 +1433,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
static char *dir;
static bool did_findfile_init = false;
char *file_name = NULL;
- char *buf = NULL;
+ static size_t file_to_findlen = 0;
if (rel_fname != NULL && path_with_url(rel_fname)) {
// Do not attempt to search "relative" to a URL. #6009
@@ -1370,12 +1452,15 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
ptr[len] = save_char;
xfree(*file_to_find);
- *file_to_find = xstrdup(NameBuff);
+ file_to_findlen = strlen(NameBuff);
+ *file_to_find = xmemdupz(NameBuff, file_to_findlen);
if (options & FNAME_UNESC) {
// Change all "\ " to " ".
for (ptr = *file_to_find; *ptr != NUL; ptr++) {
if (ptr[0] == '\\' && ptr[1] == ' ') {
- memmove(ptr, ptr + 1, strlen(ptr));
+ memmove(ptr, ptr + 1,
+ (size_t)((*file_to_find + file_to_findlen) - (ptr + 1)) + 1);
+ file_to_findlen--;
}
}
}
@@ -1402,42 +1487,48 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
// filename on the first call.
if (first == true) {
if (path_with_url(*file_to_find)) {
- file_name = xstrdup(*file_to_find);
+ file_name = xmemdupz(*file_to_find, file_to_findlen);
goto theend;
}
+ size_t rel_fnamelen = rel_fname != NULL ? strlen(rel_fname) : 0;
+
// When FNAME_REL flag given first use the directory of the file.
// Otherwise or when this fails use the current directory.
for (int run = 1; run <= 2; run++) {
- size_t l = strlen(*file_to_find);
+ size_t l = file_to_findlen;
if (run == 1
&& rel_to_curdir
&& (options & FNAME_REL)
&& rel_fname != NULL
- && strlen(rel_fname) + l < MAXPATHL) {
- STRCPY(NameBuff, rel_fname);
- STRCPY(path_tail(NameBuff), *file_to_find);
- l = strlen(NameBuff);
+ && rel_fnamelen + l < MAXPATHL) {
+ l = (size_t)vim_snprintf(NameBuff,
+ MAXPATHL,
+ "%.*s%s",
+ (int)(path_tail(rel_fname) - rel_fname),
+ rel_fname,
+ *file_to_find);
+ assert(l < MAXPATHL);
} else {
STRCPY(NameBuff, *file_to_find);
run = 2;
}
// When the file doesn't exist, try adding parts of 'suffixesadd'.
- buf = suffixes;
+ char *suffix = suffixes;
while (true) {
if ((os_path_exists(NameBuff)
&& (find_what == FINDFILE_BOTH
|| ((find_what == FINDFILE_DIR)
== os_isdir(NameBuff))))) {
- file_name = xstrdup(NameBuff);
+ file_name = xmemdupz(NameBuff, l);
goto theend;
}
- if (*buf == NUL) {
+ if (*suffix == NUL) {
break;
}
assert(MAXPATHL >= l);
- copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
+ l += copy_option_part(&suffix, NameBuff + l, MAXPATHL - l, ",");
}
}
}
@@ -1470,15 +1561,15 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
break;
}
- buf = xmalloc(MAXPATHL);
+ char *buf = xmalloc(MAXPATHL);
// 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) {
@@ -1618,19 +1709,24 @@ char *file_name_in_line(char *line, int col, int options, int count, char *rel_f
}
if (file_lnum != NULL) {
- const char *line_english = " line ";
- const char *line_transl = _(line_msg);
+ const 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().
char *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 (!isdigit((uint8_t)(*p))) {
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 3df77571a1..6c6a6f58c0 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -816,13 +816,13 @@ static int find_previous_pathsep(char *path, char **psep)
static bool is_unique(char *maybe_unique, garray_T *gap, int i)
FUNC_ATTR_NONNULL_ALL
{
+ size_t candidate_len = strlen(maybe_unique);
char **other_paths = gap->ga_data;
for (int j = 0; j < gap->ga_len; j++) {
if (j == i) {
continue; // don't compare it with itself
}
- size_t candidate_len = strlen(maybe_unique);
size_t other_path_len = strlen(other_paths[j]);
if (other_path_len < candidate_len) {
continue; // it's different when it's shorter
@@ -849,9 +849,10 @@ static void expand_path_option(char *curdir, char *path_option, garray_T *gap)
FUNC_ATTR_NONNULL_ALL
{
char *buf = xmalloc(MAXPATHL);
+ size_t curdirlen = 0;
while (*path_option != NUL) {
- copy_option_part(&path_option, buf, MAXPATHL, " ,");
+ size_t buflen = copy_option_part(&path_option, buf, MAXPATHL, " ,");
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) {
// Relative to current buffer:
@@ -861,34 +862,40 @@ static void expand_path_option(char *curdir, char *path_option, garray_T *gap)
continue;
}
char *p = path_tail(curbuf->b_ffname);
- size_t len = (size_t)(p - curbuf->b_ffname);
- if (len + strlen(buf) >= MAXPATHL) {
+ size_t plen = (size_t)(p - curbuf->b_ffname);
+ if (plen + strlen(buf) >= MAXPATHL) {
continue;
}
if (buf[1] == NUL) {
- buf[len] = NUL;
+ buf[plen] = NUL;
} else {
- STRMOVE(buf + len, buf + 2);
+ memmove(buf + plen, buf + 2, (buflen - 2) + 1); // +1 for NUL
}
- memmove(buf, curbuf->b_ffname, len);
- simplify_filename(buf);
+ memmove(buf, curbuf->b_ffname, plen);
+ buflen = simplify_filename(buf);
} else if (buf[0] == NUL) {
STRCPY(buf, curdir); // relative to current directory
+ if (curdirlen == 0) {
+ curdirlen = strlen(curdir);
+ }
+ buflen = curdirlen;
} else if (path_with_url(buf)) {
continue; // URL can't be used here
} else if (!path_is_absolute(buf)) {
// Expand relative path to their full path equivalent
- size_t len = strlen(curdir);
- if (len + strlen(buf) + 3 > MAXPATHL) {
+ if (curdirlen == 0) {
+ curdirlen = strlen(curdir);
+ }
+ if (curdirlen + buflen + 3 > MAXPATHL) {
continue;
}
- STRMOVE(buf + len + 1, buf);
+ 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);
}
- GA_APPEND(char *, gap, xstrdup(buf));
+ GA_APPEND(char *, gap, xmemdupz(buf, buflen));
}
xfree(buf);
@@ -959,7 +966,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
char *file_pattern = xmalloc(len + 2);
file_pattern[0] = '*';
file_pattern[1] = NUL;
- strcat(file_pattern, pattern);
+ STRCPY(file_pattern + 1, pattern);
char *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, false);
xfree(file_pattern);
if (pat == NULL) {
@@ -987,7 +994,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
bool is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0
&& curdir[dir_end - path] == NUL;
if (is_in_curdir) {
- in_curdir[i] = xstrdup(path);
+ in_curdir[i] = xmemdupz(path, len);
}
// Shorten the filename while maintaining its uniqueness
@@ -1012,7 +1019,8 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
&& is_unique(pathsep_p + 1, gap, i)
&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) {
sort_again = true;
- memmove(path, pathsep_p + 1, strlen(pathsep_p));
+ memmove(path, pathsep_p + 1,
+ (size_t)((path + len) - (pathsep_p + 1)) + 1); // +1 for NUL
break;
}
}
@@ -1031,9 +1039,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
// c:\file.txt c:\ .\file.txt
short_name = path_shorten_fname(path, curdir);
if (short_name != NULL && short_name > path + 1) {
- STRCPY(path, ".");
- add_pathsep(path);
- STRMOVE(path + strlen(path), short_name);
+ vim_snprintf(path, MAXPATHL, ".%s%s", PATHSEPSTR, short_name);
}
}
os_breakcheck();
@@ -1041,7 +1047,6 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
// Shorten filenames in /in/current/directory/{filename}
for (int i = 0; i < gap->ga_len && !got_int; i++) {
- char *rel_path;
char *path = in_curdir[i];
if (path == NULL) {
@@ -1059,10 +1064,10 @@ static void uniquefy_paths(garray_T *gap, char *pattern, char *path_option)
continue;
}
- rel_path = xmalloc(strlen(short_name) + strlen(PATHSEPSTR) + 2);
- STRCPY(rel_path, ".");
- add_pathsep(rel_path);
- strcat(rel_path, short_name);
+ size_t rel_pathsize = 1 + STRLEN_LITERAL(PATHSEPSTR) + strlen(short_name) + 1;
+ char *rel_path = xmalloc(rel_pathsize);
+
+ vim_snprintf(rel_path, rel_pathsize, ".%s%s", PATHSEPSTR, short_name);
xfree(fnames[i]);
fnames[i] = rel_path;
@@ -1518,7 +1523,7 @@ void addfile(garray_T *gap, char *f, int flags)
// its simplest form by stripping out unneeded components, if any. The
// resulting file name is simplified in place and will either be the same
// length as that supplied, or shorter.
-void simplify_filename(char *filename)
+size_t simplify_filename(char *filename)
FUNC_ATTR_NONNULL_ALL
{
int components = 0;
@@ -1539,10 +1544,12 @@ void simplify_filename(char *filename)
} while (vim_ispathsep(*p));
}
char *start = p; // remember start after "c:/" or "/" or "///"
+ char *p_end = p + strlen(p); // point to NUL at end of string "p"
#ifdef UNIX
// Posix says that "//path" is unchanged but "///path" is "/path".
if (start > filename + 2) {
- STRMOVE(filename + 1, p);
+ 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
@@ -1551,7 +1558,8 @@ void simplify_filename(char *filename)
// At this point "p" is pointing to the char following a single "/"
// or "p" is at the "start" of the (absolute or relative) path name.
if (vim_ispathsep(*p)) {
- STRMOVE(p, p + 1); // remove duplicate "/"
+ 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) {
@@ -1569,7 +1577,8 @@ void simplify_filename(char *filename)
} else if (p > start) {
p--; // strip preceding path separator
}
- STRMOVE(p, tail);
+ memmove(p, tail, (size_t)(p_end - tail) + 1);
+ p_end -= (size_t)(tail - p);
}
} else if (p[0] == '.' && p[1] == '.'
&& (vim_ispathsep(p[2]) || p[2] == NUL)) {
@@ -1667,16 +1676,19 @@ void simplify_filename(char *filename)
if (p > start && tail[-1] == '.') {
p--;
}
- STRMOVE(p, tail); // strip previous component
+ 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 "../"
+ } else if (p == start && !relative) { // leading "/.." or "/../"
+ 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 "./"
+ if (p == start + 2 && p[-2] == '.') { // leading "./../"
+ memmove(p - 2, p, (size_t)(p_end - p) + 1); // strip leading "./"
+ p_end -= 2;
tail -= 2;
}
p = tail; // skip to char after ".." or "../"
@@ -1686,6 +1698,8 @@ void simplify_filename(char *filename)
p = (char *)path_next_component(p);
}
} while (*p != NUL);
+
+ return (size_t)(p_end - filename);
}
/// Checks for a Windows drive letter ("C:/") at the start of the path.
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index c676b00986..c99a8083e4 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2556,7 +2556,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
STRMOVE(filename + 1, filename);
*filename++ = NUL;
- tnp->tn_search_ctx = vim_findfile_init(buf, filename,
+ 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