| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8abc3f4 commit 8709490
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Fix :func:`time.mktime` error handling on AIX for year before 1970. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -990,60 +990,68 @@ not present, current time as returned by localtime() is used."); | |||
| 990 | 990 | ||
| 991 | 991 | #ifdef HAVE_MKTIME | |
| 992 | 992 | static PyObject * | |
| 993 | - time_mktime(PyObject *self, PyObject *tup) | ||
| 993 | + time_mktime(PyObject *self, PyObject *tm_tuple) | ||
| 994 | 994 | { | |
| 995 | - struct tm buf; | ||
| 995 | + struct tm tm; | ||
| 996 | 996 | time_t tt; | |
| 997 | - #ifdef _AIX | ||
| 998 | - time_t clk; | ||
| 999 | - int year = buf.tm_year; | ||
| 1000 | - int delta_days = 0; | ||
| 1001 | - #endif | ||
| 1002 | 997 | ||
| 1003 | - if (!gettmarg(tup, &buf, | ||
| 998 | + if (!gettmarg(tm_tuple, &tm, | ||
| 1004 | 999 | "iiiiiiiii;mktime(): illegal time tuple argument")) | |
| 1005 | 1000 | { | |
| 1006 | 1001 | return NULL; | |
| 1007 | 1002 | } | |
| 1008 | - #ifndef _AIX | ||
| 1009 | - buf.tm_wday = -1; /* sentinel; original value ignored */ | ||
| 1010 | - tt = mktime(&buf); | ||
| 1011 | - #else | ||
| 1012 | - /* year < 1902 or year > 2037 */ | ||
| 1013 | - if ((buf.tm_year < 2) || (buf.tm_year > 137)) { | ||
| 1014 | - /* Issue #19748: On AIX, mktime() doesn't report overflow error for | ||
| 1015 | - * timestamp < -2^31 or timestamp > 2**31-1. */ | ||
| 1003 | + | ||
| 1004 | + #ifdef _AIX | ||
| 1005 | + /* bpo-19748: AIX mktime() valid range is 00:00:00 UTC, January 1, 1970 | ||
| 1006 | + to 03:14:07 UTC, January 19, 2038. Thanks to the workaround below, | ||
| 1007 | + it is possible to support years in range [1902; 2037] */ | ||
| 1008 | + if (tm.tm_year < 2 || tm.tm_year > 137) { | ||
| 1009 | + /* bpo-19748: On AIX, mktime() does not report overflow error | ||
| 1010 | + for timestamp < -2^31 or timestamp > 2**31-1. */ | ||
| 1016 | 1011 | PyErr_SetString(PyExc_OverflowError, | |
| 1017 | 1012 | "mktime argument out of range"); | |
| 1018 | 1013 | return NULL; | |
| 1019 | 1014 | } | |
| 1020 | - year = buf.tm_year; | ||
| 1021 | - /* year < 1970 - adjust buf.tm_year into legal range */ | ||
| 1022 | - while (buf.tm_year < 70) { | ||
| 1023 | - buf.tm_year += 4; | ||
| 1015 | + | ||
| 1016 | + /* bpo-34373: AIX mktime() has an integer overflow for years in range | ||
| 1017 | + [1902; 1969]. Workaround the issue by using a year greater or equal than | ||
| 1018 | + 1970 (tm_year >= 70): mktime() behaves correctly in that case | ||
| 1019 | + (ex: properly report errors). tm_year and tm_wday are adjusted after | ||
| 1020 | + mktime() call. */ | ||
| 1021 | + int orig_tm_year = tm.tm_year; | ||
| 1022 | + int delta_days = 0; | ||
| 1023 | + while (tm.tm_year < 70) { | ||
| 1024 | + /* Use 4 years to account properly leap years */ | ||
| 1025 | + tm.tm_year += 4; | ||
| 1024 | 1026 | delta_days -= (366 + (365 * 3)); | |
| 1025 | 1027 | } | |
| 1028 | + #endif | ||
| 1026 | 1029 | ||
| 1027 | - buf.tm_wday = -1; | ||
| 1028 | - clk = mktime(&buf); | ||
| 1029 | - buf.tm_year = year; | ||
| 1030 | - | ||
| 1031 | - if ((buf.tm_wday != -1) && delta_days) | ||
| 1032 | - buf.tm_wday = (buf.tm_wday + delta_days) % 7; | ||
| 1030 | + tm.tm_wday = -1; /* sentinel; original value ignored */ | ||
| 1031 | + tt = mktime(&tm); | ||
| 1033 | 1032 | ||
| 1034 | - tt = clk + (delta_days * (24 * 3600)); | ||
| 1035 | - #endif | ||
| 1036 | 1033 | /* Return value of -1 does not necessarily mean an error, but tm_wday | |
| 1037 | 1034 | * cannot remain set to -1 if mktime succeeded. */ | |
| 1038 | 1035 | if (tt == (time_t)(-1) | |
| 1039 | 1036 | /* Return value of -1 does not necessarily mean an error, but | |
| 1040 | 1037 | * tm_wday cannot remain set to -1 if mktime succeeded. */ | |
| 1041 | - && buf.tm_wday == -1) | ||
| 1038 | + && tm.tm_wday == -1) | ||
| 1042 | 1039 | { | |
| 1043 | 1040 | PyErr_SetString(PyExc_OverflowError, | |
| 1044 | 1041 | "mktime argument out of range"); | |
| 1045 | 1042 | return NULL; | |
| 1046 | 1043 | } | |
| 1044 | + | ||
| 1045 | + #ifdef _AIX | ||
| 1046 | + if (delta_days != 0) { | ||
| 1047 | + tm.tm_year = orig_tm_year; | ||
| 1048 | + if (tm.tm_wday != -1) { | ||
| 1049 | + tm.tm_wday = (tm.tm_wday + delta_days) % 7; | ||
| 1050 | + } | ||
| 1051 | + tt += delta_days * (24 * 3600); | ||
| 1052 | + } | ||
| 1053 | + #endif | ||
| 1054 | + | ||
| 1047 | 1055 | return PyFloat_FromDouble((double)tt); | |
| 1048 | 1056 | } | |
| 1049 | 1057 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1062,26 +1062,23 @@ _PyTime_localtime(time_t t, struct tm *tm) | |||
| 1062 | 1062 | } | |
| 1063 | 1063 | return 0; | |
| 1064 | 1064 | #else /* !MS_WINDOWS */ | |
| 1065 | + | ||
| 1065 | 1066 | #ifdef _AIX | |
| 1066 | - /* AIX does not return NULL on an error | ||
| 1067 | - so test ranges - asif! | ||
| 1068 | - (1902-01-01, -2145916800.0) | ||
| 1069 | - (2038-01-01, 2145916800.0) */ | ||
| 1070 | - if (abs(t) > (time_t) 2145916800) { | ||
| 1071 | - #ifdef EINVAL | ||
| 1067 | + /* bpo-34373: AIX does not return NULL if t is too small or too large */ | ||
| 1068 | + if (t < -2145916800 /* 1902-01-01 */ | ||
| 1069 | + || t > 2145916800 /* 2038-01-01 */) { | ||
| 1072 | 1070 | errno = EINVAL; | |
| 1073 | - #endif | ||
| 1074 | 1071 | PyErr_SetString(PyExc_OverflowError, | |
| 1075 | - "ctime argument out of range"); | ||
| 1072 | + "localtime argument out of range"); | ||
| 1076 | 1073 | return -1; | |
| 1077 | 1074 | } | |
| 1078 | 1075 | #endif | |
| 1076 | + | ||
| 1077 | + errno = 0; | ||
| 1079 | 1078 | if (localtime_r(&t, tm) == NULL) { | |
| 1080 | - #ifdef EINVAL | ||
| 1081 | 1079 | if (errno == 0) { | |
| 1082 | 1080 | errno = EINVAL; | |
| 1083 | 1081 | } | |
| 1084 | - #endif | ||
| 1085 | 1082 | PyErr_SetFromErrno(PyExc_OSError); | |
| 1086 | 1083 | return -1; | |
| 1087 | 1084 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments