Skip to content

Commit 32bc11c

Browse files
bpo-35371: Fix possible crash in os.utime() on Windows. (GH-10844)
1 parent edeca92 commit 32bc11c

File tree

3 files changed

+40
-22
lines changed

3 files changed

+40
-22
lines changed

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
@@ -4689,7 +4689,6 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46894689
int result;
46904690
#endif
46914691

4692-
PyObject *return_value = NULL;
46934692
utime_t utime;
46944693

46954694
memset(&utime, 0, sizeof(utime_t));
@@ -4698,7 +4697,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
46984697
PyErr_SetString(PyExc_ValueError,
46994698
"utime: you may specify either 'times'"
47004699
" or 'ns' but not both");
4701-
goto exit;
4700+
return NULL;
47024701
}
47034702

47044703
if (times && (times != Py_None)) {
@@ -4708,14 +4707,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47084707
PyErr_SetString(PyExc_TypeError,
47094708
"utime: 'times' must be either"
47104709
" a tuple of two ints or None");
4711-
goto exit;
4710+
return NULL;
47124711
}
47134712
utime.now = 0;
47144713
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
47154714
&a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
47164715
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
47174716
&m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4718-
goto exit;
4717+
return NULL;
47194718
}
47204719
utime.atime_s = a_sec;
47214720
utime.atime_ns = a_nsec;
@@ -4726,14 +4725,14 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47264725
if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
47274726
PyErr_SetString(PyExc_TypeError,
47284727
"utime: 'ns' must be a tuple of two ints");
4729-
goto exit;
4728+
return NULL;
47304729
}
47314730
utime.now = 0;
47324731
if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
47334732
&utime.atime_s, &utime.atime_ns) ||
47344733
!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
47354734
&utime.mtime_s, &utime.mtime_ns)) {
4736-
goto exit;
4735+
return NULL;
47374736
}
47384737
}
47394738
else {
@@ -4743,20 +4742,20 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47434742

47444743
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
47454744
if (follow_symlinks_specified("utime", follow_symlinks))
4746-
goto exit;
4745+
return NULL;
47474746
#endif
47484747

47494748
if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
47504749
dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
47514750
fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4752-
goto exit;
4751+
return NULL;
47534752

47544753
#if !defined(HAVE_UTIMENSAT)
47554754
if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
47564755
PyErr_SetString(PyExc_ValueError,
47574756
"utime: cannot use dir_fd and follow_symlinks "
47584757
"together on this platform");
4759-
goto exit;
4758+
return NULL;
47604759
}
47614760
#endif
47624761

@@ -4768,7 +4767,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47684767
Py_END_ALLOW_THREADS
47694768
if (hFile == INVALID_HANDLE_VALUE) {
47704769
path_error(path);
4771-
goto exit;
4770+
return NULL;
47724771
}
47734772

47744773
if (utime.now) {
@@ -4785,8 +4784,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
47854784
something is wrong with the file, when it also
47864785
could be the time stamp that gives a problem. */
47874786
PyErr_SetFromWindowsErr(0);
4788-
goto exit;
4787+
CloseHandle(hFile);
4788+
return NULL;
47894789
}
4790+
CloseHandle(hFile);
47904791
#else /* MS_WINDOWS */
47914792
Py_BEGIN_ALLOW_THREADS
47924793

@@ -4814,21 +4815,13 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
48144815

48154816
if (result < 0) {
48164817
/* see previous comment about not putting filename in error here */
4817-
return_value = posix_error();
4818-
goto exit;
4818+
posix_error();
4819+
return NULL;
48194820
}
48204821

48214822
#endif /* MS_WINDOWS */
48224823

4823-
Py_INCREF(Py_None);
4824-
return_value = Py_None;
4825-
4826-
exit:
4827-
#ifdef MS_WINDOWS
4828-
if (hFile != INVALID_HANDLE_VALUE)
4829-
CloseHandle(hFile);
4830-
#endif
4831-
return return_value;
4824+
Py_RETURN_NONE;
48324825
}
48334826

48344827
/* Process operations */

0 commit comments

Comments
 (0)