From b333640aba212e8f2b70fd5038fe160492666dca Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Fri, 4 May 2012 02:31:57 -0700 Subject: [PATCH] Issue #14127: Fix two bugs with the Windows implementation. --- Modules/posixmodule.c | 61 +++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6cabe37753c..2dbfec1fbce 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3658,9 +3658,17 @@ typedef struct { /* * utime_read_time_arguments() processes arguments for the utime * family of functions. - * returns zero on failure. */ -static int + +typedef enum { + utime_success = 0, + utime_parse_failure = 1, + utime_times_and_ns_collision = 2, + utime_times_conversion_failure = 3, + utime_ns_conversion_failure = 4, +} utime_status; + +static utime_status utime_read_time_arguments(utime_arguments *ua) { PyObject *times = NULL; @@ -3668,7 +3676,8 @@ utime_read_time_arguments(utime_arguments *ua) char format[24]; char *kwlist[4]; char **kw = kwlist; - int return_value; + utime_status return_value; + int parse_result; *kw++ = ua->first_argument_name; *kw++ = "times"; @@ -3681,20 +3690,21 @@ utime_read_time_arguments(utime_arguments *ua) ua->function_name); if (ua->converter) - return_value = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs, + parse_result = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs, format, kwlist, ua->converter, ua->path, ×, &ns); else - return_value = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs, + parse_result = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs, format, kwlist, ua->path, ×, &ns); - if (!return_value) - return 0; + if (!parse_result) + return utime_parse_failure; if (times && ns) { PyErr_Format(PyExc_RuntimeError, "%s: you may specify either 'times'" " or 'ns' but not both", ua->function_name); + return_value = utime_times_and_ns_collision; goto fail; } @@ -3704,15 +3714,18 @@ utime_read_time_arguments(utime_arguments *ua) "%s: 'time' must be either" " a tuple of two ints or None", ua->function_name); + return_value = utime_times_conversion_failure; goto fail; } ua->now = 0; if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), &ua->atime_s, &ua->atime_ns) == -1 || _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &ua->mtime_s, &ua->mtime_ns) == -1) + &ua->mtime_s, &ua->mtime_ns) == -1) { + return_value = utime_times_conversion_failure; goto fail; - return 1; + } + return utime_success; } if (ns) { @@ -3720,25 +3733,28 @@ utime_read_time_arguments(utime_arguments *ua) PyErr_Format(PyExc_TypeError, "%s: 'ns' must be a tuple of two ints", ua->function_name); + return_value = utime_ns_conversion_failure; goto fail; } ua->now = 0; if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0), &ua->atime_s, &ua->atime_ns) || !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1), - &ua->mtime_s, &ua->mtime_ns)) + &ua->mtime_s, &ua->mtime_ns)) { + return_value = utime_ns_conversion_failure; goto fail; - return 1; + } + return utime_success; } /* either times=None, or neither times nor ns was specified. use "now". */ ua->now = 1; - return 1; + return utime_success; fail: if (ua->converter) Py_DECREF(ua->path); - return 0; + return return_value; } @@ -3767,7 +3783,10 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) ua.path_format = 'U'; ua.path = &upath; - if (!utime_read_time_arguments(&ua)) { + switch (utime_read_time_arguments(&ua)) { + default: + return NULL; + case utime_success: { wchar_t *wpath = PyUnicode_AsUnicode(upath); if (wpath == NULL) return NULL; @@ -3778,8 +3797,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) return win32_error_object("utime", upath); + break; } - else { + case utime_parse_failure: { const char *apath; /* Drop the argument parsing error as narrow strings are also valid. */ @@ -3787,7 +3807,7 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) ua.path_format = 'y'; ua.path = (PyObject **)&apath; - if (!utime_read_time_arguments(&ua)) + if (utime_read_time_arguments(&ua) != utime_success) return NULL; if (win32_warn_bytes_api()) return NULL; @@ -3801,6 +3821,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) win32_error("utime", apath); return NULL; } + break; + } + } if (ua.now) { @@ -3839,7 +3862,7 @@ done: ua.path = &opath; ua.converter = PyUnicode_FSConverter; - if (!utime_read_time_arguments(&ua)) + if (utime_read_time_arguments(&ua) != utime_success) return NULL; path = PyBytes_AsString(opath); if (ua.now) { @@ -3892,7 +3915,7 @@ posix_futimes(PyObject *self, PyObject *args, PyObject *kwargs) ua.path = (PyObject **)&fd; ua.first_argument_name = "fd"; - if (!utime_read_time_arguments(&ua)) + if (utime_read_time_arguments(&ua) != utime_success) return NULL; if (ua.now) { @@ -3937,7 +3960,7 @@ posix_lutimes(PyObject *self, PyObject *args, PyObject *kwargs) ua.path = &opath; ua.converter = PyUnicode_FSConverter; - if (!utime_read_time_arguments(&ua)) + if (utime_read_time_arguments(&ua) != utime_success) return NULL; path = PyBytes_AsString(opath);