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 834603112e)

Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
This commit is contained in:
Miss Islington (bot) 2018-10-19 17:46:25 -07:00 committed by GitHub
parent 3e5bcd12f6
commit 8f53dcdb24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 3 deletions

View File

@ -1589,6 +1589,16 @@ class ExecTests(unittest.TestCase):
with self.assertRaises(ValueError):
os.execve(args[0], args, newenv)
@unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
def test_execve_with_empty_path(self):
# bpo-32890: Check GetLastError() misuse
try:
os.execve('', ['arg'], {})
except OSError as e:
self.assertTrue(e.winerror is None or e.winerror != 0)
else:
self.fail('No OSError raised')
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
class Win32ErrorTests(unittest.TestCase):

View File

@ -0,0 +1,2 @@
Fix usage of GetLastError() instead of errno in os.execve() and
os.truncate().

View File

@ -1421,6 +1421,12 @@ win32_error_object(const char* function, PyObject* filename)
#endif /* MS_WINDOWS */
static PyObject *
posix_path_object_error(PyObject *path)
{
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
}
static PyObject *
path_object_error(PyObject *path)
{
@ -1428,7 +1434,7 @@ path_object_error(PyObject *path)
return PyErr_SetExcFromWindowsErrWithFilenameObject(
PyExc_OSError, 0, path);
#else
return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
return posix_path_object_error(path);
#endif
}
@ -1449,6 +1455,12 @@ path_error(path_t *path)
return path_object_error(path->object);
}
static PyObject *
posix_path_error(path_t *path)
{
return posix_path_object_error(path->object);
}
static PyObject *
path_error2(path_t *path, path_t *path2)
{
@ -5097,7 +5109,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
/* If we get here it's definitely an error */
path_error(path);
posix_path_error(path);
free_string_array(envlist, envc);
fail:
@ -9060,7 +9072,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
if (result < 0)
return path_error(path);
return posix_path_error(path);
Py_RETURN_NONE;
}