0
0
mirror of https://github.com/vim/vim.git synced 2025-08-26 20:03:41 -04:00

patch 9.1.1050: too many strlen() calls in os_unix.c

Problem:  too many strlen() calls in os_unix.c
Solution: refactor os_unix.c and remove calls to strlen()
          (John Marriott)

closes: #16496

Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
John Marriott 2025-01-23 20:05:29 +01:00 committed by Christian Brabandt
parent f400a0cc41
commit efc41a5958
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
2 changed files with 120 additions and 77 deletions

View File

@ -1835,11 +1835,13 @@ may_restore_clipboard(void)
void void
ex_xrestore(exarg_T *eap) ex_xrestore(exarg_T *eap)
{ {
if (eap->arg != NULL && STRLEN(eap->arg) > 0) size_t arglen;
if (eap->arg != NULL && (arglen = STRLEN(eap->arg)) > 0)
{ {
if (xterm_display_allocated) if (xterm_display_allocated)
vim_free(xterm_display); vim_free(xterm_display);
xterm_display = (char *)vim_strsave(eap->arg); xterm_display = (char *)vim_strnsave(eap->arg, arglen);
xterm_display_allocated = TRUE; xterm_display_allocated = TRUE;
} }
smsg(_("restoring display %s"), xterm_display == NULL smsg(_("restoring display %s"), xterm_display == NULL
@ -2625,7 +2627,7 @@ strerror(int err)
if (err > 0 && err < sys_nerr) if (err > 0 && err < sys_nerr)
return (sys_errlist[err]); return (sys_errlist[err]);
sprintf(er, "Error %d", err); snprintf(er, sizeof(er), "Error %d", err);
return er; return er;
} }
#endif #endif
@ -2662,7 +2664,7 @@ mch_FullName(
int len, int len,
int force) // also expand when already absolute path int force) // also expand when already absolute path
{ {
int l; int buflen = 0;
#ifdef HAVE_FCHDIR #ifdef HAVE_FCHDIR
int fd = -1; int fd = -1;
static int dont_fchdir = FALSE; // TRUE when fchdir() doesn't work static int dont_fchdir = FALSE; // TRUE when fchdir() doesn't work
@ -2778,6 +2780,8 @@ mch_FullName(
} }
if (p != NULL) if (p != NULL)
{ {
int l;
#ifdef HAVE_FCHDIR #ifdef HAVE_FCHDIR
if (fd >= 0) if (fd >= 0)
{ {
@ -2800,23 +2804,29 @@ mch_FullName(
close(fd); close(fd);
#endif #endif
l = STRLEN(buf); buflen = (int)STRLEN(buf);
if (l >= len - 1) if (buflen >= len - 1)
retval = FAIL; // no space for trailing "/" retval = FAIL; // no space for trailing "/"
#ifndef VMS #ifndef VMS
else if (l > 0 && buf[l - 1] != '/' && *fname != NUL else if (buflen > 0 && buf[buflen - 1] != PATHSEP && *fname != NUL
&& STRCMP(fname, ".") != 0) && STRCMP(fname, ".") != 0)
STRCAT(buf, "/"); {
STRCPY(buf + buflen, PATHSEPSTR);
buflen += STRLEN_LITERAL(PATHSEPSTR);
}
#endif #endif
} }
if (buflen == 0)
buflen = (int)STRLEN(buf);
// Catch file names which are too long. // Catch file names which are too long.
if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len) if (retval == FAIL || (int)(buflen + STRLEN(fname)) >= len)
return FAIL; return FAIL;
// Do not append ".", "/dir/." is equal to "/dir". // Do not append ".", "/dir/." is equal to "/dir".
if (STRCMP(fname, ".") != 0) if (STRCMP(fname, ".") != 0)
STRCAT(buf, fname); STRCPY(buf + buflen, fname);
return OK; return OK;
} }
@ -2850,6 +2860,7 @@ fname_case(
{ {
struct stat st; struct stat st;
char_u *slash, *tail; char_u *slash, *tail;
size_t taillen;
DIR *dirp; DIR *dirp;
struct dirent *dp; struct dirent *dp;
@ -2874,12 +2885,13 @@ fname_case(
if (dirp == NULL) if (dirp == NULL)
return; return;
taillen = STRLEN(tail);
while ((dp = readdir(dirp)) != NULL) while ((dp = readdir(dirp)) != NULL)
{ {
// Only accept names that differ in case and are the same byte // Only accept names that differ in case and are the same byte
// length. TODO: accept different length name. // length. TODO: accept different length name.
if (STRICMP(tail, dp->d_name) == 0 if (STRICMP(tail, dp->d_name) == 0
&& STRLEN(tail) == STRLEN(dp->d_name)) && taillen == STRLEN(dp->d_name))
{ {
char_u newname[MAXPATHL + 1]; char_u newname[MAXPATHL + 1];
struct stat st2; struct stat st2;
@ -3054,8 +3066,7 @@ mch_copy_sec(char_u *from_file, char_u *to_file)
if (size <= 0) if (size <= 0)
return; return;
for (index = 0 ; index < (int)(sizeof(smack_copied_attributes) for (index = 0 ; index < (int)ARRAY_LENGTH(smack_copied_attributes); index++)
/ sizeof(smack_copied_attributes)[0]) ; index++)
{ {
// get the name of the attribute to copy // get the name of the attribute to copy
name = smack_copied_attributes[index]; name = smack_copied_attributes[index];
@ -3220,12 +3231,19 @@ mch_get_acl(char_u *fname UNUSED)
vim_acl_solaris_T *aclent; vim_acl_solaris_T *aclent;
aclent = malloc(sizeof(vim_acl_solaris_T)); aclent = malloc(sizeof(vim_acl_solaris_T));
if (aclent == NULL)
return NULL;
if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0) if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
{ {
free(aclent); free(aclent);
return NULL; return NULL;
} }
aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t)); aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
if (aclent->acl_entry == NULL)
{
free(aclent);
return NULL;
}
if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0) if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
{ {
free(aclent->acl_entry); free(aclent->acl_entry);
@ -3240,13 +3258,15 @@ mch_get_acl(char_u *fname UNUSED)
aclsize = sizeof(struct acl); aclsize = sizeof(struct acl);
aclent = malloc(aclsize); aclent = malloc(aclsize);
if (aclent == NULL)
return NULL;
if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0) if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
{ {
if (errno == ENOSPC) if (errno == ENOSPC)
{ {
aclsize = aclent->acl_len; aclsize = aclent->acl_len;
aclent = realloc(aclent, aclsize); aclent = realloc(aclent, aclsize);
if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0) if (aclent == NULL || statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
{ {
free(aclent); free(aclent);
return NULL; return NULL;
@ -3399,7 +3419,11 @@ executable_file(char_u *name)
mch_can_exe(char_u *name, char_u **path, int use_path) mch_can_exe(char_u *name, char_u **path, int use_path)
{ {
char_u *buf; char_u *buf;
size_t bufsize;
size_t buflen;
char_u *p, *e; char_u *p, *e;
char_u *p_end;
size_t elen;
int retval; int retval;
// When "use_path" is false and if it's an absolute or relative path don't // When "use_path" is false and if it's an absolute or relative path don't
@ -3425,7 +3449,9 @@ mch_can_exe(char_u *name, char_u **path, int use_path)
p = (char_u *)getenv("PATH"); p = (char_u *)getenv("PATH");
if (p == NULL || *p == NUL) if (p == NULL || *p == NUL)
return -1; return -1;
buf = alloc(STRLEN(name) + STRLEN(p) + 2); p_end = p + STRLEN(p);
bufsize = STRLEN(name) + (size_t)(p_end - p) + 2;
buf = alloc(bufsize);
if (buf == NULL) if (buf == NULL)
return -1; return -1;
@ -3437,15 +3463,18 @@ mch_can_exe(char_u *name, char_u **path, int use_path)
{ {
e = (char_u *)strchr((char *)p, ':'); e = (char_u *)strchr((char *)p, ':');
if (e == NULL) if (e == NULL)
e = p + STRLEN(p); e = p_end;
if (e - p <= 1) // empty entry means current dir elen = (size_t)(e - p);
STRCPY(buf, "./"); if (elen <= 1) // empty entry means current dir
else
{ {
vim_strncpy(buf, p, e - p); p = (char_u *)"./";
add_pathsep(buf); elen = STRLEN_LITERAL("./");
} }
STRCAT(buf, name); buflen = vim_snprintf((char *)buf, bufsize, "%.*s%s%s",
(int)elen,
p,
(after_pathsep(p, p + elen)) ? "" : PATHSEPSTR,
name);
retval = executable_file(buf); retval = executable_file(buf);
if (retval == 1) if (retval == 1)
{ {
@ -3454,7 +3483,7 @@ mch_can_exe(char_u *name, char_u **path, int use_path)
if (buf[0] != '/') if (buf[0] != '/')
*path = FullName_save(buf, TRUE); *path = FullName_save(buf, TRUE);
else else
*path = vim_strsave(buf); *path = vim_strnsave(buf, buflen);
} }
break; break;
} }
@ -5233,13 +5262,13 @@ mch_call_shell_fork(
linenr_T lnum = curbuf->b_op_start.lnum; linenr_T lnum = curbuf->b_op_start.lnum;
int written = 0; int written = 0;
char_u *lp = ml_get(lnum); char_u *lp = ml_get(lnum);
size_t l; size_t lplen = (size_t)ml_get_len(lnum);
close(fromshell_fd); close(fromshell_fd);
for (;;) for (;;)
{ {
l = STRLEN(lp + written); lplen -= written;
if (l == 0) if (lplen == 0)
len = 0; len = 0;
else if (lp[written] == NL) else if (lp[written] == NL)
// NL -> NUL translation // NL -> NUL translation
@ -5249,10 +5278,10 @@ mch_call_shell_fork(
char_u *s = vim_strchr(lp + written, NL); char_u *s = vim_strchr(lp + written, NL);
len = write(toshell_fd, (char *)lp + written, len = write(toshell_fd, (char *)lp + written,
s == NULL ? l s == NULL ? lplen
: (size_t)(s - (lp + written))); : (size_t)(s - (lp + written)));
} }
if (len == (int)l) if (len == (int)lplen)
{ {
// Finished a line, add a NL, unless this line // Finished a line, add a NL, unless this line
// should not have one. // should not have one.
@ -5272,6 +5301,7 @@ mch_call_shell_fork(
break; break;
} }
lp = ml_get(lnum); lp = ml_get(lnum);
lplen = ml_get_len(lnum);
written = 0; written = 0;
} }
else if (len > 0) else if (len > 0)
@ -6089,14 +6119,14 @@ get_signal_name(int sig)
char_u numbuf[NUMBUFLEN]; char_u numbuf[NUMBUFLEN];
if (sig == SIGKILL) if (sig == SIGKILL)
return vim_strsave((char_u *)"kill"); return vim_strnsave((char_u *)"kill", STRLEN_LITERAL("kill"));
for (i = 0; signal_info[i].sig != -1; i++) for (i = 0; signal_info[i].sig != -1; i++)
if (sig == signal_info[i].sig) if (sig == signal_info[i].sig)
return strlow_save((char_u *)signal_info[i].name); return strlow_save((char_u *)signal_info[i].name);
vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig); i = vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig);
return vim_strsave(numbuf); return vim_strnsave(numbuf, i);
} }
char * char *
@ -6852,7 +6882,9 @@ mch_expand_wildcards(
*/ */
int j; int j;
char_u *tempname; char_u *tempname;
size_t tempnamelen;
char_u *command; char_u *command;
size_t commandlen;
FILE *fd; FILE *fd;
char_u *buffer; char_u *buffer;
#define STYLE_ECHO 0 // use "echo", the default #define STYLE_ECHO 0 // use "echo", the default
@ -6866,10 +6898,14 @@ mch_expand_wildcards(
int check_spaces; int check_spaces;
static int did_find_nul = FALSE; static int did_find_nul = FALSE;
int ampersand = FALSE; int ampersand = FALSE;
// vimglob() function to define for Posix shell #define STRING_INIT(s) \
static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; {(char_u *)(s), STRLEN_LITERAL(s)}
// vimglob() function with globstar setting enabled, only for bash >= 4.X // vimglob() function to define for Posix shell
static char *sh_globstar_opt = "[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; "; static string_T sh_vimglob_func = STRING_INIT("vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >");
// vimglob() function with globstar setting enabled, only for bash >= 4.X
static string_T sh_globstar_opt = STRING_INIT("[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; ");
#undef STRING_INIT
*num_file = 0; // default: no files found *num_file = 0; // default: no files found
*file = NULL; *file = NULL;
@ -6943,12 +6979,12 @@ mch_expand_wildcards(
// Compute the length of the command. We need 2 extra bytes: for the // Compute the length of the command. We need 2 extra bytes: for the
// optional '&' and for the NUL. // optional '&' and for the NUL.
// Worst case: "unset nonomatch; print -N >" plus two is 29 // Worst case: "unset nonomatch; print -N >" plus two is 29
len = STRLEN(tempname) + 29; tempnamelen = STRLEN(tempname);
len = tempnamelen + 29;
if (shell_style == STYLE_VIMGLOB) if (shell_style == STYLE_VIMGLOB)
len += STRLEN(sh_vimglob_func); len += sh_vimglob_func.length;
else if (shell_style == STYLE_GLOBSTAR) else if (shell_style == STYLE_GLOBSTAR)
len += STRLEN(sh_vimglob_func) len += sh_vimglob_func.length + sh_globstar_opt.length;
+ STRLEN(sh_globstar_opt);
for (i = 0; i < num_pat; ++i) for (i = 0; i < num_pat; ++i)
{ {
@ -6985,63 +7021,62 @@ mch_expand_wildcards(
if (shell_style == STYLE_BT) if (shell_style == STYLE_BT)
{ {
// change `command; command& ` to (command; command ) // change `command; command& ` to (command; command )
STRCPY(command, "("); commandlen = vim_snprintf((char *)command, len, "(%s)>%s", pat[0] + 1, tempname); // +1 to exclude first backtick
STRCAT(command, pat[0] + 1); // exclude first backtick
p = command + STRLEN(command) - 1; p = (char_u *)strstr((char *)command, ")>");
*p-- = ')'; // remove last backtick if (p == NULL)
while (p > command && VIM_ISWHITE(*p))
--p;
if (*p == '&') // remove trailing '&'
{ {
ampersand = TRUE; ; // can't happen ;-)
*p = ' '; }
else
{
--p;
while (p > command && VIM_ISWHITE(*p))
--p;
if (*p == '`') // remove backtick
*p = ' ';
--p;
while (p > command && VIM_ISWHITE(*p))
--p;
if (*p == '&') // remove ampersand
{
ampersand = TRUE;
*p = ' ';
}
} }
STRCAT(command, ">");
} }
else else
{ {
STRCPY(command, "");
if (shell_style == STYLE_GLOB) if (shell_style == STYLE_GLOB)
{ {
// Assume the nonomatch option is valid only for csh like shells, // Assume the nonomatch option is valid only for csh like shells,
// otherwise, this may set the positional parameters for the shell, // otherwise, this may set the positional parameters for the shell,
// e.g. "$*". // e.g. "$*".
if (flags & EW_NOTFOUND) commandlen = vim_snprintf((char *)command, len, "%sset nonomatch; glob >%s",
STRCAT(command, "set nonomatch; "); (flags & EW_NOTFOUND) ? "" : "un", tempname);
else
STRCAT(command, "unset nonomatch; ");
} }
if (shell_style == STYLE_GLOB)
STRCAT(command, "glob >");
else if (shell_style == STYLE_PRINT) else if (shell_style == STYLE_PRINT)
STRCAT(command, "print -N >"); commandlen = vim_snprintf((char *)command, len, "print -N >%s", tempname);
else if (shell_style == STYLE_VIMGLOB) else if (shell_style == STYLE_VIMGLOB)
STRCAT(command, sh_vimglob_func); commandlen = vim_snprintf((char *)command, len, "%s%s", sh_vimglob_func.string, tempname);
else if (shell_style == STYLE_GLOBSTAR) else if (shell_style == STYLE_GLOBSTAR)
{ commandlen = vim_snprintf((char *)command, len, "%s%s%s", sh_globstar_opt.string,
STRCAT(command, sh_globstar_opt); sh_vimglob_func.string, tempname);
STRCAT(command, sh_vimglob_func);
}
else else
STRCAT(command, "echo >"); commandlen = vim_snprintf((char *)command, len, "echo >%s", tempname);
}
STRCAT(command, tempname);
if (shell_style != STYLE_BT)
for (i = 0; i < num_pat; ++i) for (i = 0; i < num_pat; ++i)
{ {
// When using system() always add extra quotes, because the shell // When using system() always add extra quotes, because the shell
// is started twice. Otherwise put a backslash before special // is started twice. Otherwise put a backslash before special
// characters, except inside ``. // characters, except inside ``.
#ifdef USE_SYSTEM #ifdef USE_SYSTEM
STRCAT(command, " \""); commandlen += vim_snprintf((char *)command + commandlen, len, " \"%s\"", pat[i]);
STRCAT(command, pat[i]);
STRCAT(command, "\"");
#else #else
int intick = FALSE; int intick = FALSE;
p = command + STRLEN(command); p = command + commandlen;
*p++ = ' '; *p++ = ' ';
for (j = 0; pat[i][j] != NUL; ++j) for (j = 0; pat[i][j] != NUL; ++j)
{ {
@ -7070,12 +7105,14 @@ mch_expand_wildcards(
*p++ = pat[i][j]; *p++ = pat[i][j];
} }
*p = NUL; *p = NUL;
commandlen = (size_t)(p - command);
#endif #endif
} }
}
if (flags & EW_SILENT) if (flags & EW_SILENT)
show_shell_mess = FALSE; show_shell_mess = FALSE;
if (ampersand) if (ampersand)
STRCAT(command, "&"); // put the '&' after the redirection STRCPY(command + commandlen, "&"); // put the '&' after the redirection
/* /*
* Using zsh -G: If a pattern has no matches, it is just deleted from * Using zsh -G: If a pattern has no matches, it is just deleted from
@ -8133,7 +8170,8 @@ do_xterm_trace(void)
char_u buf[50]; char_u buf[50];
char_u *strp; char_u *strp;
long got_hints; long got_hints;
static char_u *mouse_code; static char_u *mouse_code = NULL;
static size_t mouse_codelen = 0;
static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER}; static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
static int prev_row = 0, prev_col = 0; static int prev_row = 0, prev_col = 0;
static XSizeHints xterm_hints; static XSizeHints xterm_hints;
@ -8156,6 +8194,8 @@ do_xterm_trace(void)
// Rely on the same mouse code for the duration of this // Rely on the same mouse code for the duration of this
mouse_code = find_termcode(mouse_name); mouse_code = find_termcode(mouse_name);
if (mouse_code != NULL)
mouse_codelen = STRLEN(mouse_code);
prev_row = mouse_row; prev_row = mouse_row;
prev_col = mouse_col; prev_col = mouse_col;
xterm_trace = 2; xterm_trace = 2;
@ -8174,7 +8214,8 @@ do_xterm_trace(void)
xterm_hints.x = 2; xterm_hints.x = 2;
return TRUE; return TRUE;
} }
if (mouse_code == NULL || STRLEN(mouse_code) > 45)
if (mouse_code == NULL || mouse_codelen > 45)
{ {
xterm_trace = 0; xterm_trace = 0;
return FALSE; return FALSE;
@ -8189,12 +8230,12 @@ do_xterm_trace(void)
return TRUE; return TRUE;
STRCPY(buf, mouse_code); STRCPY(buf, mouse_code);
strp = buf + STRLEN(buf); strp = buf + mouse_codelen;
*strp++ = (xterm_button | MOUSE_DRAG) & ~0x20; *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
*strp++ = (char_u)(col + ' ' + 1); *strp++ = (char_u)(col + ' ' + 1);
*strp++ = (char_u)(row + ' ' + 1); *strp++ = (char_u)(row + ' ' + 1);
*strp = 0; *strp = NUL;
add_to_input_buf(buf, STRLEN(buf)); add_to_input_buf(buf, strp - buf);
prev_row = row; prev_row = row;
prev_col = col; prev_col = col;

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1050,
/**/ /**/
1049, 1049,
/**/ /**/