patch 9.1.1050: too many strlen() calls in os_unix.c Commit: https://github.com/vim/vim/commit/efc41a5958bf25b352e0916af5f57dafbbb44f17 Author: John Marriott <basil...@internode.on.net> Date: Thu Jan 23 20:05:29 2025 +0100
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 <basil...@internode.on.net> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/os_unix.c b/src/os_unix.c index dc518fc67..95b21d297 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1835,11 +1835,13 @@ may_restore_clipboard(void) void 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) vim_free(xterm_display); - xterm_display = (char *)vim_strsave(eap->arg); + xterm_display = (char *)vim_strnsave(eap->arg, arglen); xterm_display_allocated = TRUE; } smsg(_("restoring display %s"), xterm_display == NULL @@ -2625,7 +2627,7 @@ strerror(int err) if (err > 0 && err < sys_nerr) return (sys_errlist[err]); - sprintf(er, "Error %d", err); + snprintf(er, sizeof(er), "Error %d", err); return er; } #endif @@ -2662,7 +2664,7 @@ mch_FullName( int len, int force) // also expand when already absolute path { - int l; + int buflen = 0; #ifdef HAVE_FCHDIR int fd = -1; static int dont_fchdir = FALSE; // TRUE when fchdir() doesn't work @@ -2778,6 +2780,8 @@ mch_FullName( } if (p != NULL) { + int l; + #ifdef HAVE_FCHDIR if (fd >= 0) { @@ -2800,23 +2804,29 @@ mch_FullName( close(fd); #endif - l = STRLEN(buf); - if (l >= len - 1) + buflen = (int)STRLEN(buf); + if (buflen >= len - 1) retval = FAIL; // no space for trailing "/" #ifndef VMS - else if (l > 0 && buf[l - 1] != '/' && *fname != NUL + else if (buflen > 0 && buf[buflen - 1] != PATHSEP && *fname != NUL && STRCMP(fname, ".") != 0) - STRCAT(buf, "/"); + { + STRCPY(buf + buflen, PATHSEPSTR); + buflen += STRLEN_LITERAL(PATHSEPSTR); + } #endif } + if (buflen == 0) + buflen = (int)STRLEN(buf); + // 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; // Do not append ".", "/dir/." is equal to "/dir". if (STRCMP(fname, ".") != 0) - STRCAT(buf, fname); + STRCPY(buf + buflen, fname); return OK; } @@ -2850,6 +2860,7 @@ fname_case( { struct stat st; char_u *slash, *tail; + size_t taillen; DIR *dirp; struct dirent *dp; @@ -2874,12 +2885,13 @@ fname_case( if (dirp == NULL) return; + taillen = STRLEN(tail); while ((dp = readdir(dirp)) != NULL) { // Only accept names that differ in case and are the same byte // length. TODO: accept different length name. if (STRICMP(tail, dp->d_name) == 0 - && STRLEN(tail) == STRLEN(dp->d_name)) + && taillen == STRLEN(dp->d_name)) { char_u newname[MAXPATHL + 1]; struct stat st2; @@ -3054,8 +3066,7 @@ mch_copy_sec(char_u *from_file, char_u *to_file) if (size <= 0) return; - for (index = 0 ; index < (int)(sizeof(smack_copied_attributes) - / sizeof(smack_copied_attributes)[0]) ; index++) + for (index = 0 ; index < (int)ARRAY_LENGTH(smack_copied_attributes); index++) { // get the name of the attribute to copy name = smack_copied_attributes[index]; @@ -3220,12 +3231,19 @@ mch_get_acl(char_u *fname UNUSED) vim_acl_solaris_T *aclent; aclent = malloc(sizeof(vim_acl_solaris_T)); + if (aclent == NULL) + return NULL; if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0) { free(aclent); return NULL; } 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) { free(aclent->acl_entry); @@ -3240,13 +3258,15 @@ mch_get_acl(char_u *fname UNUSED) aclsize = sizeof(struct acl); aclent = malloc(aclsize); + if (aclent == NULL) + return NULL; if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0) { if (errno == ENOSPC) { aclsize = aclent->acl_len; 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); return NULL; @@ -3399,7 +3419,11 @@ executable_file(char_u *name) mch_can_exe(char_u *name, char_u **path, int use_path) { char_u *buf; + size_t bufsize; + size_t buflen; char_u *p, *e; + char_u *p_end; + size_t elen; int retval; // 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"); if (p == NULL || *p == NUL) 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) return -1; @@ -3437,15 +3463,18 @@ mch_can_exe(char_u *name, char_u **path, int use_path) { e = (char_u *)strchr((char *)p, ':'); if (e == NULL) - e = p + STRLEN(p); - if (e - p <= 1) // empty entry means current dir - STRCPY(buf, "./"); - else + e = p_end; + elen = (size_t)(e - p); + if (elen <= 1) // empty entry means current dir { - vim_strncpy(buf, p, e - p); - add_pathsep(buf); + p = (char_u *)"./"; + 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); if (retval == 1) { @@ -3454,7 +3483,7 @@ mch_can_exe(char_u *name, char_u **path, int use_path) if (buf[0] != '/') *path = FullName_save(buf, TRUE); else - *path = vim_strsave(buf); + *path = vim_strnsave(buf, buflen); } break; } @@ -5233,13 +5262,13 @@ mch_call_shell_fork( linenr_T lnum = curbuf->b_op_start.lnum; int written = 0; char_u *lp = ml_get(lnum); - size_t l; + size_t lplen = (size_t)ml_get_len(lnum); close(fromshell_fd); for (;;) { - l = STRLEN(lp + written); - if (l == 0) + lplen -= written; + if (lplen == 0) len = 0; else if (lp[written] == NL) // NL -> NUL translation @@ -5249,10 +5278,10 @@ mch_call_shell_fork( char_u *s = vim_strchr(lp + written, NL); len = write(toshell_fd, (char *)lp + written, - s == NULL ? l + s == NULL ? lplen : (size_t)(s - (lp + written))); } - if (len == (int)l) + if (len == (int)lplen) { // Finished a line, add a NL, unless this line // should not have one. @@ -5272,6 +5301,7 @@ mch_call_shell_fork( break; } lp = ml_get(lnum); + lplen = ml_get_len(lnum); written = 0; } else if (len > 0) @@ -6089,14 +6119,14 @@ get_signal_name(int sig) char_u numbuf[NUMBUFLEN]; 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++) if (sig == signal_info[i].sig) return strlow_save((char_u *)signal_info[i].name); - vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig); - return vim_strsave(numbuf); + i = vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig); + return vim_strnsave(numbuf, i); } char * @@ -6852,7 +6882,9 @@ mch_expand_wildcards( */ int j; char_u *tempname; + size_t tempnamelen; char_u *command; + size_t commandlen; FILE *fd; char_u *buffer; #define STYLE_ECHO 0 // use "echo", the default @@ -6866,10 +6898,14 @@ mch_expand_wildcards( int check_spaces; static int did_find_nul = FALSE; int ampersand = FALSE; - // vimglob() function to define for Posix shell - static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; - // vimglob() function with globstar setting enabled, only for bash >= 4.X - static char *sh_globstar_opt = "[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; "; +#define STRING_INIT(s) \ + {(char_u *)(s), STRLEN_LITERAL(s)} + // vimglob() function to define for Posix shell + 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 *file = NULL; @@ -6943,12 +6979,12 @@ mch_expand_wildcards( // Compute the length of the command. We need 2 extra bytes: for the // optional '&' and for the NUL. // 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) - len += STRLEN(sh_vimglob_func); + len += sh_vimglob_func.length; else if (shell_style == STYLE_GLOBSTAR) - len += STRLEN(sh_vimglob_func) - + STRLEN(sh_globstar_opt); + len += sh_vimglob_func.length + sh_globstar_opt.length; for (i = 0; i < num_pat; ++i) { @@ -6985,63 +7021,62 @@ mch_expand_wildcards( if (shell_style == STYLE_BT) { // change `command; command& ` to (command; command ) - STRCPY(command, "("); - STRCAT(command, pat[0] + 1); // exclude first backtick - p = command + STRLEN(command) - 1; - *p-- = ')'; // remove last backtick - while (p > command && VIM_ISWHITE(*p)) - --p; - if (*p == '&') // remove trailing '&' + commandlen = vim_snprintf((char *)command, len, "(%s)>%s", pat[0] + 1, tempname); // +1 to exclude first backtick + + p = (char_u *)strstr((char *)command, ")>"); + if (p == NULL) { - ampersand = TRUE; - *p = ' '; + ; // can't happen ;-) + } + 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 { - STRCPY(command, ""); if (shell_style == STYLE_GLOB) { // Assume the nonomatch option is valid only for csh like shells, // otherwise, this may set the positional parameters for the shell, // e.g. "$*". - if (flags & EW_NOTFOUND) - STRCAT(command, "set nonomatch; "); - else - STRCAT(command, "unset nonomatch; "); + commandlen = vim_snprintf((char *)command, len, "%sset nonomatch; glob >%s", + (flags & EW_NOTFOUND) ? "" : "un", tempname); } - if (shell_style == STYLE_GLOB) - STRCAT(command, "glob >"); 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) - STRCAT(command, sh_vimglob_func); + commandlen = vim_snprintf((char *)command, len, "%s%s", sh_vimglob_func.string, tempname); else if (shell_style == STYLE_GLOBSTAR) - { - STRCAT(command, sh_globstar_opt); - STRCAT(command, sh_vimglob_func); - } + commandlen = vim_snprintf((char *)command, len, "%s%s%s", sh_globstar_opt.string, + sh_vimglob_func.string, tempname); else - STRCAT(command, "echo >"); - } - - STRCAT(command, tempname); + commandlen = vim_snprintf((char *)command, len, "echo >%s", tempname); - if (shell_style != STYLE_BT) for (i = 0; i < num_pat; ++i) { // When using system() always add extra quotes, because the shell // is started twice. Otherwise put a backslash before special // characters, except inside ``. #ifdef USE_SYSTEM - STRCAT(command, " \""); - STRCAT(command, pat[i]); - STRCAT(command, "\""); + commandlen += vim_snprintf((char *)command + commandlen, len, " \"%s\"", pat[i]); #else int intick = FALSE; - p = command + STRLEN(command); + p = command + commandlen; *p++ = ' '; for (j = 0; pat[i][j] != NUL; ++j) { @@ -7070,12 +7105,14 @@ mch_expand_wildcards( *p++ = pat[i][j]; } *p = NUL; + commandlen = (size_t)(p - command); #endif } + } if (flags & EW_SILENT) show_shell_mess = FALSE; 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 @@ -8133,7 +8170,8 @@ do_xterm_trace(void) char_u buf[50]; char_u *strp; 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 int prev_row = 0, prev_col = 0; static XSizeHints xterm_hints; @@ -8156,6 +8194,8 @@ do_xterm_trace(void) // Rely on the same mouse code for the duration of this mouse_code = find_termcode(mouse_name); + if (mouse_code != NULL) + mouse_codelen = STRLEN(mouse_code); prev_row = mouse_row; prev_col = mouse_col; xterm_trace = 2; @@ -8174,7 +8214,8 @@ do_xterm_trace(void) xterm_hints.x = 2; return TRUE; } - if (mouse_code == NULL || STRLEN(mouse_code) > 45) + + if (mouse_code == NULL || mouse_codelen > 45) { xterm_trace = 0; return FALSE; @@ -8189,12 +8230,12 @@ do_xterm_trace(void) return TRUE; STRCPY(buf, mouse_code); - strp = buf + STRLEN(buf); + strp = buf + mouse_codelen; *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20; *strp++ = (char_u)(col + ' ' + 1); *strp++ = (char_u)(row + ' ' + 1); - *strp = 0; - add_to_input_buf(buf, STRLEN(buf)); + *strp = NUL; + add_to_input_buf(buf, strp - buf); prev_row = row; prev_col = col; diff --git a/src/version.c b/src/version.c index 02a58aff5..53cecb346 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 */ +/**/ + 1050, /**/ 1049, /**/ -- -- 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/E1tb2fa-00ENci-R5%40256bit.org.