0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

patch 9.1.0973: too many strlen() calls in fileio.c

Problem:  too many strlen() calls in fileio.c
Solution: refactor fileio.c and remove calls to STRLEN(),
          check for out-of-memory condition in buf_check_timestamp()
          (John Marriott)

closes: #16306

Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
John Marriott
2024-12-29 16:14:19 +01:00
committed by Christian Brabandt
parent df67fc0e69
commit 14ede1890f
2 changed files with 209 additions and 148 deletions

View File

@@ -55,17 +55,23 @@ filemess(
{ {
int msg_scroll_save; int msg_scroll_save;
int prev_msg_col = msg_col; int prev_msg_col = msg_col;
size_t len;
if (msg_silent != 0) if (msg_silent != 0)
return; return;
msg_add_fname(buf, name); // put file name in IObuff with quotes msg_add_fname(buf, name); // put file name in IObuff with quotes
// If it's extremely long, truncate it. // If it's extremely long, truncate it.
if (STRLEN(IObuff) > IOSIZE - 100) len = STRLEN(IObuff);
IObuff[IOSIZE - 100] = NUL; if (len > IOSIZE - 100)
{
len = IOSIZE - 100;
IObuff[len] = NUL;
}
// Avoid an over-long translation to cause trouble. // Avoid an over-long translation to cause trouble.
STRNCAT(IObuff, s, 99); if (*s != NUL)
STRNCPY(IObuff + len, s, 99);
/* /*
* For the first message may have to start a new line. * For the first message may have to start a new line.
@@ -224,6 +230,7 @@ readfile(
#ifdef FEAT_SODIUM #ifdef FEAT_SODIUM
int may_need_lseek = FALSE; int may_need_lseek = FALSE;
#endif #endif
size_t fnamelen = 0;
curbuf->b_au_did_filetype = FALSE; // reset before triggering any autocommands curbuf->b_au_did_filetype = FALSE; // reset before triggering any autocommands
@@ -336,10 +343,10 @@ readfile(
if (fname != NULL && *fname != NUL) if (fname != NULL && *fname != NUL)
{ {
size_t namelen = STRLEN(fname); fnamelen = STRLEN(fname);
// If the name is too long we might crash further on, quit here. // If the name is too long we might crash further on, quit here.
if (namelen >= MAXPATHL) if (fnamelen >= MAXPATHL)
{ {
filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0); filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
msg_end(); msg_end();
@@ -350,7 +357,7 @@ readfile(
// If the name ends in a path separator, we can't open it. Check here, // If the name ends in a path separator, we can't open it. Check here,
// because reading the file may actually work, but then creating the // because reading the file may actually work, but then creating the
// swap file may destroy it! Reported on MS-DOS and Win 95. // swap file may destroy it! Reported on MS-DOS and Win 95.
if (after_pathsep(fname, fname + namelen)) if (after_pathsep(fname, fname + fnamelen))
{ {
filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0); filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
msg_end(); msg_end();
@@ -776,11 +783,13 @@ readfile(
// Also write a message in the GUI window, if there is one. // Also write a message in the GUI window, if there is one.
if (gui.in_use && !gui.dying && !gui.starting) if (gui.in_use && !gui.dying && !gui.starting)
{ {
size_t plen = STRLEN(_("Reading from stdin..."));
// make a copy, gui_write() may try to change it // make a copy, gui_write() may try to change it
p = vim_strsave((char_u *)_("Reading from stdin...")); p = vim_strnsave((char_u *)_("Reading from stdin..."), plen);
if (p != NULL) if (p != NULL)
{ {
gui_write(p, (int)STRLEN(p)); gui_write(p, (int)plen);
vim_free(p); vim_free(p);
} }
} }
@@ -838,7 +847,7 @@ readfile(
c = enc_utf8; c = enc_utf8;
if (!c && !read_stdin) if (!c && !read_stdin)
{ {
fc = fname[STRLEN(fname) - 1]; fc = fname[fnamelen - 1];
if (TOLOWER_ASC(fc) == 'x') if (TOLOWER_ASC(fc) == 'x')
{ {
// Read the first line (and a bit more). Immediately rewind to // Read the first line (and a bit more). Immediately rewind to
@@ -1001,7 +1010,6 @@ retry:
converted = need_conversion(fenc); converted = need_conversion(fenc);
if (converted) if (converted)
{ {
// "ucs-bom" means we need to check the first bytes of the file // "ucs-bom" means we need to check the first bytes of the file
// for a BOM. // for a BOM.
if (STRCMP(fenc, ENC_UCSBOM) == 0) if (STRCMP(fenc, ENC_UCSBOM) == 0)
@@ -2481,31 +2489,38 @@ failed:
if (!filtering && !(flags & READ_DUMMY)) if (!filtering && !(flags & READ_DUMMY))
{ {
int buflen;
msg_add_fname(curbuf, sfname); // fname in IObuff with quotes msg_add_fname(curbuf, sfname); // fname in IObuff with quotes
c = FALSE; c = FALSE;
buflen = (int)STRLEN(IObuff);
#ifdef UNIX #ifdef UNIX
if (S_ISFIFO(perm)) // fifo if (S_ISFIFO(perm)) // fifo
{ {
STRCAT(IObuff, _("[fifo]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[fifo]"));
c = TRUE; c = TRUE;
} }
if (S_ISSOCK(perm)) // or socket if (S_ISSOCK(perm)) // or socket
{ {
STRCAT(IObuff, _("[socket]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[socket]"));
c = TRUE; c = TRUE;
} }
# ifdef OPEN_CHR_FILES # ifdef OPEN_CHR_FILES
if (S_ISCHR(perm)) // or character special if (S_ISCHR(perm)) // or character special
{ {
STRCAT(IObuff, _("[character special]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[character special]"));
c = TRUE; c = TRUE;
} }
# endif # endif
#endif #endif
if (curbuf->b_p_ro) if (curbuf->b_p_ro)
{ {
STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
"%s", shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
c = TRUE; c = TRUE;
} }
if (read_no_eol_lnum) if (read_no_eol_lnum)
@@ -2515,22 +2530,26 @@ failed:
} }
if (ff_error == EOL_DOS) if (ff_error == EOL_DOS)
{ {
STRCAT(IObuff, _("[CR missing]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("CR missing"));
c = TRUE; c = TRUE;
} }
if (split) if (split)
{ {
STRCAT(IObuff, _("[long lines split]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[long lines split]"));
c = TRUE; c = TRUE;
} }
if (notconverted) if (notconverted)
{ {
STRCAT(IObuff, _("[NOT converted]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[NOT converted]"));
c = TRUE; c = TRUE;
} }
else if (converted) else if (converted)
{ {
STRCAT(IObuff, _("[converted]")); buflen += vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[converted]"));
c = TRUE; c = TRUE;
} }
#ifdef FEAT_CRYPT #ifdef FEAT_CRYPT
@@ -2542,19 +2561,20 @@ failed:
#endif #endif
if (conv_error != 0) if (conv_error != 0)
{ {
sprintf((char *)IObuff + STRLEN(IObuff), vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[CONVERSION ERROR in line %ld]"), (long)conv_error); _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
c = TRUE; c = TRUE;
} }
else if (illegal_byte > 0) else if (illegal_byte > 0)
{ {
sprintf((char *)IObuff + STRLEN(IObuff), vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte); _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
c = TRUE; c = TRUE;
} }
else if (error) else if (error)
{ {
STRCAT(IObuff, _("[READ ERRORS]")); vim_snprintf((char *)IObuff + buflen, IOSIZE - buflen,
_("[READ ERRORS]"));
c = TRUE; c = TRUE;
} }
if (msg_add_fileformat(fileformat)) if (msg_add_fileformat(fileformat))
@@ -3162,22 +3182,17 @@ msg_add_lines(
long lnum, long lnum,
off_T nchars) off_T nchars)
{ {
char_u *p; int len = (int)STRLEN(IObuff);
p = IObuff + STRLEN(IObuff);
if (insert_space)
*p++ = ' ';
if (shortmess(SHM_LINES)) if (shortmess(SHM_LINES))
vim_snprintf((char *)p, IOSIZE - (p - IObuff), vim_snprintf((char *)IObuff + len, IOSIZE - (size_t)len,
"%ldL, %lldB", lnum, (varnumber_T)nchars); "%s%ldL, %lldB", insert_space ? " " : "", lnum, (varnumber_T)nchars);
else else
{ {
sprintf((char *)p, NGETTEXT("%ld line, ", "%ld lines, ", lnum), lnum); len += vim_snprintf((char *)IObuff + len, IOSIZE - (size_t)len,
p += STRLEN(p); NGETTEXT("%s%ld line, ", "%s%ld lines, ", lnum), insert_space ? " " : "", lnum);
vim_snprintf((char *)p, IOSIZE - (p - IObuff), vim_snprintf((char *)IObuff + len, IOSIZE - (size_t)len,
NGETTEXT("%lld byte", "%lld bytes", nchars), NGETTEXT("%lld byte", "%lld bytes", nchars), (varnumber_T)nchars);
(varnumber_T)nchars);
} }
} }
@@ -3585,6 +3600,7 @@ buf_modname(
char_u *s; char_u *s;
char_u *e; char_u *e;
char_u *ptr; char_u *ptr;
size_t ptrlen;
int fnamelen, extlen; int fnamelen, extlen;
extlen = (int)STRLEN(ext); extlen = (int)STRLEN(ext);
@@ -3642,10 +3658,14 @@ buf_modname(
} }
// the file name has at most BASENAMELEN characters. // the file name has at most BASENAMELEN characters.
if (STRLEN(ptr) > (unsigned)BASENAMELEN) ptrlen = (size_t)(fnamelen - (ptr - retval));
ptr[BASENAMELEN] = '\0'; if (ptrlen > (unsigned)BASENAMELEN)
{
ptrlen = BASENAMELEN;
ptr[ptrlen] = NUL;
}
s = ptr + STRLEN(ptr); s = ptr + ptrlen;
/* /*
* For 8.3 file names we may have to reduce the length. * For 8.3 file names we may have to reduce the length.
@@ -3685,7 +3705,7 @@ buf_modname(
* If the extension doesn't start with '.', and there already is an * If the extension doesn't start with '.', and there already is an
* extension, it may need to be truncated * extension, it may need to be truncated
*/ */
else if ((int)STRLEN(e) + extlen > 4) else if ((int)(ptrlen - (e - retval)) + extlen > 4)
s = e + 4 - extlen; s = e + 4 - extlen;
} }
#ifdef MSWIN #ifdef MSWIN
@@ -3703,13 +3723,12 @@ buf_modname(
* ext can start with '.' and cannot exceed 3 more characters. * ext can start with '.' and cannot exceed 3 more characters.
*/ */
STRCPY(s, ext); STRCPY(s, ext);
/* /*
* Prepend the dot. * Prepend the dot.
*/ */
if (prepend_dot && !shortname && *(e = gettail(retval)) != '.') if (prepend_dot && !shortname && *(e = gettail(retval)) != '.')
{ {
STRMOVE(e + 1, e); mch_memmove(e + 1, e, (size_t)(((fnamelen + extlen) - (e - retval)) + 1)); // +1 for NUL
*e = '.'; *e = '.';
} }
@@ -4111,7 +4130,7 @@ move_lines(buf_T *frombuf, buf_T *tobuf)
curbuf = tobuf; curbuf = tobuf;
for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum) for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
{ {
p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE)); p = vim_strnsave(ml_get_buf(frombuf, lnum, FALSE), ml_get_buf_len(frombuf, lnum));
if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL) if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
{ {
vim_free(p); vim_free(p);
@@ -4154,8 +4173,6 @@ buf_check_timestamp(
stat_T st; stat_T st;
int stat_res; int stat_res;
int retval = 0; int retval = 0;
char_u *path;
char *tbuf;
char *mesg = NULL; char *mesg = NULL;
char *mesg2 = ""; char *mesg2 = "";
int helpmesg = FALSE; int helpmesg = FALSE;
@@ -4164,7 +4181,6 @@ buf_check_timestamp(
RELOAD_NORMAL, RELOAD_NORMAL,
RELOAD_DETECT RELOAD_DETECT
} reload = RELOAD_NONE; } reload = RELOAD_NONE;
char *reason;
#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG) #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
int can_reload = FALSE; int can_reload = FALSE;
#endif #endif
@@ -4175,9 +4191,6 @@ buf_check_timestamp(
#endif #endif
static int busy = FALSE; static int busy = FALSE;
int n; int n;
#ifdef FEAT_EVAL
char_u *s;
#endif
bufref_T bufref; bufref_T bufref;
set_bufref(&bufref, buf); set_bufref(&bufref, buf);
@@ -4242,21 +4255,51 @@ buf_check_timestamp(
reload = RELOAD_NORMAL; reload = RELOAD_NORMAL;
else else
{ {
char *reason;
#ifdef FEAT_EVAL
size_t reasonlen;
#endif
if (stat_res < 0) if (stat_res < 0)
{
reason = "deleted"; reason = "deleted";
#ifdef FEAT_EVAL
reasonlen = STRLEN_LITERAL("deleted");
#endif
}
else if (bufIsChanged(buf)) else if (bufIsChanged(buf))
{
reason = "conflict"; reason = "conflict";
#ifdef FEAT_EVAL
reasonlen = STRLEN_LITERAL("conflict");
#endif
}
/* /*
* Check if the file contents really changed to avoid giving a * Check if the file contents really changed to avoid giving a
* warning when only the timestamp was set (e.g., checked out of * warning when only the timestamp was set (e.g., checked out of
* CVS). Always warn when the buffer was changed. * CVS). Always warn when the buffer was changed.
*/ */
else if (orig_size != buf->b_orig_size || buf_contents_changed(buf)) else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
{
reason = "changed"; reason = "changed";
#ifdef FEAT_EVAL
reasonlen = STRLEN_LITERAL("changed");
#endif
}
else if (orig_mode != buf->b_orig_mode) else if (orig_mode != buf->b_orig_mode)
{
reason = "mode"; reason = "mode";
#ifdef FEAT_EVAL
reasonlen = STRLEN_LITERAL("mode");
#endif
}
else else
{
reason = "time"; reason = "time";
#ifdef FEAT_EVAL
reasonlen = STRLEN_LITERAL("time");
#endif
}
/* /*
* Only give the warning if there are no FileChangedShell * Only give the warning if there are no FileChangedShell
@@ -4265,8 +4308,8 @@ buf_check_timestamp(
*/ */
busy = TRUE; busy = TRUE;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1); set_vim_var_string(VV_FCS_REASON, (char_u *)reason, reasonlen);
set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1); set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", 0);
#endif #endif
++allbuf_lock; ++allbuf_lock;
n = apply_autocmds(EVENT_FILECHANGEDSHELL, n = apply_autocmds(EVENT_FILECHANGEDSHELL,
@@ -4278,7 +4321,7 @@ buf_check_timestamp(
if (!bufref_valid(&bufref)) if (!bufref_valid(&bufref))
emsg(_(e_filechangedshell_autocommand_deleted_buffer)); emsg(_(e_filechangedshell_autocommand_deleted_buffer));
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
s = get_vim_var_str(VV_FCS_CHOICE); char_u *s = get_vim_var_str(VV_FCS_CHOICE);
if (STRCMP(s, "reload") == 0 && *reason != 'd') if (STRCMP(s, "reload") == 0 && *reason != 'd')
reload = RELOAD_NORMAL; reload = RELOAD_NORMAL;
else if (STRCMP(s, "edit") == 0) else if (STRCMP(s, "edit") == 0)
@@ -4343,26 +4386,34 @@ buf_check_timestamp(
if (mesg != NULL) if (mesg != NULL)
{ {
char_u *path;
path = home_replace_save(buf, buf->b_fname); path = home_replace_save(buf, buf->b_fname);
if (path != NULL) if (path != NULL)
{ {
size_t tbufsize;
char *tbuf;
if (!helpmesg) if (!helpmesg)
mesg2 = ""; mesg2 = "";
tbuf = alloc(STRLEN(path) + STRLEN(mesg) + STRLEN(mesg2) + 2); tbufsize = STRLEN(mesg) + STRLEN(path) + 2 + STRLEN(mesg2) + 1; // +2 for either '\n' or "; "
sprintf(tbuf, mesg, path); // and +1 for NUL
tbuf = alloc(tbufsize);
if (tbuf != NULL)
{
int tbuflen;
tbuflen = vim_snprintf(tbuf, tbufsize, mesg, path);
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
// Set warningmsg here, before the unimportant and output-specific // Set warningmsg here, before the unimportant and output-specific
// mesg2 has been appended. // mesg2 has been appended.
set_vim_var_string(VV_WARNINGMSG, (char_u *)tbuf, -1); set_vim_var_string(VV_WARNINGMSG, (char_u *)tbuf, tbuflen);
#endif #endif
#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG) #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
if (can_reload) if (can_reload)
{ {
if (*mesg2 != NUL) if (*mesg2 != NUL)
{ vim_snprintf(tbuf + tbuflen, tbufsize - tbuflen, "\n%s", mesg2);
STRCAT(tbuf, "\n");
STRCAT(tbuf, mesg2);
}
switch (do_dialog(VIM_WARNING, (char_u *)_("Warning"), switch (do_dialog(VIM_WARNING, (char_u *)_("Warning"),
(char_u *)tbuf, (char_u *)tbuf,
(char_u *)_("&OK\n&Load File\nLoad File &and Options"), (char_u *)_("&OK\n&Load File\nLoad File &and Options"),
@@ -4382,10 +4433,7 @@ buf_check_timestamp(
|| already_warned) || already_warned)
{ {
if (*mesg2 != NUL) if (*mesg2 != NUL)
{ vim_snprintf(tbuf + tbuflen, tbufsize - tbuflen, "; %s", mesg2);
STRCAT(tbuf, "; ");
STRCAT(tbuf, mesg2);
}
emsg(tbuf); emsg(tbuf);
retval = 2; retval = 2;
} }
@@ -4402,9 +4450,9 @@ buf_check_timestamp(
if (emsg_silent == 0 && !in_assert_fails) if (emsg_silent == 0 && !in_assert_fails)
{ {
out_flush(); out_flush();
#ifdef FEAT_GUI #ifdef FEAT_GUI
if (!focus) if (!focus)
#endif #endif
// give the user some time to think about it // give the user some time to think about it
ui_delay(1004L, TRUE); ui_delay(1004L, TRUE);
@@ -4414,9 +4462,10 @@ buf_check_timestamp(
} }
already_warned = TRUE; already_warned = TRUE;
} }
}
vim_free(path);
vim_free(tbuf); vim_free(tbuf);
vim_free(path);
} }
} }
@@ -4696,18 +4745,18 @@ getftypewfd(WIN32_FIND_DATAW *wfd)
{ {
if (tag == IO_REPARSE_TAG_MOUNT_POINT) if (tag == IO_REPARSE_TAG_MOUNT_POINT)
return (char_u*)"junction"; return (char_u*)"junction";
else if (tag == IO_REPARSE_TAG_SYMLINK) if (tag == IO_REPARSE_TAG_SYMLINK)
{ {
if (flag & FILE_ATTRIBUTE_DIRECTORY) if (flag & FILE_ATTRIBUTE_DIRECTORY)
return (char_u*)"linkd"; return (char_u*)"linkd";
else
return (char_u*)"link"; return (char_u*)"link";
} }
return (char_u*)"reparse"; // unknown reparse point type return (char_u*)"reparse"; // unknown reparse point type
} }
if (flag & FILE_ATTRIBUTE_DIRECTORY) if (flag & FILE_ATTRIBUTE_DIRECTORY)
return (char_u*)"dir"; return (char_u*)"dir";
else
return (char_u*)"file"; return (char_u*)"file";
} }
@@ -4793,7 +4842,6 @@ create_readdirex_item(char_u *path, char_u *name)
ret = mch_stat(p, &st); ret = mch_stat(p, &st);
if (ret < 0) if (ret < 0)
q = (char_u*)"link"; q = (char_u*)"link";
} }
vim_free(p); vim_free(p);
@@ -4876,9 +4924,9 @@ compare_readdirex_item(const void *p1, const void *p2)
name2 = dict_get_string(*(dict_T**)p2, "name", FALSE); name2 = dict_get_string(*(dict_T**)p2, "name", FALSE);
if (readdirex_sort == READDIR_SORT_BYTE) if (readdirex_sort == READDIR_SORT_BYTE)
return STRCMP(name1, name2); return STRCMP(name1, name2);
else if (readdirex_sort == READDIR_SORT_IC) if (readdirex_sort == READDIR_SORT_IC)
return STRICMP(name1, name2); return STRICMP(name1, name2);
else
return STRCOLL(name1, name2); return STRCOLL(name1, name2);
} }
@@ -4887,9 +4935,9 @@ compare_readdir_item(const void *s1, const void *s2)
{ {
if (readdirex_sort == READDIR_SORT_BYTE) if (readdirex_sort == READDIR_SORT_BYTE)
return STRCMP(*(char **)s1, *(char **)s2); return STRCMP(*(char **)s1, *(char **)s2);
else if (readdirex_sort == READDIR_SORT_IC) if (readdirex_sort == READDIR_SORT_IC)
return STRICMP(*(char **)s1, *(char **)s2); return STRICMP(*(char **)s1, *(char **)s2);
else
return STRCOLL(*(char **)s1, *(char **)s2); return STRCOLL(*(char **)s1, *(char **)s2);
} }
#endif #endif
@@ -4919,6 +4967,7 @@ readdir_core(
HANDLE hFind = INVALID_HANDLE_VALUE; HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW wfd; WIN32_FIND_DATAW wfd;
WCHAR *wn = NULL; // UTF-16 name, NULL when not used. WCHAR *wn = NULL; // UTF-16 name, NULL when not used.
char_u *p_end;
# else # else
DIR *dirp; DIR *dirp;
struct dirent *dp; struct dirent *dp;
@@ -4944,11 +4993,11 @@ readdir_core(
if (buf == NULL) if (buf == NULL)
return FAIL; return FAIL;
STRNCPY(buf, path, MAXPATHL-5); STRNCPY(buf, path, MAXPATHL-5);
p = buf + STRLEN(buf); p = p_end = buf + STRLEN(buf);
MB_PTR_BACK(buf, p); MB_PTR_BACK(buf, p);
if (*p == '\\' || *p == '/') if (*p == '\\' || *p == '/')
*p = NUL; p_end = p;
STRCAT(p, "\\*"); STRCPY(p_end, "\\*");
wn = enc_to_utf16(buf, NULL); wn = enc_to_utf16(buf, NULL);
if (wn != NULL) if (wn != NULL)
@@ -5118,9 +5167,6 @@ readdir_core(
delete_recursive(char_u *name) delete_recursive(char_u *name)
{ {
int result = 0; int result = 0;
int i;
char_u *exp;
garray_T ga;
// A symbolic link to a directory itself is deleted, not the directory it // A symbolic link to a directory itself is deleted, not the directory it
// points to. // points to.
@@ -5132,15 +5178,19 @@ delete_recursive(char_u *name)
# endif # endif
) )
{ {
exp = vim_strsave(name); char_u *exp = vim_strsave(name);
garray_T ga;
if (exp == NULL) if (exp == NULL)
return -1; return -1;
if (readdir_core(&ga, exp, FALSE, NULL, NULL, READDIR_SORT_NONE) == OK) if (readdir_core(&ga, exp, FALSE, NULL, NULL, READDIR_SORT_NONE) == OK)
{ {
int len = vim_snprintf((char *)NameBuff, MAXPATHL, "%s/", exp);
int i;
for (i = 0; i < ga.ga_len; ++i) for (i = 0; i < ga.ga_len; ++i)
{ {
vim_snprintf((char *)NameBuff, MAXPATHL, "%s/%s", exp, vim_snprintf((char *)NameBuff + len, MAXPATHL - len, "%s", ((char_u **)ga.ga_data)[i]);
((char_u **)ga.ga_data)[i]);
if (delete_recursive(NameBuff) != 0) if (delete_recursive(NameBuff) != 0)
// Remember the failure but continue deleting any further // Remember the failure but continue deleting any further
// entries. // entries.
@@ -5226,6 +5276,7 @@ vim_deltempdir(void)
vim_settempdir(char_u *tempdir) vim_settempdir(char_u *tempdir)
{ {
char_u *buf; char_u *buf;
size_t buflen;
buf = alloc(MAXPATHL + 2); buf = alloc(MAXPATHL + 2);
if (buf == NULL) if (buf == NULL)
@@ -5233,8 +5284,13 @@ vim_settempdir(char_u *tempdir)
if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL) if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
STRCPY(buf, tempdir); STRCPY(buf, tempdir);
add_pathsep(buf); buflen = STRLEN(buf);
vim_tempdir = vim_strsave(buf); if (!after_pathsep(buf, buf + buflen))
{
STRCPY(buf + buflen, PATHSEPSTR);
buflen += STRLEN_LITERAL(PATHSEPSTR);
}
vim_tempdir = vim_strnsave(buf, buflen);
# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD) # if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
vim_opentempdir(); vim_opentempdir();
# endif # endif
@@ -5286,7 +5342,6 @@ vim_tempname(
for (i = 0; i < (int)ARRAY_LENGTH(tempdirs); ++i) for (i = 0; i < (int)ARRAY_LENGTH(tempdirs); ++i)
{ {
# ifndef HAVE_MKDTEMP # ifndef HAVE_MKDTEMP
size_t itmplen;
long nr; long nr;
long off; long off;
# endif # endif
@@ -5296,8 +5351,14 @@ vim_tempname(
expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20); expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
if (itmp[0] != '$' && mch_isdir(itmp)) if (itmp[0] != '$' && mch_isdir(itmp))
{ {
size_t itmplen = STRLEN(itmp);
// directory exists // directory exists
add_pathsep(itmp); if (!after_pathsep(itmp, itmp + itmplen))
{
STRCPY(itmp + itmplen, PATHSEPSTR);
itmplen += STRLEN_LITERAL(PATHSEPSTR);
}
# ifdef HAVE_MKDTEMP # ifdef HAVE_MKDTEMP
{ {
@@ -5307,7 +5368,8 @@ vim_tempname(
mode_t umask_save = umask(077); mode_t umask_save = umask(077);
# endif # endif
// Leave room for filename // Leave room for filename
STRCAT(itmp, "vXXXXXX"); STRCPY(itmp + itmplen, "vXXXXXX");
itmplen += STRLEN_LITERAL("vXXXXXX");
if (mkdtemp((char *)itmp) != NULL) if (mkdtemp((char *)itmp) != NULL)
vim_settempdir(itmp); vim_settempdir(itmp);
# if defined(UNIX) || defined(VMS) # if defined(UNIX) || defined(VMS)
@@ -5320,7 +5382,6 @@ vim_tempname(
// otherwise it doesn't matter. The use of mkdir() avoids any // otherwise it doesn't matter. The use of mkdir() avoids any
// security problems because of the predictable number. // security problems because of the predictable number.
nr = (mch_get_pid() + (long)time(NULL)) % 1000000L; nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
itmplen = STRLEN(itmp);
// Try up to 10000 different values until we find a name that // Try up to 10000 different values until we find a name that
// doesn't exist. // doesn't exist.
@@ -5331,7 +5392,7 @@ vim_tempname(
mode_t umask_save; mode_t umask_save;
# endif # endif
sprintf((char *)itmp + itmplen, "v%ld", nr + off); vim_snprintf((char *)itmp + itmplen, sizeof(itmp) - itmplen, "v%ld", nr + off);
# ifndef EEXIST # ifndef EEXIST
// If mkdir() does not set errno to EEXIST, check for // If mkdir() does not set errno to EEXIST, check for
// existing file here. There is a race condition then, // existing file here. There is a race condition then,
@@ -5372,20 +5433,20 @@ vim_tempname(
{ {
// There is no need to check if the file exists, because we own the // There is no need to check if the file exists, because we own the
// directory and nobody else creates a file in it. // directory and nobody else creates a file in it.
sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++); int itmplen = vim_snprintf((char *)itmp, sizeof(itmp), "%s%ld", vim_tempdir, temp_count++);
return vim_strsave(itmp); return vim_strnsave(itmp, (size_t)itmplen);
} }
return NULL; return NULL;
#else // TEMPDIRNAMES #else // TEMPDIRNAMES
char_u *p;
# ifdef MSWIN # ifdef MSWIN
WCHAR wszTempFile[_MAX_PATH + 1]; WCHAR wszTempFile[_MAX_PATH + 1];
WCHAR buf4[4]; WCHAR buf4[4];
WCHAR *chartab = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; WCHAR *chartab = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char_u *retval; char_u *retval;
char_u *p;
char_u *shname; char_u *shname;
long i; long i;
@@ -5405,7 +5466,7 @@ vim_tempname(
if (GetTempFileNameW(wszTempFile, buf4, 0, itmp) == 0) if (GetTempFileNameW(wszTempFile, buf4, 0, itmp) == 0)
return NULL; return NULL;
if (!keep) if (!keep)
// GetTempFileName() will create the file, we don't want that // GetTempFileNameW() will create the file, we don't want that
(void)DeleteFileW(itmp); (void)DeleteFileW(itmp);
// Backslashes in a temp file name cause problems when filtering with // Backslashes in a temp file name cause problems when filtering with
@@ -5422,34 +5483,32 @@ vim_tempname(
return retval; return retval;
# else // MSWIN # else // MSWIN
int itmplen;
# ifdef USE_TMPNAM # ifdef USE_TMPNAM
char_u *p;
// tmpnam() will make its own name // tmpnam() will make its own name
p = tmpnam((char *)itmp); p = tmpnam((char *)itmp);
if (p == NULL || *p == NUL) if (p == NULL || *p == NUL)
return NULL; return NULL;
# else # else
char_u *p;
# ifdef VMS_TEMPNAM # ifdef VMS_TEMPNAM
// mktemp() is not working on VMS. It seems to be // mktemp() is not working on VMS. It seems to be
// a do-nothing function. Therefore we use tempnam(). // a do-nothing function. Therefore we use tempnam().
sprintf((char *)itmp, "VIM%c", extra_char); vim_snprintf((char *)itmp, sizeof(itmp), "VIM%c", extra_char);
p = (char_u *)tempnam("tmp:", (char *)itmp); p = (char_u *)tempnam("tmp:", (char *)itmp);
if (p != NULL) if (p != NULL)
{ {
// VMS will use '.LIS' if we don't explicitly specify an extension, // VMS will use '.LIS' if we don't explicitly specify an extension,
// and VIM will then be unable to find the file later // and VIM will then be unable to find the file later
STRCPY(itmp, p); itmplen = vim_snprintf((char *)itmp, sizeof(itmp), "%s.txt", p);
STRCAT(itmp, ".txt");
free(p); free(p);
} }
else else
return NULL; return NULL;
# else # else
STRCPY(itmp, TEMPNAME); STRCPY(itmp, TEMPNAME);
itmplen = STRLEN_LITERAL(TEMPNAME);
if ((p = vim_strchr(itmp, '?')) != NULL) if ((p = vim_strchr(itmp, '?')) != NULL)
*p = extra_char; *p = extra_char;
if (mktemp((char *)itmp) == NULL) if (mktemp((char *)itmp) == NULL)
@@ -5457,7 +5516,7 @@ vim_tempname(
# endif # endif
# endif # endif
return vim_strsave(itmp); return vim_strnsave(itmp, (size_t)itmplen);
# endif // MSWIN # endif // MSWIN
#endif // TEMPDIRNAMES #endif // TEMPDIRNAMES
} }

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 */
/**/
973,
/**/ /**/
972, 972,
/**/ /**/