Skip to content

Commit 8346031

Browse files
Alexey Izbyshevvstinner
authored andcommitted
bpo-32890, os: Use errno instead of GetLastError() in execve() and truncate() (GH-5784)
path_error() uses GetLastError() on Windows, but some os functions are implemented via CRT APIs which report errors via errno. This may result in raising OSError with invalid error code (such as zero). Introduce posix_path_error() function and use it where appropriate.
1 parent a267056 commit 8346031

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

Lib/test/test_os.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,16 @@ def test_execve_invalid_env(self):
15891589
with self.assertRaises(ValueError):
15901590
os.execve(args[0], args, newenv)
15911591

1592+
@unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
1593+
def test_execve_with_empty_path(self):
1594+
# bpo-32890: Check GetLastError() misuse
1595+
try:
1596+
os.execve('', ['arg'], {})
1597+
except OSError as e:
1598+
self.assertTrue(e.winerror is None or e.winerror != 0)
1599+
else:
1600+
self.fail('No OSError raised')
1601+
15921602

15931603
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
15941604
class Win32ErrorTests(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix usage of GetLastError() instead of errno in os.execve() and
2+
os.truncate().

Modules/posixmodule.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,14 +1455,20 @@ win32_error_object(const char* function, PyObject* filename)
14551455

14561456
#endif /* MS_WINDOWS */
14571457

1458+
static PyObject *
1459+
posix_path_object_error(PyObject *path)
1460+
{
1461+
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1462+
}
1463+
14581464
static PyObject *
14591465
path_object_error(PyObject *path)
14601466
{
14611467
#ifdef MS_WINDOWS
14621468
return PyErr_SetExcFromWindowsErrWithFilenameObject(
14631469
PyExc_OSError, 0, path);
14641470
#else
1465-
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1471+
return posix_path_object_error(path);
14661472
#endif
14671473
}
14681474

@@ -1483,6 +1489,12 @@ path_error(path_t *path)
14831489
return path_object_error(path->object);
14841490
}
14851491

1492+
static PyObject *
1493+
posix_path_error(path_t *path)
1494+
{
1495+
return posix_path_object_error(path->object);
1496+
}
1497+
14861498
static PyObject *
14871499
path_error2(path_t *path, path_t *path2)
14881500
{
@@ -5141,7 +5153,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
51415153

51425154
/* If we get here it's definitely an error */
51435155

5144-
path_error(path);
5156+
posix_path_error(path);
51455157

51465158
free_string_array(envlist, envc);
51475159
fail:
@@ -9477,7 +9489,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
94779489
_Py_END_SUPPRESS_IPH
94789490
Py_END_ALLOW_THREADS
94799491
if (result < 0)
9480-
return path_error(path);
9492+
return posix_path_error(path);
94819493

94829494
Py_RETURN_NONE;
94839495
}

0 commit comments

Comments
 (0)