changeset 16621:7ad3fc329e08 v8.1.1313

patch 8.1.1313: warnings for using localtime() and ctime() commit https://github.com/vim/vim/commit/63d2555c9cefbbeeca3ec87fdd5d241e9488f9dd Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 10 21:28:38 2019 +0200 patch 8.1.1313: warnings for using localtime() and ctime() Problem: Warnings for using localtime() and ctime(). Solution: Use localtime_r() if available. Avoid using ctime().
author Bram Moolenaar <Bram@vim.org>
date Fri, 10 May 2019 21:30:07 +0200
parents f4e556e906f3
children 502db4d7790b
files src/auto/configure src/config.h.in src/configure.ac src/evalfunc.c src/hardcopy.c src/memline.c src/nbdebug.c src/proto/memline.pro src/undo.c src/version.c
diffstat 10 files changed, 83 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -12650,10 +12650,21 @@ fi
 if test "x$vim_cv_getcwd_broken" = "xyes" ; then
   $as_echo "#define BAD_GETCWD 1" >>confdefs.h
 
+  for ac_func in getwd
+do :
+  ac_fn_c_check_func "$LINENO" "getwd" "ac_cv_func_getwd"
+if test "x$ac_cv_func_getwd" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETWD 1
+_ACEOF
+
+fi
+done
+
 fi
 
 for ac_func in fchdir fchown fchmod fsync getcwd getpseudotty \
-	getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
+	getpwent getpwnam getpwuid getrlimit gettimeofday localtime_r lstat \
 	memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
 	getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
 	sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -174,6 +174,7 @@
 #undef HAVE_GETTIMEOFDAY
 #undef HAVE_GETWD
 #undef HAVE_ICONV
+#undef HAVE_LOCALTIME_R
 #undef HAVE_LSTAT
 #undef HAVE_MEMSET
 #undef HAVE_MKDTEMP
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -3736,12 +3736,13 @@ main()
 
 if test "x$vim_cv_getcwd_broken" = "xyes" ; then
   AC_DEFINE(BAD_GETCWD)
+  AC_CHECK_FUNCS(getwd)
 fi
 
 dnl Check for functions in one big call, to reduce the size of configure.
 dnl Can only be used for functions that do not require any include.
 AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \
-	getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat \
+	getpwent getpwnam getpwuid getrlimit gettimeofday localtime_r lstat \
 	memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
 	getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
 	sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -13213,6 +13213,9 @@ f_str2nr(typval_T *argvars, typval_T *re
 f_strftime(typval_T *argvars, typval_T *rettv)
 {
     char_u	result_buf[256];
+# ifdef HAVE_LOCALTIME_R
+    struct tm	tmval;
+# endif
     struct tm	*curtime;
     time_t	seconds;
     char_u	*p;
@@ -13224,7 +13227,11 @@ f_strftime(typval_T *argvars, typval_T *
 	seconds = time(NULL);
     else
 	seconds = (time_t)tv_get_number(&argvars[1]);
+# ifdef HAVE_LOCALTIME_R
+    curtime = localtime_r(&seconds, &tmval);
+# else
     curtime = localtime(&seconds);
+# endif
     /* MSVC returns NULL for an invalid value of seconds. */
     if (curtime == NULL)
 	rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
--- a/src/hardcopy.c
+++ b/src/hardcopy.c
@@ -2723,9 +2723,7 @@ prt_add_resource(struct prt_ps_resource_
     int
 mch_print_begin(prt_settings_T *psettings)
 {
-    time_t	now;
     int		bbox[4];
-    char	*p_time;
     double      left;
     double      right;
     double      top;
@@ -2734,7 +2732,6 @@ mch_print_begin(prt_settings_T *psetting
     struct prt_ps_resource_S *res_encoding;
     char	buffer[256];
     char_u      *p_encoding;
-    char_u	*p;
     struct prt_ps_resource_S *res_cidfont;
     struct prt_ps_resource_S *res_cmap;
     int		retval = FALSE;
@@ -2761,13 +2758,8 @@ mch_print_begin(prt_settings_T *psetting
     prt_dsc_textline("For", buffer);
     prt_dsc_textline("Creator", VIM_VERSION_LONG);
     /* Note: to ensure Clean8bit I don't think we can use LC_TIME */
-    now = time(NULL);
-    p_time = ctime(&now);
-    /* Note: ctime() adds a \n so we have to remove it :-( */
-    p = vim_strchr((char_u *)p_time, '\n');
-    if (p != NULL)
-	*p = NUL;
-    prt_dsc_textline("CreationDate", p_time);
+
+    prt_dsc_textline("CreationDate", get_ctime(time(NULL), FALSE));
     prt_dsc_textline("DocumentData", "Clean8Bit");
     prt_dsc_textline("Orientation", "Portrait");
     prt_dsc_atend("Pages");
--- a/src/memline.c
+++ b/src/memline.c
@@ -2078,6 +2078,41 @@ get_b0_dict(char_u *fname, dict_T *d)
 #endif
 
 /*
+ * Replacement for ctime(), which is not safe to use.
+ * Requires strftime(), otherwise returns "(unknown)".
+ * If "thetime" is invalid returns "(invalid)".  Never returns NULL.
+ * When "add_newline" is TRUE add a newline like ctime() does.
+ * Uses a static buffer.
+ */
+    char *
+get_ctime(time_t thetime, int add_newline)
+{
+    static char buf[50];
+#ifdef HAVE_STRFTIME
+# ifdef HAVE_LOCALTIME_R
+    struct tm	tmval;
+# endif
+    struct tm	*curtime;
+
+# ifdef HAVE_LOCALTIME_R
+    curtime = localtime_r(&thetime, &tmval);
+# else
+    curtime = localtime(&thetime);
+# endif
+    /* MSVC returns NULL for an invalid value of seconds. */
+    if (curtime == NULL)
+	STRCPY(buf, _("(Invalid)"));
+    else
+	(void)strftime(buf, sizeof(buf) - 1, "%a %b %d %H:%M:%S %Y", curtime);
+#else
+    STRCPY(buf, "(unknown)");
+#endif
+    if (add_newline)
+	STRCAT(buf, "\n");
+    return buf;
+}
+
+/*
  * Give information about an existing swap file.
  * Returns timestamp (0 when unknown).
  */
@@ -2087,17 +2122,15 @@ swapfile_info(char_u *fname)
     stat_T	    st;
     int		    fd;
     struct block0   b0;
-    time_t	    x = (time_t)0;
-    char	    *p;
 #ifdef UNIX
     char_u	    uname[B0_UNAME_SIZE];
 #endif
 
-    /* print the swap file date */
+    // print the swap file date
     if (mch_stat((char *)fname, &st) != -1)
     {
 #ifdef UNIX
-	/* print name of owner of the file */
+	// print name of owner of the file
 	if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
 	{
 	    msg_puts(_("          owned by: "));
@@ -2107,13 +2140,10 @@ swapfile_info(char_u *fname)
 	else
 #endif
 	    msg_puts(_("             dated: "));
-	x = st.st_mtime;		    /* Manx C can't do &st.st_mtime */
-	p = ctime(&x);			    /* includes '\n' */
-	if (p == NULL)
-	    msg_puts("(invalid)\n");
-	else
-	    msg_puts(p);
+	msg_puts(get_ctime(st.st_mtime, TRUE));
     }
+    else
+	st.st_mtime = 0;
 
     /*
      * print the original file name
@@ -2191,7 +2221,7 @@ swapfile_info(char_u *fname)
 	msg_puts(_("         [cannot be opened]"));
     msg_putchar('\n');
 
-    return x;
+    return st.st_mtime;
 }
 
 /*
@@ -4412,15 +4442,14 @@ attention_message(
     char_u  *fname)	/* swap file name */
 {
     stat_T	st;
-    time_t	x, sx;
-    char	*p;
+    time_t	swap_mtime;
 
     ++no_wait_return;
     (void)emsg(_("E325: ATTENTION"));
     msg_puts(_("\nFound a swap file by the name \""));
     msg_home_replace(fname);
     msg_puts("\"\n");
-    sx = swapfile_info(fname);
+    swap_mtime = swapfile_info(fname);
     msg_puts(_("While opening file \""));
     msg_outtrans(buf->b_fname);
     msg_puts("\"\n");
@@ -4431,13 +4460,8 @@ attention_message(
     else
     {
 	msg_puts(_("             dated: "));
-	x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
-	p = ctime(&x);			    /* includes '\n' */
-	if (p == NULL)
-	    msg_puts("(invalid)\n");
-	else
-	    msg_puts(p);
-	if (sx != 0 && x > sx)
+	msg_puts(get_ctime(st.st_mtime, TRUE));
+	if (swap_mtime != 0 && st.st_mtime > swap_mtime)
 	    msg_puts(_("      NEWER than swap file!\n"));
     }
     /* Some of these messages are long to allow translation to
--- a/src/nbdebug.c
+++ b/src/nbdebug.c
@@ -80,12 +80,13 @@ nbdebug_log_init(
 	char		*file;		/* possible nb_debug output file */
 	char		*cp;		/* nb_dlevel pointer */
 
-	if (log_var && (file = getenv(log_var)) != NULL) {
+	if (log_var && (file = getenv(log_var)) != NULL)
+	{
 		time_t now;
 
 		nb_debug = fopen(file, "a");
 		time(&now);
-		fprintf(nb_debug, "%s", asctime(localtime(&now)));
+		fprintf(nb_debug, "%s", get_ctime(now, TRUE));
 		if (level_var && (cp = getenv(level_var)) != NULL) {
 			nb_dlevel = strtoul(cp, NULL, 0);
 		} else {
--- a/src/proto/memline.pro
+++ b/src/proto/memline.pro
@@ -13,6 +13,7 @@ void ml_recover(void);
 int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
 char_u *make_percent_swname(char_u *dir, char_u *name);
 void get_b0_dict(char_u *fname, dict_T *d);
+char *get_ctime(time_t thetime, int add_newline);
 void ml_sync_all(int check_file, int check_char);
 void ml_preserve(buf_T *buf, int message);
 char_u *ml_get(linenr_T lnum);
--- a/src/undo.c
+++ b/src/undo.c
@@ -3110,11 +3110,19 @@ ex_undolist(exarg_T *eap UNUSED)
 u_add_time(char_u *buf, size_t buflen, time_t tt)
 {
 #ifdef HAVE_STRFTIME
+# ifdef HAVE_LOCALTIME_R
+    struct tm	tmval;
+# endif
     struct tm	*curtime;
 
     if (vim_time() - tt >= 100)
     {
 	curtime = localtime(&tt);
+# ifdef HAVE_LOCALTIME_R
+	curtime = localtime_r(&tt, &tmval);
+# else
+	curtime = localtime(&tt);
+# endif
 	if (vim_time() - tt < (60L * 60L * 12L))
 	    /* within 12 hours */
 	    (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1313,
+/**/
     1312,
 /**/
     1311,