]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1050: too many strlen() calls in os_unix.c v9.1.1050
authorJohn Marriott <basilisk@internode.on.net>
Thu, 23 Jan 2025 19:05:29 +0000 (20:05 +0100)
committerChristian Brabandt <cb@256bit.org>
Thu, 23 Jan 2025 19:05:29 +0000 (20:05 +0100)
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>
src/os_unix.c
src/version.c

index dc518fc6764d6345ec4109e40019c3074483ace0..95b21d297dc4f7625db2017949319ea5427496a7 100644 (file)
@@ -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;
index 02a58aff52164d44d8bde6128769d80e61165f12..53cecb34600a8abc07c99a044a4b11d10a56f57d 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1050,
 /**/
     1049,
 /**/