[PATCH v2 4/5] ucrtbase: Correct behavior of strftime format %X.

Jeff Smith whydoubt at gmail.com
Mon Nov 18 01:07:29 CST 2019


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
 dlls/msvcrt/time.c         | 86 ++++++++++++++++++--------------------
 dlls/ucrtbase/tests/misc.c |  2 +-
 2 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/dlls/msvcrt/time.c b/dlls/msvcrt/time.c
index 058a8a53c9..30f59e0846 100644
--- a/dlls/msvcrt/time.c
+++ b/dlls/msvcrt/time.c
@@ -54,6 +54,12 @@ static const int MonthLengths[2][12] =
     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 };
 
+#if _MSVCR_VER>=140
+static const int MAX_SECONDS = 60;
+#else
+static const int MAX_SECONDS = 59;
+#endif
+
 static inline BOOL IsLeapYear(int Year)
 {
     return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
@@ -954,45 +960,6 @@ char ** CDECL __p__tzname(void)
 	return MSVCRT__tzname;
 }
 
-static inline BOOL strftime_time(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max,
-        const struct MSVCRT_tm *mstm, MSVCRT___lc_time_data *time_data)
-{
-    SYSTEMTIME st;
-    MSVCRT_size_t ret;
-    LCID lcid;
-
-    st.wYear = mstm->tm_year + 1900;
-    st.wMonth = mstm->tm_mon + 1;
-    st.wDayOfWeek = mstm->tm_wday;
-    st.wDay = mstm->tm_mday;
-    st.wHour = mstm->tm_hour;
-    st.wMinute = mstm->tm_min;
-    st.wSecond = mstm->tm_sec;
-    st.wMilliseconds = 0;
-
-#if _MSVCR_VER < 110
-    lcid = time_data->lcid;
-#else
-    lcid = LocaleNameToLCID(time_data->locname, 0);
-#endif
-
-    ret = GetTimeFormatA(lcid, 0, &st, time_data->str.names.time, NULL, 0);
-    if(ret && ret<max-*pos)
-        ret = GetTimeFormatA(lcid, 0, &st, time_data->str.names.time,
-                str+*pos, max-*pos);
-    if(!ret) {
-        *str = 0;
-        *MSVCRT__errno() = MSVCRT_EINVAL;
-        return FALSE;
-    }else if(ret > max-*pos) {
-        *str = 0;
-        *MSVCRT__errno() = MSVCRT_ERANGE;
-        return FALSE;
-    }
-    *pos += ret-1;
-    return TRUE;
-}
-
 static inline BOOL strftime_tzdiff(char *str, MSVCRT_size_t *pos, MSVCRT_size_t max, BOOL is_dst)
 {
     MSVCRT_long tz = MSVCRT___timezone + (is_dst ? MSVCRT__dstbias : 0);
@@ -1117,10 +1084,39 @@ static inline BOOL strftime_format(char *str, MSVCRT_size_t *pos, MSVCRT_size_t
             while(*format == *substr) format++;
             /* TODO: era */
             break;
+        case 'h':
+            while(*format == *substr) format++;
+            if(!MSVCRT_CHECK_PMT(mstm->tm_hour>=0 && mstm->tm_hour<=23))
+                goto einval_error;
+            ret = strftime_int(str, pos, max, (mstm->tm_hour + 11) % 12 + 1,
+                    (format - substr < 2) ? 0 : 2, 1, 12);
+            break;
+        case 'H':
+            while(*format == *substr) format++;
+            ret = strftime_int(str, pos, max, mstm->tm_hour, (format - substr < 2) ? 0 : 2, 0, 23);
+            break;
+        case 'm':
+            while(*format == *substr) format++;
+            ret = strftime_int(str, pos, max, mstm->tm_min, (format - substr < 2) ? 0 : 2, 0, 59);
+            break;
+        case 's':
+            while(*format == *substr) format++;
+            ret = strftime_int(str, pos, max, mstm->tm_sec,
+                    (format - substr < 2) ? 0 : 2, 0, MAX_SECONDS);
+            break;
+        case 't':
+            while(*format == *substr) format++;
+            if(!MSVCRT_CHECK_PMT(mstm->tm_hour>=0 && mstm->tm_hour<=23))
+                goto einval_error;
+            ret = strftime_nstr(str, pos, max,
+                    (mstm->tm_hour < 12) ? time_data->str.names.am : time_data->str.names.pm,
+                    (format - substr < 2) ? 1 : MSVCRT_SIZE_MAX);
+            break;
         default:
             while(*format && *format != '\'' &&
-                  *format != 'd' && *format != 'M' &&
-                  *format != 'y' && *format != 'g')
+                  *format != 'd' && *format != 'M' && *format != 'y' &&
+                  *format != 'g' && *format != 'h' && *format != 'H' &&
+                  *format != 'm' && *format != 's' && *format != 't')
                 format++;
             ret = strftime_nstr(str, pos, max, substr, format - substr);
             break;
@@ -1182,7 +1178,7 @@ static MSVCRT_size_t strftime_helper(char *str, MSVCRT_size_t max, const char *f
                 return 0;
             if(ret < max)
                 str[ret++] = ' ';
-            if(!strftime_time(str, &ret, max, mstm, time_data))
+            if(!strftime_format(str, &ret, max, mstm, time_data, time_data->str.names.time))
                 return 0;
             break;
         case 'x':
@@ -1191,7 +1187,7 @@ static MSVCRT_size_t strftime_helper(char *str, MSVCRT_size_t max, const char *f
                 return 0;
             break;
         case 'X':
-            if(!strftime_time(str, &ret, max, mstm, time_data))
+            if(!strftime_format(str, &ret, max, mstm, time_data, time_data->str.names.time))
                 return 0;
             break;
         case 'a':
@@ -1329,7 +1325,7 @@ static MSVCRT_size_t strftime_helper(char *str, MSVCRT_size_t max, const char *f
             break;
 #endif
         case 'S':
-            if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, 59))
+            if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, MAX_SECONDS))
                 return 0;
             break;
 #if _MSVCR_VER>=140
@@ -1345,7 +1341,7 @@ static MSVCRT_size_t strftime_helper(char *str, MSVCRT_size_t max, const char *f
                 return 0;
             if(ret < max)
                 str[ret++] = ':';
-            if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, 59))
+            if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, MAX_SECONDS))
                 return 0;
             break;
         case 'u':
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c
index 35b7375cd8..3aca31734f 100644
--- a/dlls/ucrtbase/tests/misc.c
+++ b/dlls/ucrtbase/tests/misc.c
@@ -946,7 +946,7 @@ static void test_strftime(void)
         {"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
         {"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
         {"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }},
-        {"%X", "23:59:60", { 60, 59, 23, 1, 0, 70, 4, 0, 0 }, TRUE},
+        {"%X", "23:59:60", { 60, 59, 23, 1, 0, 70, 4, 0, 0 }},
     };
 
     const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 };
-- 
2.23.0




More information about the wine-devel mailing list