Commit 32bc11c3 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-35371: Fix possible crash in os.utime() on Windows. (GH-10844)

parent edeca92c
...@@ -634,6 +634,29 @@ class UtimeTests(unittest.TestCase): ...@@ -634,6 +634,29 @@ class UtimeTests(unittest.TestCase):
# seconds and nanoseconds parameters are mutually exclusive # seconds and nanoseconds parameters are mutually exclusive
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
os.utime(self.fname, (5, 5), ns=(5, 5)) os.utime(self.fname, (5, 5), ns=(5, 5))
with self.assertRaises(TypeError):
os.utime(self.fname, [5, 5])
with self.assertRaises(TypeError):
os.utime(self.fname, (5,))
with self.assertRaises(TypeError):
os.utime(self.fname, (5, 5, 5))
with self.assertRaises(TypeError):
os.utime(self.fname, ns=[5, 5])
with self.assertRaises(TypeError):
os.utime(self.fname, ns=(5,))
with self.assertRaises(TypeError):
os.utime(self.fname, ns=(5, 5, 5))
if os.utime not in os.supports_follow_symlinks:
with self.assertRaises(NotImplementedError):
os.utime(self.fname, (5, 5), follow_symlinks=False)
if os.utime not in os.supports_fd:
with open(self.fname, 'wb', 0) as fp:
with self.assertRaises(TypeError):
os.utime(fp.fileno(), (5, 5))
if os.utime not in os.supports_dir_fd:
with self.assertRaises(NotImplementedError):
os.utime(self.fname, (5, 5), dir_fd=0)
@support.cpython_only @support.cpython_only
def test_issue31577(self): def test_issue31577(self):
......
Fixed possible crash in ``os.utime()`` on Windows when pass incorrect
arguments.
...@@ -4689,7 +4689,6 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4689,7 +4689,6 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
int result; int result;
#endif #endif
PyObject *return_value = NULL;
utime_t utime; utime_t utime;
memset(&utime, 0, sizeof(utime_t)); memset(&utime, 0, sizeof(utime_t));
...@@ -4698,7 +4697,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4698,7 +4697,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"utime: you may specify either 'times'" "utime: you may specify either 'times'"
" or 'ns' but not both"); " or 'ns' but not both");
goto exit; return NULL;
} }
if (times && (times != Py_None)) { if (times && (times != Py_None)) {
...@@ -4708,14 +4707,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4708,14 +4707,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"utime: 'times' must be either" "utime: 'times' must be either"
" a tuple of two ints or None"); " a tuple of two ints or None");
goto exit; return NULL;
} }
utime.now = 0; utime.now = 0;
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
&a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
&m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
goto exit; return NULL;
} }
utime.atime_s = a_sec; utime.atime_s = a_sec;
utime.atime_ns = a_nsec; utime.atime_ns = a_nsec;
...@@ -4726,14 +4725,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4726,14 +4725,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"utime: 'ns' must be a tuple of two ints"); "utime: 'ns' must be a tuple of two ints");
goto exit; return NULL;
} }
utime.now = 0; utime.now = 0;
if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0), if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
&utime.atime_s, &utime.atime_ns) || &utime.atime_s, &utime.atime_ns) ||
!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1), !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
&utime.mtime_s, &utime.mtime_ns)) { &utime.mtime_s, &utime.mtime_ns)) {
goto exit; return NULL;
} }
} }
else { else {
...@@ -4743,20 +4742,20 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4743,20 +4742,20 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
if (follow_symlinks_specified("utime", follow_symlinks)) if (follow_symlinks_specified("utime", follow_symlinks))
goto exit; return NULL;
#endif #endif
if (path_and_dir_fd_invalid("utime", path, dir_fd) || if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
goto exit; return NULL;
#if !defined(HAVE_UTIMENSAT) #if !defined(HAVE_UTIMENSAT)
if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"utime: cannot use dir_fd and follow_symlinks " "utime: cannot use dir_fd and follow_symlinks "
"together on this platform"); "together on this platform");
goto exit; return NULL;
} }
#endif #endif
...@@ -4768,7 +4767,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4768,7 +4767,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (hFile == INVALID_HANDLE_VALUE) { if (hFile == INVALID_HANDLE_VALUE) {
path_error(path); path_error(path);
goto exit; return NULL;
} }
if (utime.now) { if (utime.now) {
...@@ -4785,8 +4784,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4785,8 +4784,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
something is wrong with the file, when it also something is wrong with the file, when it also
could be the time stamp that gives a problem. */ could be the time stamp that gives a problem. */
PyErr_SetFromWindowsErr(0); PyErr_SetFromWindowsErr(0);
goto exit; CloseHandle(hFile);
return NULL;
} }
CloseHandle(hFile);
#else /* MS_WINDOWS */ #else /* MS_WINDOWS */
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
...@@ -4814,21 +4815,13 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, ...@@ -4814,21 +4815,13 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
if (result < 0) { if (result < 0) {
/* see previous comment about not putting filename in error here */ /* see previous comment about not putting filename in error here */
return_value = posix_error(); posix_error();
goto exit; return NULL;
} }
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
Py_INCREF(Py_None); Py_RETURN_NONE;
return_value = Py_None;
exit:
#ifdef MS_WINDOWS
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
#endif
return return_value;
} }
/* Process operations */ /* Process operations */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment