Skip to content

Commit 8f53dcd

Browse files
miss-islingtonAlexey Izbyshev
andauthored
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. (cherry picked from commit 8346031) Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
1 parent 3e5bcd1 commit 8f53dcd

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
@@ -1421,14 +1421,20 @@ win32_error_object(const char* function, PyObject* filename)
14211421

14221422
#endif /* MS_WINDOWS */
14231423

1424+
static PyObject *
1425+
posix_path_object_error(PyObject *path)
1426+
{
1427+
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1428+
}
1429+
14241430
static PyObject *
14251431
path_object_error(PyObject *path)
14261432
{
14271433
#ifdef MS_WINDOWS
14281434
return PyErr_SetExcFromWindowsErrWithFilenameObject(
14291435
PyExc_OSError, 0, path);
14301436
#else
1431-
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1437+
return posix_path_object_error(path);
14321438
#endif
14331439
}
14341440

@@ -1449,6 +1455,12 @@ path_error(path_t *path)
14491455
return path_object_error(path->object);
14501456
}
14511457

1458+
static PyObject *
1459+
posix_path_error(path_t *path)
1460+
{
1461+
return posix_path_object_error(path->object);
1462+
}
1463+
14521464
static PyObject *
14531465
path_error2(path_t *path, path_t *path2)
14541466
{
@@ -5097,7 +5109,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
50975109

50985110
/* If we get here it's definitely an error */
50995111

5100-
path_error(path);
5112+
posix_path_error(path);
51015113

51025114
free_string_array(envlist, envc);
51035115
fail:
@@ -9060,7 +9072,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
90609072
_Py_END_SUPPRESS_IPH
90619073
Py_END_ALLOW_THREADS
90629074
if (result < 0)
9063-
return path_error(path);
9075+
return posix_path_error(path);
90649076

90659077
Py_RETURN_NONE;
90669078
}

0 commit comments

Comments
 (0)