Skip to content

Commit 013832f

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 1e28daf commit 013832f

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
@@ -660,6 +660,29 @@ def test_utime_invalid_arguments(self):
660660
# seconds and nanoseconds parameters are mutually exclusive
661661
with self.assertRaises(ValueError):
662662
os.utime(self.fname, (5, 5), ns=(5, 5))
663+
with self.assertRaises(TypeError):
664+
os.utime(self.fname, [5, 5])
665+
with self.assertRaises(TypeError):
666+
os.utime(self.fname, (5,))
667+
with self.assertRaises(TypeError):
668+
os.utime(self.fname, (5, 5, 5))
669+
with self.assertRaises(TypeError):
670+
os.utime(self.fname, ns=[5, 5])
671+
with self.assertRaises(TypeError):
672+
os.utime(self.fname, ns=(5,))
673+
with self.assertRaises(TypeError):
674+
os.utime(self.fname, ns=(5, 5, 5))
675+
676+
if os.utime not in os.supports_follow_symlinks:
677+
with self.assertRaises(NotImplementedError):
678+
os.utime(self.fname, (5, 5), follow_symlinks=False)
679+
if os.utime not in os.supports_fd:
680+
with open(self.fname, 'wb', 0) as fp:
681+
with self.assertRaises(TypeError):
682+
os.utime(fp.fileno(), (5, 5))
683+
if os.utime not in os.supports_dir_fd:
684+
with self.assertRaises(NotImplementedError):
685+
os.utime(self.fname, (5, 5), dir_fd=0)
663686

664687

665688
from test import mapping_tests
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
@@ -4589,7 +4589,6 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
45894589
int result;
45904590
#endif
45914591

4592-
PyObject *return_value = NULL;
45934592
utime_t utime;
45944593

45954594
memset(&utime, 0, sizeof(utime_t));
@@ -4598,7 +4597,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
45984597
PyErr_SetString(PyExc_ValueError,
45994598
"utime: you may specify either 'times'"
46004599
" or 'ns' but not both");
4601-
goto exit;
4600+
return NULL;
46024601
}
46034602

46044603
if (times && (times != Py_None)) {
@@ -4608,14 +4607,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46084607
PyErr_SetString(PyExc_TypeError,
46094608
"utime: 'times' must be either"
46104609
" a tuple of two ints or None");
4611-
goto exit;
4610+
return NULL;
46124611
}
46134612
utime.now = 0;
46144613
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
46154614
&a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
46164615
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
46174616
&m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4618-
goto exit;
4617+
return NULL;
46194618
}
46204619
utime.atime_s = a_sec;
46214620
utime.atime_ns = a_nsec;
@@ -4626,14 +4625,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46264625
if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
46274626
PyErr_SetString(PyExc_TypeError,
46284627
"utime: 'ns' must be a tuple of two ints");
4629-
goto exit;
4628+
return NULL;
46304629
}
46314630
utime.now = 0;
46324631
if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
46334632
&utime.atime_s, &utime.atime_ns) ||
46344633
!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
46354634
&utime.mtime_s, &utime.mtime_ns)) {
4636-
goto exit;
4635+
return NULL;
46374636
}
46384637
}
46394638
else {
@@ -4643,20 +4642,20 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46434642

46444643
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
46454644
if (follow_symlinks_specified("utime", follow_symlinks))
4646-
goto exit;
4645+
return NULL;
46474646
#endif
46484647

46494648
if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
46504649
dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
46514650
fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4652-
goto exit;
4651+
return NULL;
46534652

46544653
#if !defined(HAVE_UTIMENSAT)
46554654
if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
46564655
PyErr_SetString(PyExc_ValueError,
46574656
"utime: cannot use dir_fd and follow_symlinks "
46584657
"together on this platform");
4659-
goto exit;
4658+
return NULL;
46604659
}
46614660
#endif
46624661

@@ -4668,7 +4667,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46684667
Py_END_ALLOW_THREADS
46694668
if (hFile == INVALID_HANDLE_VALUE) {
46704669
path_error(path);
4671-
goto exit;
4670+
return NULL;
46724671
}
46734672

46744673
if (utime.now) {
@@ -4685,8 +4684,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46854684
something is wrong with the file, when it also
46864685
could be the time stamp that gives a problem. */
46874686
PyErr_SetFromWindowsErr(0);
4688-
goto exit;
4687+
CloseHandle(hFile);
4688+
return NULL;
46894689
}
4690+
CloseHandle(hFile);
46904691
#else /* MS_WINDOWS */
46914692
Py_BEGIN_ALLOW_THREADS
46924693

@@ -4714,21 +4715,13 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47144715

47154716
if (result < 0) {
47164717
/* see previous comment about not putting filename in error here */
4717-
return_value = posix_error();
4718-
goto exit;
4718+
posix_error();
4719+
return NULL;
47194720
}
47204721

47214722
#endif /* MS_WINDOWS */
47224723

4723-
Py_INCREF(Py_None);
4724-
return_value = Py_None;
4725-
4726-
exit:
4727-
#ifdef MS_WINDOWS
4728-
if (hFile != INVALID_HANDLE_VALUE)
4729-
CloseHandle(hFile);
4730-
#endif
4731-
return return_value;
4724+
Py_RETURN_NONE;
47324725
}
47334726

47344727
/* Process operations */

0 commit comments

Comments
 (0)