Skip to content

Commit d9a2665

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 75ee130 commit d9a2665

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
@@ -1582,6 +1582,16 @@ def test_execve_invalid_env(self):
15821582
with self.assertRaises(ValueError):
15831583
os.execve(args[0], args, newenv)
15841584

1585+
@unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
1586+
def test_execve_with_empty_path(self):
1587+
# bpo-32890: Check GetLastError() misuse
1588+
try:
1589+
os.execve('', ['arg'], {})
1590+
except OSError as e:
1591+
self.assertTrue(e.winerror is None or e.winerror != 0)
1592+
else:
1593+
self.fail('No OSError raised')
1594+
15851595

15861596
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
15871597
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
@@ -1340,14 +1340,20 @@ win32_error_object(const char* function, PyObject* filename)
13401340

13411341
#endif /* MS_WINDOWS */
13421342

1343+
static PyObject *
1344+
posix_path_object_error(PyObject *path)
1345+
{
1346+
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1347+
}
1348+
13431349
static PyObject *
13441350
path_object_error(PyObject *path)
13451351
{
13461352
#ifdef MS_WINDOWS
13471353
return PyErr_SetExcFromWindowsErrWithFilenameObject(
13481354
PyExc_OSError, 0, path);
13491355
#else
1350-
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1356+
return posix_path_object_error(path);
13511357
#endif
13521358
}
13531359

@@ -1368,6 +1374,12 @@ path_error(path_t *path)
13681374
return path_object_error(path->object);
13691375
}
13701376

1377+
static PyObject *
1378+
posix_path_error(path_t *path)
1379+
{
1380+
return posix_path_object_error(path->object);
1381+
}
1382+
13711383
static PyObject *
13721384
path_error2(path_t *path, path_t *path2)
13731385
{
@@ -5041,7 +5053,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
50415053

50425054
/* If we get here it's definitely an error */
50435055

5044-
path_error(path);
5056+
posix_path_error(path);
50455057

50465058
free_string_array(envlist, envc);
50475059
fail:
@@ -8770,7 +8782,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
87708782
_Py_END_SUPPRESS_IPH
87718783
Py_END_ALLOW_THREADS
87728784
if (result < 0)
8773-
return path_error(path);
8785+
return posix_path_error(path);
87748786

87758787
Py_RETURN_NONE;
87768788
}

0 commit comments

Comments
 (0)