Skip to content

Commit 265b419

Browse files
bpo-35371: Fix possible crash in os.utime() on Windows. (GH-10844)
(cherry picked from commit 32bc11c) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 7da9755 commit 265b419

3 files changed

Lines changed: 40 additions & 22 deletions

File tree

Lib/test/test_os.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,29 @@ def test_utime_invalid_arguments(self):
634634
# seconds and nanoseconds parameters are mutually exclusive
635635
with self.assertRaises(ValueError):
636636
os.utime(self.fname, (5, 5), ns=(5, 5))
637+
with self.assertRaises(TypeError):
638+
os.utime(self.fname, [5, 5])
639+
with self.assertRaises(TypeError):
640+
os.utime(self.fname, (5,))
641+
with self.assertRaises(TypeError):
642+
os.utime(self.fname, (5, 5, 5))
643+
with self.assertRaises(TypeError):
644+
os.utime(self.fname, ns=[5, 5])
645+
with self.assertRaises(TypeError):
646+
os.utime(self.fname, ns=(5,))
647+
with self.assertRaises(TypeError):
648+
os.utime(self.fname, ns=(5, 5, 5))
649+
650+
if os.utime not in os.supports_follow_symlinks:
651+
with self.assertRaises(NotImplementedError):
652+
os.utime(self.fname, (5, 5), follow_symlinks=False)
653+
if os.utime not in os.supports_fd:
654+
with open(self.fname, 'wb', 0) as fp:
655+
with self.assertRaises(TypeError):
656+
os.utime(fp.fileno(), (5, 5))
657+
if os.utime not in os.supports_dir_fd:
658+
with self.assertRaises(NotImplementedError):
659+
os.utime(self.fname, (5, 5), dir_fd=0)
637660

638661
@support.cpython_only
639662
def test_issue31577(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed possible crash in ``os.utime()`` on Windows when pass incorrect
2+
arguments.

Modules/posixmodule.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4645,7 +4645,6 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46454645
int result;
46464646
#endif
46474647

4648-
PyObject *return_value = NULL;
46494648
utime_t utime;
46504649

46514650
memset(&utime, 0, sizeof(utime_t));
@@ -4654,7 +4653,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46544653
PyErr_SetString(PyExc_ValueError,
46554654
"utime: you may specify either 'times'"
46564655
" or 'ns' but not both");
4657-
goto exit;
4656+
return NULL;
46584657
}
46594658

46604659
if (times && (times != Py_None)) {
@@ -4664,14 +4663,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46644663
PyErr_SetString(PyExc_TypeError,
46654664
"utime: 'times' must be either"
46664665
" a tuple of two ints or None");
4667-
goto exit;
4666+
return NULL;
46684667
}
46694668
utime.now = 0;
46704669
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
46714670
&a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
46724671
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
46734672
&m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4674-
goto exit;
4673+
return NULL;
46754674
}
46764675
utime.atime_s = a_sec;
46774676
utime.atime_ns = a_nsec;
@@ -4682,14 +4681,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46824681
if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
46834682
PyErr_SetString(PyExc_TypeError,
46844683
"utime: 'ns' must be a tuple of two ints");
4685-
goto exit;
4684+
return NULL;
46864685
}
46874686
utime.now = 0;
46884687
if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
46894688
&utime.atime_s, &utime.atime_ns) ||
46904689
!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
46914690
&utime.mtime_s, &utime.mtime_ns)) {
4692-
goto exit;
4691+
return NULL;
46934692
}
46944693
}
46954694
else {
@@ -4699,20 +4698,20 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46994698

47004699
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
47014700
if (follow_symlinks_specified("utime", follow_symlinks))
4702-
goto exit;
4701+
return NULL;
47034702
#endif
47044703

47054704
if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
47064705
dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
47074706
fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4708-
goto exit;
4707+
return NULL;
47094708

47104709
#if !defined(HAVE_UTIMENSAT)
47114710
if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
47124711
PyErr_SetString(PyExc_ValueError,
47134712
"utime: cannot use dir_fd and follow_symlinks "
47144713
"together on this platform");
4715-
goto exit;
4714+
return NULL;
47164715
}
47174716
#endif
47184717

@@ -4724,7 +4723,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47244723
Py_END_ALLOW_THREADS
47254724
if (hFile == INVALID_HANDLE_VALUE) {
47264725
path_error(path);
4727-
goto exit;
4726+
return NULL;
47284727
}
47294728

47304729
if (utime.now) {
@@ -4741,8 +4740,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47414740
something is wrong with the file, when it also
47424741
could be the time stamp that gives a problem. */
47434742
PyErr_SetFromWindowsErr(0);
4744-
goto exit;
4743+
CloseHandle(hFile);
4744+
return NULL;
47454745
}
4746+
CloseHandle(hFile);
47464747
#else /* MS_WINDOWS */
47474748
Py_BEGIN_ALLOW_THREADS
47484749

@@ -4770,21 +4771,13 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47704771

47714772
if (result < 0) {
47724773
/* see previous comment about not putting filename in error here */
4773-
return_value = posix_error();
4774-
goto exit;
4774+
posix_error();
4775+
return NULL;
47754776
}
47764777

47774778
#endif /* MS_WINDOWS */
47784779

4779-
Py_INCREF(Py_None);
4780-
return_value = Py_None;
4781-
4782-
exit:
4783-
#ifdef MS_WINDOWS
4784-
if (hFile != INVALID_HANDLE_VALUE)
4785-
CloseHandle(hFile);
4786-
#endif
4787-
return return_value;
4780+
Py_RETURN_NONE;
47884781
}
47894782

47904783
/* Process operations */

0 commit comments

Comments
 (0)