diff options
author | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2011-01-04 16:34:30 (GMT) |
---|---|---|
committer | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2011-01-04 16:34:30 (GMT) |
commit | b9588b528a48302a4884d0500caec71f1c59280c (patch) | |
tree | d1e04bad5afcc744fed2ef46253db5b79c9c0c39 /Modules | |
parent | 2427ab9d6f132224d6ee4a2b7f00b9d69ba6c0a3 (diff) | |
download | cpython-b9588b528a48302a4884d0500caec71f1c59280c.zip cpython-b9588b528a48302a4884d0500caec71f1c59280c.tar.gz cpython-b9588b528a48302a4884d0500caec71f1c59280c.tar.bz2 |
Issue #8013: time.asctime and time.ctime no longer call system asctime
and ctime functions. The year range for time.asctime is now 1900
through maxint. The range for time.ctime is the same as for
time.localtime. The string produced by these functions is longer than
24 characters when year is greater than 9999.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/timemodule.c | 61 |
1 files changed, 39 insertions, 22 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 4a0bacb..29a2f2d 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -599,19 +599,51 @@ time_strptime(PyObject *self, PyObject *args) return strptime_result; } + PyDoc_STRVAR(strptime_doc, "strptime(string, format) -> struct_time\n\ \n\ Parse a string to a time tuple according to a format specification.\n\ See the library reference manual for formatting codes (same as strftime())."); +static PyObject * +_asctime(struct tm *timeptr) +{ + /* Inspired by Open Group reference implementation available at + * http://pubs.opengroup.org/onlinepubs/009695399/functions/asctime.html */ + static char wday_name[7][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static char mon_name[12][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + char buf[20]; /* 'Sun Sep 16 01:03:52\0' */ + int n; + + n = snprintf(buf, sizeof(buf), "%.3s %.3s%3d %.2d:%.2d:%.2d", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec); + /* XXX: since the fields used by snprintf above are validated in checktm, + * the following condition should never trigger. We keep the check because + * historically fixed size buffer used in asctime was the source of + * crashes. */ + if (n + 1 != sizeof(buf)) { + PyErr_SetString(PyExc_ValueError, "unconvertible time"); + return NULL; + } + + return PyUnicode_FromFormat("%s %d", buf, 1900 + timeptr->tm_year); +} static PyObject * time_asctime(PyObject *self, PyObject *args) { PyObject *tup = NULL; struct tm buf; - char *p, *q; + if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup)) return NULL; if (tup == NULL) { @@ -619,17 +651,7 @@ time_asctime(PyObject *self, PyObject *args) buf = *localtime(&tt); } else if (!gettmarg(tup, &buf) || !checktm(&buf)) return NULL; - p = asctime(&buf); - if (p == NULL) { - PyErr_SetString(PyExc_ValueError, "unconvertible time"); - return NULL; - } - /* Replace a terminating newline by a null byte, normally at position 24. - * It can occur later if the year has more than four digits. */ - for (q = p+24; *q != '\0'; q++) - if (*q == '\n') - *q = '\0'; - return PyUnicode_FromString(p); + return _asctime(&buf); } PyDoc_STRVAR(asctime_doc, @@ -644,7 +666,7 @@ time_ctime(PyObject *self, PyObject *args) { PyObject *ot = NULL; time_t tt; - char *p, *q; + struct tm *timeptr; if (!PyArg_UnpackTuple(args, "ctime", 0, 1, &ot)) return NULL; @@ -658,17 +680,12 @@ time_ctime(PyObject *self, PyObject *args) if (tt == (time_t)-1 && PyErr_Occurred()) return NULL; } - p = ctime(&tt); - if (p == NULL) { + timeptr = localtime(&tt); + if (timeptr == NULL) { PyErr_SetString(PyExc_ValueError, "unconvertible time"); - return NULL; + return NULL; } - /* Replace a terminating newline by a null byte, normally at position 24. - * It can occur later if the year has more than four digits. */ - for (q = p+24; *q != '\0'; q++) - if (*q == '\n') - *q = '\0'; - return PyUnicode_FromString(p); + return _asctime(timeptr); } PyDoc_STRVAR(ctime_doc, |