# HG changeset patch # User Bram Moolenaar # Date 1557516607 -7200 # Node ID 7ad3fc329e08a8c29a73b217fb486f3e1cda4035 # Parent f4e556e906f3f652568fdc1ae49f0bef1edaa28f patch 8.1.1313: warnings for using localtime() and ctime() commit https://github.com/vim/vim/commit/63d2555c9cefbbeeca3ec87fdd5d241e9488f9dd Author: Bram Moolenaar 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(). diff --git a/src/auto/configure b/src/auto/configure --- 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 \ diff --git a/src/config.h.in b/src/config.h.in --- 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 diff --git a/src/configure.ac b/src/configure.ac --- 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 \ diff --git a/src/evalfunc.c b/src/evalfunc.c --- 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)")); diff --git a/src/hardcopy.c b/src/hardcopy.c --- 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"); diff --git a/src/memline.c b/src/memline.c --- 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 diff --git a/src/nbdebug.c b/src/nbdebug.c --- 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 { diff --git a/src/proto/memline.pro b/src/proto/memline.pro --- 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); diff --git a/src/undo.c b/src/undo.c --- 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); diff --git a/src/version.c b/src/version.c --- 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,