From 740ae7d4e192f389a9695844313e73d987800fbf Mon Sep 17 00:00:00 2001 From: Ethan Furman Date: Sat, 4 Jun 2016 12:06:26 -0700 Subject: issue27186: add C version of os.fspath(); patch by Jelle Zijlstra --- Modules/posixmodule.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ded6d716eb..c55226576c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12284,6 +12284,56 @@ error: return NULL; } +/* + Return the file system path representation of the object. + + If the object is str or bytes, then allow it to pass through with + an incremented refcount. If the object defines __fspath__(), then + return the result of that method. All other types raise a TypeError. +*/ +PyObject * +PyOS_FSPath(PyObject *path) +{ + _Py_IDENTIFIER(__fspath__); + PyObject *func = NULL; + PyObject *path_repr = NULL; + + if (PyUnicode_Check(path) || PyBytes_Check(path)) { + Py_INCREF(path); + return path; + } + + func = _PyObject_LookupSpecial(path, &PyId___fspath__); + if (NULL == func) { + return PyErr_Format(PyExc_TypeError, + "expected str, bytes or os.PathLike object, " + "not %S", + path->ob_type); + } + + path_repr = PyObject_CallFunctionObjArgs(func, NULL); + Py_DECREF(func); + return path_repr; +} + +/*[clinic input] +os.fspath + + path: object + +Return the file system path representation of the object. + +If the object is str or bytes, then allow it to pass through with +an incremented refcount. If the object defines __fspath__(), then +return the result of that method. All other types raise a TypeError. +[clinic start generated code]*/ + +static PyObject * +os_fspath_impl(PyModuleDef *module, PyObject *path) +/*[clinic end generated code: output=51ef0c2772c1932a input=652c7c37e4be1c13]*/ +{ + return PyOS_FSPath(path); +} #include "clinic/posixmodule.c.h" @@ -12484,6 +12534,7 @@ static PyMethodDef posix_methods[] = { {"scandir", (PyCFunction)posix_scandir, METH_VARARGS | METH_KEYWORDS, posix_scandir__doc__}, + OS_FSPATH_METHODDEF {NULL, NULL} /* Sentinel */ }; -- cgit v1.2.1 From 1f48144f1b96cca0f69320e353810bc13b64f180 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 9 Jun 2016 14:32:08 -0700 Subject: Clarify documentation for os.fspath(). --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c55226576c..f4510dbec9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12323,14 +12323,14 @@ os.fspath Return the file system path representation of the object. -If the object is str or bytes, then allow it to pass through with -an incremented refcount. If the object defines __fspath__(), then -return the result of that method. All other types raise a TypeError. +If the object is str or bytes, then allow it to pass through as-is. If the +object defines __fspath__(), then return the result of that method. All other +types raise a TypeError. [clinic start generated code]*/ static PyObject * os_fspath_impl(PyModuleDef *module, PyObject *path) -/*[clinic end generated code: output=51ef0c2772c1932a input=652c7c37e4be1c13]*/ +/*[clinic end generated code: output=51ef0c2772c1932a input=e357165f7b22490f]*/ { return PyOS_FSPath(path); } -- cgit v1.2.1 From 2d3cd9e42e536185d9b1c6acbb4b900a848f5204 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 10 Jun 2016 14:37:21 -0700 Subject: Issue #27186: Add os.PathLike support to DirEntry Initial patch thanks to Jelle Zijlstra. --- Modules/posixmodule.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index f4510dbec9..ecdeab4925 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11718,6 +11718,13 @@ DirEntry_repr(DirEntry *self) return PyUnicode_FromFormat("", self->name); } +static PyObject * +DirEntry_fspath(DirEntry *self) +{ + Py_INCREF(self->path); + return self->path; +} + static PyMemberDef DirEntry_members[] = { {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, "the entry's base filename, relative to scandir() \"path\" argument"}, @@ -11742,6 +11749,9 @@ static PyMethodDef DirEntry_methods[] = { {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS, "return inode of the entry; cached per entry", }, + {"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS, + "returns the path for the entry", + }, {NULL} }; -- cgit v1.2.1 From 70619426311f86acbcade7d399288baa9c5cba52 Mon Sep 17 00:00:00 2001 From: doko Date: Mon, 13 Jun 2016 16:33:04 +0200 Subject: - Comment out socket (SO_REUSEPORT) and posix (O_SHLOCK, O_EXLOCK) constants exposed on the API which are not implemented on GNU/Hurd. They would not work at runtime anyway. --- Modules/posixmodule.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ecdeab4925..7d8249095d 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12658,12 +12658,14 @@ all_ins(PyObject *m) #ifdef O_LARGEFILE if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; #endif +#ifndef __GNU__ #ifdef O_SHLOCK if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; #endif #ifdef O_EXLOCK if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; #endif +#endif #ifdef O_EXEC if (PyModule_AddIntMacro(m, O_EXEC)) return -1; #endif -- cgit v1.2.1 From a52c718a5d46902bbe429710e02f45f738565889 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 24 Jun 2016 12:03:43 -0700 Subject: Issue #27186: Update os.fspath()/PyOS_FSPath() to check the return type of __fspath__(). As part of this change, also make sure that the pure Python implementation of os.fspath() is tested. --- Modules/posixmodule.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 7d8249095d..df802cbc09 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12317,12 +12317,21 @@ PyOS_FSPath(PyObject *path) if (NULL == func) { return PyErr_Format(PyExc_TypeError, "expected str, bytes or os.PathLike object, " - "not %S", - path->ob_type); + "not %.200s", + Py_TYPE(path)->tp_name); } path_repr = PyObject_CallFunctionObjArgs(func, NULL); Py_DECREF(func); + if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", Py_TYPE(path)->tp_name, + Py_TYPE(path_repr)->tp_name); + Py_DECREF(path_repr); + return NULL; + } + return path_repr; } -- cgit v1.2.1 From 8ecaa879ea3137279269eb78ead7ad57c1d269e0 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 24 Jun 2016 14:14:44 -0700 Subject: Issue #27038: Expose DirEntry as os.DirEntry. Thanks to Jelle Zijlstra for the code portion of the patch. --- Modules/posixmodule.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index df802cbc09..4dc7c49465 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -13320,6 +13320,7 @@ INITFUNC(void) Py_DECREF(unicode); } PyModule_AddObject(m, "_have_functions", list); + PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType); initialized = 1; -- cgit v1.2.1 From 03e4d0c5c6c7af36230ec72d1ad7842cf1e887ef Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 15 Jul 2016 10:41:49 -0700 Subject: Issue #27512: Don't segfault when os.fspath() calls an object whose __fspath__() raises an exception. Thanks to Xiang Zhang for the patch. --- Modules/posixmodule.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4c0f26e89c..7f16a83e78 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12319,6 +12319,10 @@ PyOS_FSPath(PyObject *path) path_repr = PyObject_CallFunctionObjArgs(func, NULL); Py_DECREF(func); + if (NULL == path_repr) { + return NULL; + } + if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { PyErr_Format(PyExc_TypeError, "expected %.200s.__fspath__() to return str or bytes, " -- cgit v1.2.1 From 21ba6ba34d5b3648d13f9944dc9a66c29893edf3 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Thu, 4 Aug 2016 02:38:59 +0000 Subject: Issue #17599: Use unique _Py_REPARSE_DATA_BUFFER etc names to avoid conflict The conflict occurs with Min GW, which already defines REPARSE_DATA_BUFFER. Also, Min GW uses a lowercase filename. --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 54685ae7f0..6adc7f44db 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1106,8 +1106,8 @@ _PyVerify_fd_dup2(int fd1, int fd2) static int win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) { - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; DWORD n_bytes_returned; if (0 == DeviceIoControl( @@ -7149,8 +7149,8 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) int dir_fd; HANDLE reparse_point_handle; - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; const wchar_t *print_name; static char *keywords[] = {"path", "dir_fd", NULL}; -- cgit v1.2.1 From bb2540a70ca8864f8c62210872762fc7d0cc3a01 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 6 Aug 2016 23:22:08 +0300 Subject: Issue #26800: Undocumented support of general bytes-like objects as paths in os functions is now deprecated. --- Modules/posixmodule.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6adc7f44db..52e465f1ff 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -891,7 +891,28 @@ path_converter(PyObject *o, void *p) } #endif } + else if (PyBytes_Check(o)) { +#ifdef MS_WINDOWS + if (win32_warn_bytes_api()) { + return 0; + } +#endif + bytes = o; + Py_INCREF(bytes); + } else if (PyObject_CheckBuffer(o)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "%s%s%s should be %s, not %.200s", + path->function_name ? path->function_name : "", + path->function_name ? ": " : "", + path->argument_name ? path->argument_name : "path", + path->allow_fd && path->nullable ? "string, bytes, integer or None" : + path->allow_fd ? "string, bytes or integer" : + path->nullable ? "string, bytes or None" : + "string or bytes", + Py_TYPE(o)->tp_name)) { + return 0; + } #ifdef MS_WINDOWS if (win32_warn_bytes_api()) { return 0; @@ -946,8 +967,14 @@ path_converter(PyObject *o, void *p) path->length = length; path->object = o; path->fd = -1; - path->cleanup = bytes; - return Py_CLEANUP_SUPPORTED; + if (bytes == o) { + Py_DECREF(bytes); + return 1; + } + else { + path->cleanup = bytes; + return Py_CLEANUP_SUPPORTED; + } } static void -- cgit v1.2.1 From c5a43ba5e7f08d539f3ed286d5b2781d9597caa1 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Mon, 15 Aug 2016 14:40:38 -0400 Subject: Issue #27736: Prevent segfault after interpreter re-initialization due to ref count problem introduced in code for Issue #27038 in 3.6.0a3. Patch by Xiang Zhang. --- Modules/posixmodule.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 52e465f1ff..10d6bcbba9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -13355,6 +13355,8 @@ INITFUNC(void) Py_DECREF(unicode); } PyModule_AddObject(m, "_have_functions", list); + + Py_INCREF((PyObject *) &DirEntryType); PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType); initialized = 1; -- cgit v1.2.1 From af8fbafe368b5cc4432e47bb0e38fd1e5c119840 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 26 Aug 2016 14:44:48 -0700 Subject: Issue #26027, #27524: Add PEP 519/__fspath__() support to os and os.path. Thanks to Jelle Zijlstra for the initial patch against posixmodule.c. --- Modules/posixmodule.c | 104 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 29 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 10d6bcbba9..f9693e8d57 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -834,8 +834,11 @@ static int path_converter(PyObject *o, void *p) { path_t *path = (path_t *)p; - PyObject *bytes; + PyObject *bytes, *to_cleanup = NULL; Py_ssize_t length; + int is_index, is_buffer, is_bytes, is_unicode; + /* Default to failure, forcing explicit signaling of succcess. */ + int ret = 0; const char *narrow; #define FORMAT_EXCEPTION(exc, fmt) \ @@ -850,7 +853,7 @@ path_converter(PyObject *o, void *p) return 1; } - /* ensure it's always safe to call path_cleanup() */ + /* Ensure it's always safe to call path_cleanup(). */ path->cleanup = NULL; if ((o == Py_None) && path->nullable) { @@ -862,21 +865,54 @@ path_converter(PyObject *o, void *p) return 1; } - if (PyUnicode_Check(o)) { + /* Only call this here so that we don't treat the return value of + os.fspath() as an fd or buffer. */ + is_index = path->allow_fd && PyIndex_Check(o); + is_buffer = PyObject_CheckBuffer(o); + is_bytes = PyBytes_Check(o); + is_unicode = PyUnicode_Check(o); + + if (!is_index && !is_buffer && !is_unicode && !is_bytes) { + /* Inline PyOS_FSPath() for better error messages. */ + _Py_IDENTIFIER(__fspath__); + PyObject *func = NULL; + + func = _PyObject_LookupSpecial(o, &PyId___fspath__); + if (NULL == func) { + goto error_exit; + } + + o = to_cleanup = PyObject_CallFunctionObjArgs(func, NULL); + Py_DECREF(func); + if (NULL == o) { + goto error_exit; + } + else if (PyUnicode_Check(o)) { + is_unicode = 1; + } + else if (PyBytes_Check(o)) { + is_bytes = 1; + } + else { + goto error_exit; + } + } + + if (is_unicode) { #ifdef MS_WINDOWS const wchar_t *wide; wide = PyUnicode_AsUnicodeAndSize(o, &length); if (!wide) { - return 0; + goto exit; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - return 0; + goto exit; } if (wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - return 0; + goto exit; } path->wide = wide; @@ -884,66 +920,71 @@ path_converter(PyObject *o, void *p) path->length = length; path->object = o; path->fd = -1; - return 1; + ret = 1; + goto exit; #else if (!PyUnicode_FSConverter(o, &bytes)) { - return 0; + goto exit; } #endif } - else if (PyBytes_Check(o)) { + else if (is_bytes) { #ifdef MS_WINDOWS if (win32_warn_bytes_api()) { - return 0; + goto exit; } #endif bytes = o; Py_INCREF(bytes); } - else if (PyObject_CheckBuffer(o)) { + else if (is_buffer) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "%s%s%s should be %s, not %.200s", path->function_name ? path->function_name : "", path->function_name ? ": " : "", path->argument_name ? path->argument_name : "path", - path->allow_fd && path->nullable ? "string, bytes, integer or None" : - path->allow_fd ? "string, bytes or integer" : - path->nullable ? "string, bytes or None" : - "string or bytes", + path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " + "integer or None" : + path->allow_fd ? "string, bytes, os.PathLike or integer" : + path->nullable ? "string, bytes, os.PathLike or None" : + "string, bytes or os.PathLike", Py_TYPE(o)->tp_name)) { - return 0; + goto exit; } #ifdef MS_WINDOWS if (win32_warn_bytes_api()) { - return 0; + goto exit; } #endif bytes = PyBytes_FromObject(o); if (!bytes) { - return 0; + goto exit; } } else if (path->allow_fd && PyIndex_Check(o)) { if (!_fd_converter(o, &path->fd)) { - return 0; + goto exit; } path->wide = NULL; path->narrow = NULL; path->length = 0; path->object = o; - return 1; + ret = 1; + goto exit; } else { + error_exit: PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", path->function_name ? path->function_name : "", path->function_name ? ": " : "", path->argument_name ? path->argument_name : "path", - path->allow_fd && path->nullable ? "string, bytes, integer or None" : - path->allow_fd ? "string, bytes or integer" : - path->nullable ? "string, bytes or None" : - "string or bytes", + path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " + "integer or None" : + path->allow_fd ? "string, bytes, os.PathLike or integer" : + path->nullable ? "string, bytes, os.PathLike or None" : + "string, bytes or os.PathLike", Py_TYPE(o)->tp_name); - return 0; + goto exit; } length = PyBytes_GET_SIZE(bytes); @@ -951,7 +992,7 @@ path_converter(PyObject *o, void *p) if (length > MAX_PATH-1) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); Py_DECREF(bytes); - return 0; + goto exit; } #endif @@ -959,7 +1000,7 @@ path_converter(PyObject *o, void *p) if ((size_t)length != strlen(narrow)) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); Py_DECREF(bytes); - return 0; + goto exit; } path->wide = NULL; @@ -969,12 +1010,15 @@ path_converter(PyObject *o, void *p) path->fd = -1; if (bytes == o) { Py_DECREF(bytes); - return 1; + ret = 1; } else { path->cleanup = bytes; - return Py_CLEANUP_SUPPORTED; + ret = Py_CLEANUP_SUPPORTED; } + exit: + Py_XDECREF(to_cleanup); + return ret; } static void @@ -12329,6 +12373,8 @@ error: PyObject * PyOS_FSPath(PyObject *path) { + /* For error message reasons, this function is manually inlined in + path_converter(). */ _Py_IDENTIFIER(__fspath__); PyObject *func = NULL; PyObject *path_repr = NULL; -- cgit v1.2.1 From 907ccded8b6fa68f6f572ae5de6760595df0d5a1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 5 Sep 2016 17:44:18 -0700 Subject: require a long long data type (closes #27961) --- Modules/posixmodule.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c9ac1f783e..21d91b03df 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -640,22 +640,14 @@ fail: #endif /* MS_WINDOWS */ -#ifdef HAVE_LONG_LONG -# define _PyLong_FromDev PyLong_FromLongLong -#else -# define _PyLong_FromDev PyLong_FromLong -#endif +#define _PyLong_FromDev PyLong_FromLongLong #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) static int _Py_Dev_Converter(PyObject *obj, void *p) { -#ifdef HAVE_LONG_LONG *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); -#else - *((dev_t *)p) = PyLong_AsUnsignedLong(obj); -#endif if (PyErr_Occurred()) return 0; return 1; -- cgit v1.2.1 From 914b59533a094e815809f62441d02b560e23057b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 6 Sep 2016 10:46:49 -0700 Subject: replace PY_LONG_LONG with long long --- Modules/posixmodule.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 21d91b03df..df295c25b6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1108,7 +1108,7 @@ dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, } #ifdef MS_WINDOWS - typedef PY_LONG_LONG Py_off_t; + typedef long long Py_off_t; #else typedef off_t Py_off_t; #endif @@ -2073,7 +2073,7 @@ _pystat_fromstructstat(STRUCT_STAT *st) PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); #ifdef HAVE_LARGEFILE_SUPPORT PyStructSequence_SET_ITEM(v, 1, - PyLong_FromLongLong((PY_LONG_LONG)st->st_ino)); + PyLong_FromLongLong((long long)st->st_ino)); #else PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino)); #endif @@ -2092,7 +2092,7 @@ _pystat_fromstructstat(STRUCT_STAT *st) #endif #ifdef HAVE_LARGEFILE_SUPPORT PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG)st->st_size)); + PyLong_FromLongLong((long long)st->st_size)); #else PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size)); #endif @@ -9420,17 +9420,17 @@ _pystatvfs_fromstructstatvfs(struct statvfs st) { PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); + PyLong_FromLongLong((long long) st.f_blocks)); PyStructSequence_SET_ITEM(v, 3, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); + PyLong_FromLongLong((long long) st.f_bfree)); PyStructSequence_SET_ITEM(v, 4, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); + PyLong_FromLongLong((long long) st.f_bavail)); PyStructSequence_SET_ITEM(v, 5, - PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); + PyLong_FromLongLong((long long) st.f_files)); PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); + PyLong_FromLongLong((long long) st.f_ffree)); PyStructSequence_SET_ITEM(v, 7, - PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); + PyLong_FromLongLong((long long) st.f_favail)); PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); #endif @@ -11763,10 +11763,10 @@ DirEntry_inode(DirEntry *self) self->win32_file_index = stat.st_ino; self->got_file_index = 1; } - return PyLong_FromLongLong((PY_LONG_LONG)self->win32_file_index); + return PyLong_FromLongLong((long long)self->win32_file_index); #else /* POSIX */ #ifdef HAVE_LARGEFILE_SUPPORT - return PyLong_FromLongLong((PY_LONG_LONG)self->d_ino); + return PyLong_FromLongLong((long long)self->d_ino); #else return PyLong_FromLong((long)self->d_ino); #endif -- cgit v1.2.1 From 82b75eb31160ec9c025e450ac9fa3300d560a245 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 6 Sep 2016 13:47:26 -0700 Subject: replace Py_(u)intptr_t with the c99 standard types --- Modules/posixmodule.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index df295c25b6..e88ee56fa0 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2492,8 +2492,8 @@ class id_t_converter(CConverter): type = 'id_t' format_unit = '" _Py_PARSE_PID "' -class Py_intptr_t_converter(CConverter): - type = 'Py_intptr_t' +class intptr_t_converter(CConverter): + type = 'intptr_t' format_unit = '" _Py_PARSE_INTPTR "' class Py_off_t_converter(CConverter): @@ -5244,7 +5244,7 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) char **argvlist; int i; Py_ssize_t argc; - Py_intptr_t spawnval; + intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); /* spawnv has three arguments: (mode, path, argv), where @@ -5323,7 +5323,7 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, char **envlist; PyObject *res = NULL; Py_ssize_t argc, i, envc; - Py_intptr_t spawnval; + intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); Py_ssize_t lastarg = 0; @@ -7078,7 +7078,7 @@ os_waitpid_impl(PyObject *module, pid_t pid, int options) /* MS C has a variant of waitpid() that's usable for most purposes. */ /*[clinic input] os.waitpid - pid: Py_intptr_t + pid: intptr_t options: int / @@ -7091,11 +7091,11 @@ The options argument is ignored on Windows. [clinic start generated code]*/ static PyObject * -os_waitpid_impl(PyObject *module, Py_intptr_t pid, int options) +os_waitpid_impl(PyObject *module, intptr_t pid, int options) /*[clinic end generated code: output=15f1ce005a346b09 input=444c8f51cca5b862]*/ { int status; - Py_intptr_t res; + intptr_t res; int async_err = 0; do { @@ -8559,8 +8559,8 @@ os_pipe_impl(PyObject *module) Py_BEGIN_ALLOW_THREADS ok = CreatePipe(&read, &write, &attr, 0); if (ok) { - fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY); - fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY); + fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY); + fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY); if (fds[0] == -1 || fds[1] == -1) { CloseHandle(read); CloseHandle(write); @@ -11375,14 +11375,14 @@ os_set_inheritable_impl(PyObject *module, int fd, int inheritable) #ifdef MS_WINDOWS /*[clinic input] os.get_handle_inheritable -> bool - handle: Py_intptr_t + handle: intptr_t / Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ static int -os_get_handle_inheritable_impl(PyObject *module, Py_intptr_t handle) +os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) /*[clinic end generated code: output=9e5389b0aa0916ce input=5f7759443aae3dc5]*/ { DWORD flags; @@ -11398,7 +11398,7 @@ os_get_handle_inheritable_impl(PyObject *module, Py_intptr_t handle) /*[clinic input] os.set_handle_inheritable - handle: Py_intptr_t + handle: intptr_t inheritable: bool / @@ -11406,7 +11406,7 @@ Set the inheritable flag of the specified handle. [clinic start generated code]*/ static PyObject * -os_set_handle_inheritable_impl(PyObject *module, Py_intptr_t handle, +os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable) /*[clinic end generated code: output=b1e67bfa3213d745 input=e64b2b2730469def]*/ { -- cgit v1.2.1 From 903d792642f162c92dede5edc166c9696f45c7ee Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Sep 2016 15:54:20 -0700 Subject: Run Argument Clinic on posixmodule.c Issue #17884. --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e88ee56fa0..beea9e0812 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2520,7 +2520,7 @@ class sched_param_converter(CConverter): impl_by_reference = True; [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/ /*[clinic input] @@ -7092,7 +7092,7 @@ The options argument is ignored on Windows. static PyObject * os_waitpid_impl(PyObject *module, intptr_t pid, int options) -/*[clinic end generated code: output=15f1ce005a346b09 input=444c8f51cca5b862]*/ +/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ { int status; intptr_t res; @@ -11383,7 +11383,7 @@ Get the close-on-exe flag of the specified file descriptor. static int os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) -/*[clinic end generated code: output=9e5389b0aa0916ce input=5f7759443aae3dc5]*/ +/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ { DWORD flags; @@ -11408,7 +11408,7 @@ Set the inheritable flag of the specified handle. static PyObject * os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable) -/*[clinic end generated code: output=b1e67bfa3213d745 input=e64b2b2730469def]*/ +/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ { DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { -- cgit v1.2.1 From b0d817f3e501393694cb1b6ffd47c60195578ce1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Sep 2016 16:18:52 -0700 Subject: Add os.getrandom() Issue #27778: Expose the Linux getrandom() syscall as a new os.getrandom() function. This change is part of the PEP 524. --- Modules/posixmodule.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index beea9e0812..2dc6d7b940 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -133,6 +133,13 @@ corresponding Unix manual entries for more information on calls."); #include #endif +#ifdef HAVE_LINUX_RANDOM_H +# include +#endif +#ifdef HAVE_GETRANDOM_SYSCALL +# include +#endif + #if defined(MS_WINDOWS) # define TERMSIZE_USE_CONIO #elif defined(HAVE_SYS_IOCTL_H) @@ -12421,6 +12428,59 @@ os_fspath_impl(PyObject *module, PyObject *path) return PyOS_FSPath(path); } +#ifdef HAVE_GETRANDOM_SYSCALL +/*[clinic input] +os.getrandom + + size: Py_ssize_t + flags: int=0 + +Obtain a series of random bytes. +[clinic start generated code]*/ + +static PyObject * +os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) +/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ +{ + char *buffer; + Py_ssize_t n; + PyObject *bytes; + + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + + buffer = PyMem_Malloc(size); + if (buffer == NULL) { + PyErr_NoMemory(); + return NULL; + } + + while (1) { + n = syscall(SYS_getrandom, buffer, size, flags); + if (n < 0 && errno == EINTR) { + if (PyErr_CheckSignals() < 0) { + return NULL; + } + continue; + } + break; + } + + if (n < 0) { + PyMem_Free(buffer); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + bytes = PyBytes_FromStringAndSize(buffer, n); + PyMem_Free(buffer); + + return bytes; +} +#endif /* HAVE_GETRANDOM_SYSCALL */ + #include "clinic/posixmodule.c.h" /*[clinic input] @@ -12621,6 +12681,7 @@ static PyMethodDef posix_methods[] = { METH_VARARGS | METH_KEYWORDS, posix_scandir__doc__}, OS_FSPATH_METHODDEF + OS_GETRANDOM_METHODDEF {NULL, NULL} /* Sentinel */ }; @@ -13066,6 +13127,11 @@ all_ins(PyObject *m) if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; #endif +#ifdef HAVE_GETRANDOM_SYSCALL + if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; + if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1; +#endif + return 0; } -- cgit v1.2.1 From 87da9f01c3bc74aebedc52a91aa908ddae83a579 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Sep 2016 16:33:52 -0700 Subject: os.urandom() now blocks on Linux Issue #27776: The os.urandom() function does now block on Linux 3.17 and newer until the system urandom entropy pool is initialized to increase the security. This change is part of the PEP 524. --- Modules/posixmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2dc6d7b940..0b9b3f617f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11168,8 +11168,7 @@ os_urandom_impl(PyObject *module, Py_ssize_t size) if (bytes == NULL) return NULL; - result = _PyOS_URandom(PyBytes_AS_STRING(bytes), - PyBytes_GET_SIZE(bytes)); + result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); if (result == -1) { Py_DECREF(bytes); return NULL; -- cgit v1.2.1 From 1f022f2790687b29bbf555d0e18fcc4486cd48dc Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 7 Sep 2016 14:45:10 -0700 Subject: more linux -> __linux__ --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0b9b3f617f..161704fcae 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8446,7 +8446,7 @@ done: if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", keywords, &out, &in, &offobj, &count)) return NULL; -#ifdef linux +#ifdef __linux__ if (offobj == Py_None) { do { Py_BEGIN_ALLOW_THREADS -- cgit v1.2.1 From 9c9a45c1f0a264d3006971b8211d948d6883a05b Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 8 Sep 2016 10:35:16 -0700 Subject: Issue #27781: Change file system encoding on Windows to UTF-8 (PEP 529) --- Modules/posixmodule.c | 925 ++++++++++++++++---------------------------------- 1 file changed, 285 insertions(+), 640 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 161704fcae..a39ea651fd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -164,6 +164,8 @@ corresponding Unix manual entries for more information on calls."); #define HAVE_GETLOGIN 1 #define HAVE_SPAWNV 1 #define HAVE_EXECV 1 +#define HAVE_WSPAWNV 1 +#define HAVE_WEXECV 1 #define HAVE_PIPE 1 #define HAVE_SYSTEM 1 #define HAVE_CWAIT 1 @@ -735,7 +737,7 @@ dir_fd_converter(PyObject *o, void *p) * * * On Windows, if we get a (Unicode) string we * extract the wchar_t * and return it; if we get - * bytes we extract the char * and return that. + * bytes we decode to wchar_t * and return that. * * * On all other platforms, strings are encoded * to bytes using PyUnicode_FSConverter, then we @@ -767,7 +769,9 @@ dir_fd_converter(PyObject *o, void *p) * and was not encoded. (Only used on Windows.) * path.narrow * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. + * or it was Unicode and was encoded to bytes. (On Windows, + * is an non-zero integer if the path was expressed as bytes. + * The type is deliberately incompatible to prevent misuse.) * path.fd * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any @@ -812,15 +816,24 @@ typedef struct { int nullable; int allow_fd; const wchar_t *wide; +#ifdef MS_WINDOWS + BOOL narrow; +#else const char *narrow; +#endif int fd; Py_ssize_t length; PyObject *object; PyObject *cleanup; } path_t; +#ifdef MS_WINDOWS +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ + {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} +#else #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#endif static void path_cleanup(path_t *path) { @@ -839,6 +852,10 @@ path_converter(PyObject *o, void *p) /* Default to failure, forcing explicit signaling of succcess. */ int ret = 0; const char *narrow; +#ifdef MS_WINDOWS + PyObject *wo; + const wchar_t *wide; +#endif #define FORMAT_EXCEPTION(exc, fmt) \ PyErr_Format(exc, "%s%s" fmt, \ @@ -857,7 +874,11 @@ path_converter(PyObject *o, void *p) if ((o == Py_None) && path->nullable) { path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else path->narrow = NULL; +#endif path->length = 0; path->object = o; path->fd = -1; @@ -899,9 +920,7 @@ path_converter(PyObject *o, void *p) if (is_unicode) { #ifdef MS_WINDOWS - const wchar_t *wide; - - wide = PyUnicode_AsUnicodeAndSize(o, &length); + wide = PyUnicode_AsWideCharString(o, &length); if (!wide) { goto exit; } @@ -915,7 +934,6 @@ path_converter(PyObject *o, void *p) } path->wide = wide; - path->narrow = NULL; path->length = length; path->object = o; path->fd = -1; @@ -928,11 +946,6 @@ path_converter(PyObject *o, void *p) #endif } else if (is_bytes) { -#ifdef MS_WINDOWS - if (win32_warn_bytes_api()) { - goto exit; - } -#endif bytes = o; Py_INCREF(bytes); } @@ -950,22 +963,21 @@ path_converter(PyObject *o, void *p) Py_TYPE(o)->tp_name)) { goto exit; } -#ifdef MS_WINDOWS - if (win32_warn_bytes_api()) { - goto exit; - } -#endif bytes = PyBytes_FromObject(o); if (!bytes) { goto exit; } } - else if (path->allow_fd && PyIndex_Check(o)) { + else if (is_index) { if (!_fd_converter(o, &path->fd)) { goto exit; } path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else path->narrow = NULL; +#endif path->length = 0; path->object = o; ret = 1; @@ -987,14 +999,6 @@ path_converter(PyObject *o, void *p) } length = PyBytes_GET_SIZE(bytes); -#ifdef MS_WINDOWS - if (length > MAX_PATH-1) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - Py_DECREF(bytes); - goto exit; - } -#endif - narrow = PyBytes_AS_STRING(bytes); if ((size_t)length != strlen(narrow)) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); @@ -1002,8 +1006,35 @@ path_converter(PyObject *o, void *p) goto exit; } +#ifdef MS_WINDOWS + wo = PyUnicode_DecodeFSDefaultAndSize( + narrow, + length + ); + if (!wo) { + goto exit; + } + + wide = PyUnicode_AsWideCharString(wo, &length); + Py_DECREF(wo); + + if (!wide) { + goto exit; + } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto exit; + } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto exit; + } + path->wide = wide; + path->narrow = TRUE; +#else path->wide = NULL; path->narrow = narrow; +#endif path->length = length; path->object = o; path->fd = -1; @@ -1067,7 +1098,11 @@ follow_symlinks_specified(const char *function_name, int follow_symlinks) static int path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) { - if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) { + if (!path->wide && (dir_fd != DEFAULT_DIR_FD) +#ifndef MS_WINDOWS + && !path->narrow +#endif + ) { PyErr_Format(PyExc_ValueError, "%s: can't specify dir_fd without matching path", function_name); @@ -1397,31 +1432,6 @@ posix_fildes_fd(int fd, int (*func)(int)) it also needs to set "magic" environment variables indicating the per-drive current directory, which are of the form =: */ static BOOL __stdcall -win32_chdir(LPCSTR path) -{ - char new_path[MAX_PATH]; - int result; - char env[4] = "=x:"; - - if(!SetCurrentDirectoryA(path)) - return FALSE; - result = GetCurrentDirectoryA(Py_ARRAY_LENGTH(new_path), new_path); - if (!result) - return FALSE; - /* In the ANSI API, there should not be any paths longer - than MAX_PATH-1 (not including the final null character). */ - assert(result < Py_ARRAY_LENGTH(new_path)); - if (strncmp(new_path, "\\\\", 2) == 0 || - strncmp(new_path, "//", 2) == 0) - /* UNC path, nothing to do. */ - return TRUE; - env[1] = new_path[0]; - return SetEnvironmentVariableA(env, new_path); -} - -/* The Unicode version differs from the ANSI version - since the current directory might exceed MAX_PATH characters */ -static BOOL __stdcall win32_wchdir(LPCWSTR path) { wchar_t path_buf[MAX_PATH], *new_path = path_buf; @@ -1467,33 +1477,10 @@ win32_wchdir(LPCWSTR path) #define HAVE_STAT_NSEC 1 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 -static BOOL -attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) -{ - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - memset(info, 0, sizeof(*info)); - *reparse_tag = 0; - info->dwFileAttributes = FileData.dwFileAttributes; - info->ftCreationTime = FileData.ftCreationTime; - info->ftLastAccessTime = FileData.ftLastAccessTime; - info->ftLastWriteTime = FileData.ftLastWriteTime; - info->nFileSizeHigh = FileData.nFileSizeHigh; - info->nFileSizeLow = FileData.nFileSizeLow; -/* info->nNumberOfLinks = 1; */ - if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - *reparse_tag = FileData.dwReserved0; - return TRUE; -} - static void -find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData, - BY_HANDLE_FILE_INFORMATION *info, - ULONG *reparse_tag) +find_data_to_file_info(WIN32_FIND_DATAW *pFileData, + BY_HANDLE_FILE_INFORMATION *info, + ULONG *reparse_tag) { memset(info, 0, sizeof(*info)); info->dwFileAttributes = pFileData->dwFileAttributes; @@ -1510,7 +1497,7 @@ find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData, } static BOOL -attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) +attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) { HANDLE hFindFile; WIN32_FIND_DATAW FileData; @@ -1518,7 +1505,7 @@ attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG * if (hFindFile == INVALID_HANDLE_VALUE) return FALSE; FindClose(hFindFile); - find_data_to_file_info_w(&FileData, info, reparse_tag); + find_data_to_file_info(&FileData, info, reparse_tag); return TRUE; } @@ -1561,101 +1548,8 @@ get_target_path(HANDLE hdl, wchar_t **target_path) } static int -win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse); -static int -win32_xstat_impl(const char *path, struct _Py_stat_struct *result, +win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) -{ - int code; - HANDLE hFile, hFile2; - BY_HANDLE_FILE_INFORMATION info; - ULONG reparse_tag = 0; - wchar_t *target_path; - const char *dot; - - hFile = CreateFileA( - path, - FILE_READ_ATTRIBUTES, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. - Because of this, calls like GetFinalPathNameByHandle will return - the symlink path again and not the actual final path. */ - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) { - /* Either the target doesn't exist, or we don't have access to - get a handle to it. If the former, we need to return an error. - If the latter, we can use attributes_from_dir. */ - if (GetLastError() != ERROR_SHARING_VIOLATION) - return -1; - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir(path, &info, &reparse_tag)) - /* Very strange. This should not fail now */ - return -1; - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse) { - /* Should traverse, but could not open reparse point handle */ - SetLastError(ERROR_SHARING_VIOLATION); - return -1; - } - } - } else { - if (!GetFileInformationByHandle(hFile, &info)) { - CloseHandle(hFile); - return -1; - } - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) - return -1; - - /* Close the outer open file handle now that we're about to - reopen it with different flags. */ - if (!CloseHandle(hFile)) - return -1; - - if (traverse) { - /* In order to call GetFinalPathNameByHandle we need to open - the file without the reparse handling flag set. */ - hFile2 = CreateFileA( - path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - return -1; - - if (!get_target_path(hFile2, &target_path)) - return -1; - - code = win32_xstat_impl_w(target_path, result, FALSE); - PyMem_RawFree(target_path); - return code; - } - } else - CloseHandle(hFile); - } - _Py_attribute_data_to_stat(&info, reparse_tag, result); - - /* Set S_IEXEC if it is an .exe, .bat, ... */ - dot = strrchr(path, '.'); - if (dot) { - if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 || - stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0) - result->st_mode |= 0111; - } - return 0; -} - -static int -win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse) { int code; HANDLE hFile, hFile2; @@ -1686,7 +1580,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, return -1; /* Could not get attributes on open file. Fall back to reading the directory. */ - if (!attributes_from_dir_w(path, &info, &reparse_tag)) + if (!attributes_from_dir(path, &info, &reparse_tag)) /* Very strange. This should not fail now */ return -1; if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -1724,7 +1618,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, if (!get_target_path(hFile2, &target_path)) return -1; - code = win32_xstat_impl_w(target_path, result, FALSE); + code = win32_xstat_impl(target_path, result, FALSE); PyMem_RawFree(target_path); return code; } @@ -1744,7 +1638,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, } static int -win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse) +win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { /* Protocol violation: we explicitly clear errno, instead of setting it to a POSIX error. Callers should use GetLastError. */ @@ -1752,16 +1646,6 @@ win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse) errno = 0; return code; } - -static int -win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) -{ - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - int code = win32_xstat_impl_w(path, result, traverse); - errno = 0; - return code; -} /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w In Posix, stat automatically traverses symlinks and returns the stat @@ -1771,34 +1655,20 @@ win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse Therefore, win32_lstat will get the attributes traditionally, and win32_stat will first explicitly resolve the symlink target and then will - call win32_lstat on that result. - - The _w represent Unicode equivalents of the aforementioned ANSI functions. */ + call win32_lstat on that result. */ static int -win32_lstat(const char* path, struct _Py_stat_struct *result) +win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, FALSE); } static int -win32_lstat_w(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat_w(path, result, FALSE); -} - -static int -win32_stat(const char* path, struct _Py_stat_struct *result) +win32_stat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, TRUE); } -static int -win32_stat_w(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat_w(path, result, TRUE); -} - #endif /* MS_WINDOWS */ PyDoc_STRVAR(stat_result__doc__, @@ -2200,26 +2070,25 @@ posix_do_stat(const char *function_name, path_t *path, result = FSTAT(path->fd, &st); else #ifdef MS_WINDOWS - if (path->wide) { - if (follow_symlinks) - result = win32_stat_w(path->wide, &st); - else - result = win32_lstat_w(path->wide, &st); - } + if (follow_symlinks) + result = win32_stat(path->wide, &st); else -#endif -#if defined(HAVE_LSTAT) || defined(MS_WINDOWS) + result = win32_lstat(path->wide, &st); +#else + else +#if defined(HAVE_LSTAT) if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = LSTAT(path->narrow, &st); else -#endif +#endif /* HAVE_LSTAT */ #ifdef HAVE_FSTATAT if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) result = fstatat(dir_fd, path->narrow, &st, follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); else -#endif +#endif /* HAVE_FSTATAT */ result = STAT(path->narrow, &st); +#endif /* MS_WINDOWS */ Py_END_ALLOW_THREADS if (result != 0) { @@ -2655,10 +2524,7 @@ os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (path->wide != NULL) - attr = GetFileAttributesW(path->wide); - else - attr = GetFileAttributesA(path->narrow); + attr = GetFileAttributesW(path->wide); Py_END_ALLOW_THREADS /* @@ -2782,11 +2648,8 @@ os_chdir_impl(PyObject *module, path_t *path) Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS - if (path->wide) - result = win32_wchdir(path->wide); - else - result = win32_chdir(path->narrow); - result = !result; /* on unix, success = 0, on windows, success = !0 */ + /* on unix, success = 0, on windows, success = !0 */ + result = !win32_wchdir(path->wide); #else #ifdef HAVE_FCHDIR if (path->fd != -1) @@ -2881,10 +2744,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (path->wide) - attr = GetFileAttributesW(path->wide); - else - attr = GetFileAttributesA(path->narrow); + attr = GetFileAttributesW(path->wide); if (attr == INVALID_FILE_ATTRIBUTES) result = 0; else { @@ -2892,10 +2752,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, attr &= ~FILE_ATTRIBUTE_READONLY; else attr |= FILE_ATTRIBUTE_READONLY; - if (path->wide) - result = SetFileAttributesW(path->wide, attr); - else - result = SetFileAttributesA(path->narrow, attr); + result = SetFileAttributesW(path->wide, attr); } Py_END_ALLOW_THREADS @@ -3488,7 +3345,7 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ { #ifdef MS_WINDOWS - BOOL result; + BOOL result = FALSE; #else int result; #endif @@ -3500,18 +3357,18 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, } #endif +#ifndef MS_WINDOWS if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { PyErr_SetString(PyExc_NotImplementedError, "link: src and dst must be the same type"); return NULL; } +#endif #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS if (src->wide) result = CreateHardLinkW(dst->wide, src->wide, NULL); - else - result = CreateHardLinkA(dst->narrow, src->narrow, NULL); Py_END_ALLOW_THREADS if (!result) @@ -3526,13 +3383,13 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, dst_dir_fd, dst->narrow, follow_symlinks ? AT_SYMLINK_FOLLOW : 0); else -#endif +#endif /* HAVE_LINKAT */ result = link(src->narrow, dst->narrow); Py_END_ALLOW_THREADS if (result) return path_error2(src, dst); -#endif +#endif /* MS_WINDOWS */ Py_RETURN_NONE; } @@ -3546,97 +3403,39 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) PyObject *v; HANDLE hFindFile = INVALID_HANDLE_VALUE; BOOL result; - WIN32_FIND_DATA FileData; - char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ + wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ /* only claim to have space for MAX_PATH */ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; wchar_t *wnamebuf = NULL; - if (!path->narrow) { - WIN32_FIND_DATAW wFileData; - const wchar_t *po_wchars; - - if (!path->wide) { /* Default arg: "." */ - po_wchars = L"."; - len = 1; - } else { - po_wchars = path->wide; - len = wcslen(path->wide); - } - /* The +5 is so we can append "\\*.*\0" */ - wnamebuf = PyMem_New(wchar_t, len + 5); - if (!wnamebuf) { - PyErr_NoMemory(); - goto exit; - } - wcscpy(wnamebuf, po_wchars); - if (len > 0) { - wchar_t wch = wnamebuf[len-1]; - if (wch != SEP && wch != ALTSEP && wch != L':') - wnamebuf[len++] = SEP; - wcscpy(wnamebuf + len, L"*.*"); - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFileW(wnamebuf, &wFileData); - Py_END_ALLOW_THREADS - if (hFindFile == INVALID_HANDLE_VALUE) { - int error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) - goto exit; - Py_DECREF(list); - list = path_error(path); - goto exit; - } - do { - /* Skip over . and .. */ - if (wcscmp(wFileData.cFileName, L".") != 0 && - wcscmp(wFileData.cFileName, L"..") != 0) { - v = PyUnicode_FromWideChar(wFileData.cFileName, - wcslen(wFileData.cFileName)); - if (v == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_DECREF(list); - list = NULL; - break; - } - Py_DECREF(v); - } - Py_BEGIN_ALLOW_THREADS - result = FindNextFileW(hFindFile, &wFileData); - Py_END_ALLOW_THREADS - /* FindNextFile sets error to ERROR_NO_MORE_FILES if - it got to the end of the directory. */ - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } while (result == TRUE); + WIN32_FIND_DATAW wFileData; + const wchar_t *po_wchars; + if (!path->wide) { /* Default arg: "." */ + po_wchars = L"."; + len = 1; + } else { + po_wchars = path->wide; + len = wcslen(path->wide); + } + /* The +5 is so we can append "\\*.*\0" */ + wnamebuf = PyMem_New(wchar_t, len + 5); + if (!wnamebuf) { + PyErr_NoMemory(); goto exit; } - strcpy(namebuf, path->narrow); - len = path->length; + wcscpy(wnamebuf, po_wchars); if (len > 0) { - char ch = namebuf[len-1]; - if (ch != '\\' && ch != '/' && ch != ':') - namebuf[len++] = '\\'; - strcpy(namebuf + len, "*.*"); + wchar_t wch = wnamebuf[len-1]; + if (wch != SEP && wch != ALTSEP && wch != L':') + wnamebuf[len++] = SEP; + wcscpy(wnamebuf + len, L"*.*"); + } + if ((list = PyList_New(0)) == NULL) { + goto exit; } - - if ((list = PyList_New(0)) == NULL) - return NULL; - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFile(namebuf, &FileData); + hFindFile = FindFirstFileW(wnamebuf, &wFileData); Py_END_ALLOW_THREADS if (hFindFile == INVALID_HANDLE_VALUE) { int error = GetLastError(); @@ -3648,9 +3447,13 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) } do { /* Skip over . and .. */ - if (strcmp(FileData.cFileName, ".") != 0 && - strcmp(FileData.cFileName, "..") != 0) { - v = PyBytes_FromString(FileData.cFileName); + if (wcscmp(wFileData.cFileName, L".") != 0 && + wcscmp(wFileData.cFileName, L"..") != 0) { + v = PyUnicode_FromWideChar(wFileData.cFileName, + wcslen(wFileData.cFileName)); + if (path->narrow && v) { + Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); + } if (v == NULL) { Py_DECREF(list); list = NULL; @@ -3665,7 +3468,7 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) Py_DECREF(v); } Py_BEGIN_ALLOW_THREADS - result = FindNextFile(hFindFile, &FileData); + result = FindNextFileW(hFindFile, &wFileData); Py_END_ALLOW_THREADS /* FindNextFile sets error to ERROR_NO_MORE_FILES if it got to the end of the directory. */ @@ -3846,41 +3649,29 @@ static PyObject * os__getfullpathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ { - if (!path->narrow) - { - wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; - wchar_t *wtemp; - DWORD result; - PyObject *v; - - result = GetFullPathNameW(path->wide, - Py_ARRAY_LENGTH(woutbuf), - woutbuf, &wtemp); - if (result > Py_ARRAY_LENGTH(woutbuf)) { - woutbufp = PyMem_New(wchar_t, result); - if (!woutbufp) - return PyErr_NoMemory(); - result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp); - } - if (result) - v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); - else - v = win32_error_object("GetFullPathNameW", path->object); - if (woutbufp != woutbuf) - PyMem_Free(woutbufp); - return v; - } - else { - char outbuf[MAX_PATH]; - char *temp; + wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; + wchar_t *wtemp; + DWORD result; + PyObject *v; - if (!GetFullPathName(path->narrow, Py_ARRAY_LENGTH(outbuf), - outbuf, &temp)) { - win32_error_object("GetFullPathName", path->object); - return NULL; - } - return PyBytes_FromString(outbuf); + result = GetFullPathNameW(path->wide, + Py_ARRAY_LENGTH(woutbuf), + woutbuf, &wtemp); + if (result > Py_ARRAY_LENGTH(woutbuf)) { + woutbufp = PyMem_New(wchar_t, result); + if (!woutbufp) + return PyErr_NoMemory(); + result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp); } + if (result) { + v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); + if (path->narrow) + Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); + } else + v = win32_error_object("GetFullPathNameW", path->object); + if (woutbufp != woutbuf) + PyMem_Free(woutbufp); + return v; } @@ -3964,10 +3755,7 @@ os__isdir_impl(PyObject *module, path_t *path) DWORD attributes; Py_BEGIN_ALLOW_THREADS - if (!path->narrow) - attributes = GetFileAttributesW(path->wide); - else - attributes = GetFileAttributesA(path->narrow); + attributes = GetFileAttributesW(path->wide); Py_END_ALLOW_THREADS if (attributes == INVALID_FILE_ATTRIBUTES) @@ -4065,10 +3853,7 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (path->wide) - result = CreateDirectoryW(path->wide, NULL); - else - result = CreateDirectoryA(path->narrow, NULL); + result = CreateDirectoryW(path->wide, NULL); Py_END_ALLOW_THREADS if (!result) @@ -4088,7 +3873,7 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) Py_END_ALLOW_THREADS if (result < 0) return path_error(path); -#endif +#endif /* MS_WINDOWS */ Py_RETURN_NONE; } @@ -4211,31 +3996,28 @@ internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is } #endif - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_Format(PyExc_ValueError, - "%s: src and dst must be the same type", function_name); - return NULL; - } - #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (src->wide) - result = MoveFileExW(src->wide, dst->wide, flags); - else - result = MoveFileExA(src->narrow, dst->narrow, flags); + result = MoveFileExW(src->wide, dst->wide, flags); Py_END_ALLOW_THREADS if (!result) return path_error2(src, dst); #else + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_Format(PyExc_ValueError, + "%s: src and dst must be the same type", function_name); + return NULL; + } + Py_BEGIN_ALLOW_THREADS #ifdef HAVE_RENAMEAT if (dir_fd_specified) result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); else #endif - result = rename(src->narrow, dst->narrow); + result = rename(src->narrow, dst->narrow); Py_END_ALLOW_THREADS if (result) @@ -4316,11 +4098,8 @@ os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS - if (path->wide) - result = RemoveDirectoryW(path->wide); - else - result = RemoveDirectoryA(path->narrow); - result = !result; /* Windows, success=1, UNIX, success=0 */ + /* Windows, success=1, UNIX, success=0 */ + result = !RemoveDirectoryW(path->wide); #else #ifdef HAVE_UNLINKAT if (dir_fd != DEFAULT_DIR_FD) @@ -4466,11 +4245,8 @@ os_unlink_impl(PyObject *module, path_t *path, int dir_fd) Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS - if (path->wide) - result = Py_DeleteFileW(path->wide); - else - result = DeleteFileA(path->narrow); - result = !result; /* Windows, success=1, UNIX, success=0 */ + /* Windows, success=1, UNIX, success=0 */ + result = !Py_DeleteFileW(path->wide); #else #ifdef HAVE_UNLINKAT if (dir_fd != DEFAULT_DIR_FD) @@ -4881,14 +4657,9 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (path->wide) - hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - else - hFile = CreateFileA(path->narrow, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); + hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { path_error(path); @@ -4974,9 +4745,15 @@ os__exit_impl(PyObject *module, int status) return NULL; /* Make gcc -Wall happy */ } +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) +#define EXECV_CHAR wchar_t +#else +#define EXECV_CHAR char +#endif + #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) static void -free_string_array(char **array, Py_ssize_t count) +free_string_array(EXECV_CHAR **array, Py_ssize_t count) { Py_ssize_t i; for (i = 0; i < count; i++) @@ -4985,10 +4762,15 @@ free_string_array(char **array, Py_ssize_t count) } static -int fsconvert_strdup(PyObject *o, char**out) +int fsconvert_strdup(PyObject *o, EXECV_CHAR**out) { - PyObject *bytes; Py_ssize_t size; +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + *out = PyUnicode_AsWideCharString(o, &size); + if (!*out) + return 0; +#else + PyObject *bytes; if (!PyUnicode_FSConverter(o, &bytes)) return 0; size = PyBytes_GET_SIZE(bytes); @@ -4999,26 +4781,24 @@ int fsconvert_strdup(PyObject *o, char**out) } memcpy(*out, PyBytes_AsString(bytes), size+1); Py_DECREF(bytes); +#endif return 1; } #endif #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) -static char** +static EXECV_CHAR** parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { - char **envlist; Py_ssize_t i, pos, envc; PyObject *keys=NULL, *vals=NULL; - PyObject *key, *val, *key2, *val2; - char *p; - const char *k, *v; - size_t len; + PyObject *key, *val, *keyval; + EXECV_CHAR **envlist; i = PyMapping_Size(env); if (i < 0) return NULL; - envlist = PyMem_NEW(char *, i + 1); + envlist = PyMem_NEW(EXECV_CHAR *, i + 1); if (envlist == NULL) { PyErr_NoMemory(); return NULL; @@ -5042,28 +4822,16 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) if (!key || !val) goto error; - if (PyUnicode_FSConverter(key, &key2) == 0) - goto error; - if (PyUnicode_FSConverter(val, &val2) == 0) { - Py_DECREF(key2); + keyval = PyUnicode_FromFormat("%U=%U", key, val); + if (!keyval) goto error; - } - k = PyBytes_AsString(key2); - v = PyBytes_AsString(val2); - len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2; - - p = PyMem_NEW(char, len); - if (p == NULL) { - PyErr_NoMemory(); - Py_DECREF(key2); - Py_DECREF(val2); + if (!fsconvert_strdup(keyval, &envlist[envc++])) { + Py_DECREF(keyval); goto error; } - PyOS_snprintf(p, len, "%s=%s", k, v); - envlist[envc++] = p; - Py_DECREF(key2); - Py_DECREF(val2); + + Py_DECREF(keyval); } Py_DECREF(vals); Py_DECREF(keys); @@ -5075,17 +4843,15 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) error: Py_XDECREF(keys); Py_XDECREF(vals); - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); + free_string_array(envlist, envc); return NULL; } -static char** +static EXECV_CHAR** parse_arglist(PyObject* argv, Py_ssize_t *argc) { int i; - char **argvlist = PyMem_NEW(char *, *argc+1); + EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); if (argvlist == NULL) { PyErr_NoMemory(); return NULL; @@ -5107,6 +4873,7 @@ fail: free_string_array(argvlist, *argc); return NULL; } + #endif @@ -5114,7 +4881,7 @@ fail: /*[clinic input] os.execv - path: FSConverter + path: path_t Path of executable file. argv: object Tuple or list of strings. @@ -5124,17 +4891,15 @@ Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ static PyObject * -os_execv_impl(PyObject *module, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=b21dc34deeb5b004 input=96041559925e5229]*/ +os_execv_impl(PyObject *module, path_t *path, PyObject *argv) +/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ { - const char *path_char; - char **argvlist; + EXECV_CHAR **argvlist; Py_ssize_t argc; /* execv has two arguments: (path, argv), where argv is a list or tuple of strings. */ - path_char = PyBytes_AsString(path); if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); @@ -5151,7 +4916,11 @@ os_execv_impl(PyObject *module, PyObject *path, PyObject *argv) return NULL; } - execv(path_char, argvlist); +#ifdef HAVE_WEXECV + _wexecv(path->wide, argvlist); +#else + execv(path->narrow, argvlist); +#endif /* If we get here it's definitely an error */ @@ -5177,8 +4946,8 @@ static PyObject * os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ { - char **argvlist = NULL; - char **envlist; + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist; Py_ssize_t argc, envc; /* execve has three arguments: (path, argv, env), where @@ -5211,30 +4980,33 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) fexecve(path->fd, argvlist, envlist); else #endif +#ifdef HAVE_WEXECV + _wexecve(path->wide, argvlist, envlist); +#else execve(path->narrow, argvlist, envlist); +#endif /* If we get here it's definitely an error */ path_error(path); - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); + free_string_array(envlist, envc); fail: if (argvlist) free_string_array(argvlist, argc); return NULL; } + #endif /* HAVE_EXECV */ -#ifdef HAVE_SPAWNV +#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) /*[clinic input] os.spawnv mode: int Mode of process creation. - path: FSConverter + path: path_t Path of executable file. argv: object Tuple or list of strings. @@ -5244,11 +5016,10 @@ Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * -os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=c427c0ce40f10638 input=042c91dfc1e6debc]*/ +os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) +/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ { - const char *path_char; - char **argvlist; + EXECV_CHAR **argvlist; int i; Py_ssize_t argc; intptr_t spawnval; @@ -5257,7 +5028,6 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) /* spawnv has three arguments: (mode, path, argv), where argv is a list or tuple of strings. */ - path_char = PyBytes_AsString(path); if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; @@ -5272,7 +5042,7 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) return NULL; } - argvlist = PyMem_NEW(char *, argc+1); + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { return PyErr_NoMemory(); } @@ -5292,7 +5062,11 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS - spawnval = _spawnv(mode, path_char, argvlist); +#ifdef HAVE_WSPAWNV + spawnval = _wspawnv(mode, path->wide, argvlist); +#else + spawnval = _spawnv(mode, path->narrow, argvlist); +#endif Py_END_ALLOW_THREADS free_string_array(argvlist, argc); @@ -5309,7 +5083,7 @@ os.spawnve mode: int Mode of process creation. - path: FSConverter + path: path_t Path of executable file. argv: object Tuple or list of strings. @@ -5321,13 +5095,12 @@ Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * -os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, +os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=ebcfa5f7ba2f4219 input=02362fd937963f8f]*/ +/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ { - const char *path_char; - char **argvlist; - char **envlist; + EXECV_CHAR **argvlist; + EXECV_CHAR **envlist; PyObject *res = NULL; Py_ssize_t argc, i, envc; intptr_t spawnval; @@ -5338,7 +5111,6 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - path_char = PyBytes_AsString(path); if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; @@ -5358,7 +5130,7 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, goto fail_0; } - argvlist = PyMem_NEW(char *, argc+1); + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { PyErr_NoMemory(); goto fail_0; @@ -5382,7 +5154,11 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS - spawnval = _spawnve(mode, path_char, argvlist, envlist); +#ifdef HAVE_WSPAWNV + spawnval = _wspawnve(mode, path->wide, argvlist, envlist); +#else + spawnval = _spawnve(mode, path->narrow, argvlist, envlist); +#endif Py_END_ALLOW_THREADS if (spawnval == -1) @@ -7290,21 +7066,18 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) /* Grab CreateSymbolicLinkW dynamically from kernel32 */ static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL; -static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPCSTR, LPCSTR, DWORD) = NULL; static int check_CreateSymbolicLink(void) { HINSTANCE hKernel32; /* only recheck */ - if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA) + if (Py_CreateSymbolicLinkW) return 1; hKernel32 = GetModuleHandleW(L"KERNEL32"); *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, "CreateSymbolicLinkW"); - *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32, - "CreateSymbolicLinkA"); - return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA); + return Py_CreateSymbolicLinkW != NULL; } /* Remove the last portion of the path */ @@ -7321,20 +7094,6 @@ _dirnameW(WCHAR *path) *ptr = 0; } -/* Remove the last portion of the path */ -static void -_dirnameA(char *path) -{ - char *ptr; - - /* walk the path from the end until a backslash is encountered */ - for(ptr = path + strlen(path); ptr != path; ptr--) { - if (*ptr == '\\' || *ptr == '/') - break; - } - *ptr = 0; -} - /* Is this path absolute? */ static int _is_absW(const WCHAR *path) @@ -7343,14 +7102,6 @@ _is_absW(const WCHAR *path) } -/* Is this path absolute? */ -static int -_is_absA(const char *path) -{ - return path[0] == '\\' || path[0] == '/' || path[1] == ':'; - -} - /* join root and rest with a backslash */ static void _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) @@ -7372,27 +7123,6 @@ _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) wcscpy(dest_path+root_len, rest); } -/* join root and rest with a backslash */ -static void -_joinA(char *dest_path, const char *root, const char *rest) -{ - size_t root_len; - - if (_is_absA(rest)) { - strcpy(dest_path, rest); - return; - } - - root_len = strlen(root); - - strcpy(dest_path, root); - if(root_len) { - dest_path[root_len] = '\\'; - root_len++; - } - strcpy(dest_path+root_len, rest); -} - /* Return True if the path at src relative to dest is a directory */ static int _check_dirW(LPCWSTR src, LPCWSTR dest) @@ -7411,25 +7141,6 @@ _check_dirW(LPCWSTR src, LPCWSTR dest) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ); } - -/* Return True if the path at src relative to dest is a directory */ -static int -_check_dirA(LPCSTR src, LPCSTR dest) -{ - WIN32_FILE_ATTRIBUTE_DATA src_info; - char dest_parent[MAX_PATH]; - char src_resolved[MAX_PATH] = ""; - - /* dest_parent = os.path.dirname(dest) */ - strcpy(dest_parent, dest); - _dirnameA(dest_parent); - /* src_resolved = os.path.join(dest_parent, src) */ - _joinA(src_resolved, dest_parent, src); - return ( - GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info) - && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - ); -} #endif @@ -7489,18 +7200,10 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (dst->wide) { - /* if src is a directory, ensure target_is_directory==1 */ - target_is_directory |= _check_dirW(src->wide, dst->wide); - result = Py_CreateSymbolicLinkW(dst->wide, src->wide, - target_is_directory); - } - else { - /* if src is a directory, ensure target_is_directory==1 */ - target_is_directory |= _check_dirA(src->narrow, dst->narrow); - result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, - target_is_directory); - } + /* if src is a directory, ensure target_is_directory==1 */ + target_is_directory |= _check_dirW(src->wide, dst->wide); + result = Py_CreateSymbolicLinkW(dst->wide, src->wide, + target_is_directory); Py_END_ALLOW_THREADS if (!result) @@ -7805,16 +7508,14 @@ os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) do { Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS - if (path->wide) - fd = _wopen(path->wide, flags, mode); - else + fd = _wopen(path->wide, flags, mode); #endif #ifdef HAVE_OPENAT if (dir_fd != DEFAULT_DIR_FD) fd = openat(dir_fd, path->narrow, flags, mode); else -#endif fd = open(path->narrow, flags, mode); +#endif Py_END_ALLOW_THREADS } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); _Py_END_SUPPRESS_IPH @@ -8955,10 +8656,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS - if (path->wide) - fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); - else - fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT); + fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); if (fd < 0) result = -1; else { @@ -10612,31 +10310,8 @@ os_abort_impl(PyObject *module) } #ifdef MS_WINDOWS -/* AC 3.5: change to path_t? but that might change exceptions */ -PyDoc_STRVAR(win32_startfile__doc__, -"startfile(filepath [, operation])\n\ -\n\ -Start a file with its associated application.\n\ -\n\ -When \"operation\" is not specified or \"open\", this acts like\n\ -double-clicking the file in Explorer, or giving the file name as an\n\ -argument to the DOS \"start\" command: the file is opened with whatever\n\ -application (if any) its extension is associated.\n\ -When another \"operation\" is given, it specifies what should be done with\n\ -the file. A typical operation is \"print\".\n\ -\n\ -startfile returns as soon as the associated application is launched.\n\ -There is no option to wait for the application to close, and no way\n\ -to retrieve the application's exit status.\n\ -\n\ -The filepath is relative to the current directory. If you want to use\n\ -an absolute path, make sure the first character is not a slash (\"/\");\n\ -the underlying Win32 ShellExecute function doesn't work if it is."); - /* Grab ShellExecute dynamically from shell32 */ static int has_ShellExecute = -1; -static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR, - LPCSTR, INT); static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT); static int @@ -10650,12 +10325,9 @@ check_ShellExecute() hShell32 = LoadLibraryW(L"SHELL32"); Py_END_ALLOW_THREADS if (hShell32) { - *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32, - "ShellExecuteA"); *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, "ShellExecuteW"); - has_ShellExecute = Py_ShellExecuteA && - Py_ShellExecuteW; + has_ShellExecute = Py_ShellExecuteW != NULL; } else { has_ShellExecute = 0; } @@ -10664,17 +10336,37 @@ check_ShellExecute() } +/*[clinic input] +os.startfile + filepath: path_t + operation: Py_UNICODE = NULL + +startfile(filepath [, operation]) + +Start a file with its associated application. + +When "operation" is not specified or "open", this acts like +double-clicking the file in Explorer, or giving the file name as an +argument to the DOS "start" command: the file is opened with whatever +application (if any) its extension is associated. +When another "operation" is given, it specifies what should be done with +the file. A typical operation is "print". + +startfile returns as soon as the associated application is launched. +There is no option to wait for the application to close, and no way +to retrieve the application's exit status. + +The filepath is relative to the current directory. If you want to use +an absolute path, make sure the first character is not a slash ("/"); +the underlying Win32 ShellExecute function doesn't work if it is. +[clinic start generated code]*/ + static PyObject * -win32_startfile(PyObject *self, PyObject *args) +os_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation) +/*[clinic end generated code: output=912ceba79acfa1c9 input=63950bf2986380d0]*/ { - PyObject *ofilepath; - const char *filepath; - const char *operation = NULL; - const wchar_t *wpath, *woperation; HINSTANCE rc; - PyObject *unipath, *uoperation = NULL; - if(!check_ShellExecute()) { /* If the OS doesn't have ShellExecute, return a NotImplementedError. */ @@ -10682,68 +10374,16 @@ win32_startfile(PyObject *self, PyObject *args) "startfile not available on this platform"); } - if (!PyArg_ParseTuple(args, "U|s:startfile", - &unipath, &operation)) { - PyErr_Clear(); - goto normal; - } - - if (operation) { - uoperation = PyUnicode_DecodeASCII(operation, - strlen(operation), NULL); - if (!uoperation) { - PyErr_Clear(); - operation = NULL; - goto normal; - } - } - - wpath = PyUnicode_AsUnicode(unipath); - if (wpath == NULL) - goto normal; - if (uoperation) { - woperation = PyUnicode_AsUnicode(uoperation); - if (woperation == NULL) - goto normal; - } - else - woperation = NULL; - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteW((HWND)0, woperation, wpath, + rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, NULL, NULL, SW_SHOWNORMAL); Py_END_ALLOW_THREADS - Py_XDECREF(uoperation); if (rc <= (HINSTANCE)32) { - win32_error_object("startfile", unipath); - return NULL; - } - Py_INCREF(Py_None); - return Py_None; - -normal: - if (!PyArg_ParseTuple(args, "O&|s:startfile", - PyUnicode_FSConverter, &ofilepath, - &operation)) - return NULL; - if (win32_warn_bytes_api()) { - Py_DECREF(ofilepath); + win32_error_object("startfile", filepath->object); return NULL; } - filepath = PyBytes_AsString(ofilepath); - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteA((HWND)0, operation, filepath, - NULL, NULL, SW_SHOWNORMAL); - Py_END_ALLOW_THREADS - if (rc <= (HINSTANCE)32) { - PyObject *errval = win32_error("startfile", filepath); - Py_DECREF(ofilepath); - return errval; - } - Py_DECREF(ofilepath); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* MS_WINDOWS */ @@ -11560,9 +11200,9 @@ DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) return NULL; if (follow_symlinks) - result = win32_stat_w(path, &st); + result = win32_stat(path, &st); else - result = win32_lstat_w(path, &st); + result = win32_lstat(path, &st); if (result != 0) { return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, @@ -11761,7 +11401,7 @@ DirEntry_inode(DirEntry *self) if (!path) return NULL; - if (win32_lstat_w(path, &stat) != 0) { + if (win32_lstat(path, &stat) != 0) { return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, self->path); } @@ -11910,6 +11550,11 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW) entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); if (!entry->name) goto error; + if (path->narrow) { + Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); + if (!entry->name) + goto error; + } joined_path = join_path_filenameW(path->wide, dataW->cFileName); if (!joined_path) @@ -11919,8 +11564,13 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW) PyMem_Free(joined_path); if (!entry->path) goto error; + if (path->narrow) { + Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); + if (!entry->path) + goto error; + } - find_data_to_file_info_w(dataW, &file_info, &reparse_tag); + find_data_to_file_info(dataW, &file_info, &reparse_tag); _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); return (PyObject *)entry; @@ -12316,11 +11966,6 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) Py_XINCREF(iterator->path.object); #ifdef MS_WINDOWS - if (iterator->path.narrow) { - PyErr_SetString(PyExc_TypeError, - "os.scandir() doesn't support bytes path on Windows, use Unicode instead"); - goto error; - } iterator->first_time = 1; path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); @@ -12570,7 +12215,7 @@ static PyMethodDef posix_methods[] = { OS_KILLPG_METHODDEF OS_PLOCK_METHODDEF #ifdef MS_WINDOWS - {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, + OS_STARTFILE_METHODDEF #endif OS_SETUID_METHODDEF OS_SETEUID_METHODDEF -- cgit v1.2.1 From d3d81bf758e1b6a25c9f3e66d5e49e366a805365 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 8 Sep 2016 10:41:50 -0700 Subject: Fix mismatched if blocks in posixmodule.c. --- Modules/posixmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a39ea651fd..4f5ec99e4a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2068,9 +2068,8 @@ posix_do_stat(const char *function_name, path_t *path, Py_BEGIN_ALLOW_THREADS if (path->fd != -1) result = FSTAT(path->fd, &st); - else #ifdef MS_WINDOWS - if (follow_symlinks) + else if (follow_symlinks) result = win32_stat(path->wide, &st); else result = win32_lstat(path->wide, &st); -- cgit v1.2.1 From 0b262da03401df836e0d2cd8b20412aeeaec6af8 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 8 Sep 2016 11:21:54 -0700 Subject: Issue #23524: Finish removing _PyVerify_fd from sources --- Modules/posixmodule.c | 75 +++------------------------------------------------ 1 file changed, 3 insertions(+), 72 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4f5ec99e4a..957a5f2b7d 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1178,34 +1178,6 @@ PyLong_FromPy_off_t(Py_off_t offset) #endif } - -#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 -/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to - * MSVC 14.0. This should eventually be removed. (issue23524) - */ -#define IOINFO_L2E 5 -#define IOINFO_ARRAYS 64 -#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) -#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS) -#define _NO_CONSOLE_FILENO (intptr_t)-2 - -/* the special case of checking dup2. The target fd must be in a sensible range */ -static int -_PyVerify_fd_dup2(int fd1, int fd2) -{ - if (!_PyVerify_fd(fd1)) - return 0; - if (fd2 == _NO_CONSOLE_FILENO) - return 0; - if ((unsigned)fd2 < _NHANDLE_) - return 1; - else - return 0; -} -#else -#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0) -#endif - #ifdef MS_WINDOWS static int @@ -1409,9 +1381,6 @@ posix_fildes_fd(int fd, int (*func)(int)) int res; int async_err = 0; - if (!_PyVerify_fd(fd)) - return posix_error(); - do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH @@ -7549,8 +7518,6 @@ os_close_impl(PyObject *module, int fd) /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ { int res; - if (!_PyVerify_fd(fd)) - return posix_error(); /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html * for more details. @@ -7583,9 +7550,8 @@ os_closerange_impl(PyObject *module, int fd_low, int fd_high) int i; Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH - for (i = fd_low; i < fd_high; i++) - if (_PyVerify_fd(i)) - close(i); + for (i = max(fd_low, 0); i < fd_high; i++) + close(i); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS Py_RETURN_NONE; @@ -7629,7 +7595,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) int dup3_works = -1; #endif - if (!_PyVerify_fd_dup2(fd, fd2)) + if (fd < 0 || fd2 < 0) return posix_error(); /* dup2() can fail with EINTR if the target FD is already open, because it @@ -7753,10 +7719,6 @@ os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) { Py_off_t result; - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } #ifdef SEEK_SET /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ switch (how) { @@ -7769,10 +7731,6 @@ os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) if (PyErr_Occurred()) return -1; - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS @@ -7980,10 +7938,6 @@ os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset) buffer = PyBytes_FromStringAndSize((char *)NULL, length); if (buffer == NULL) return NULL; - if (!_PyVerify_fd(fd)) { - Py_DECREF(buffer); - return posix_error(); - } do { Py_BEGIN_ALLOW_THREADS @@ -8226,8 +8180,6 @@ os_isatty_impl(PyObject *module, int fd) /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ { int return_value; - if (!_PyVerify_fd(fd)) - return 0; _Py_BEGIN_SUPPRESS_IPH return_value = isatty(fd); _Py_END_SUPPRESS_IPH @@ -8419,11 +8371,6 @@ os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) Py_ssize_t size; int async_err = 0; - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } - do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH @@ -8606,9 +8553,6 @@ os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) int result; int async_err = 0; - if (!_PyVerify_fd(fd)) - return posix_error(); - do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH @@ -10979,11 +10923,6 @@ os_get_inheritable_impl(PyObject *module, int fd) /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ { int return_value; - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } - _Py_BEGIN_SUPPRESS_IPH return_value = _Py_get_inheritable(fd); _Py_END_SUPPRESS_IPH @@ -11005,8 +10944,6 @@ os_set_inheritable_impl(PyObject *module, int fd, int inheritable) /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ { int result; - if (!_PyVerify_fd(fd)) - return posix_error(); _Py_BEGIN_SUPPRESS_IPH result = _Py_set_inheritable(fd, inheritable, NULL); @@ -11080,9 +11017,6 @@ posix_get_blocking(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "i:get_blocking", &fd)) return NULL; - if (!_PyVerify_fd(fd)) - return posix_error(); - _Py_BEGIN_SUPPRESS_IPH blocking = _Py_get_blocking(fd); _Py_END_SUPPRESS_IPH @@ -11106,9 +11040,6 @@ posix_set_blocking(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) return NULL; - if (!_PyVerify_fd(fd)) - return posix_error(); - _Py_BEGIN_SUPPRESS_IPH result = _Py_set_blocking(fd, blocking); _Py_END_SUPPRESS_IPH -- cgit v1.2.1 From 44907aa3bd6ad5b4547a4633a1b0146408099964 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 8 Sep 2016 11:28:06 -0700 Subject: use Py_MAX --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 957a5f2b7d..c1ba7ba9a6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7550,7 +7550,7 @@ os_closerange_impl(PyObject *module, int fd_low, int fd_high) int i; Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH - for (i = max(fd_low, 0); i < fd_high; i++) + for (i = Py_MAX(fd_low, 0); i < fd_high; i++) close(i); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS -- cgit v1.2.1 From 39ea75b1547851f03587418f6668a2a01d3c2194 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 9 Sep 2016 09:03:15 -0700 Subject: Issue #27781: Fixes uninitialized fd when !MS_WINDOWS and !HAVE_OPENAT --- Modules/posixmodule.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c1ba7ba9a6..ce646846df 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7477,13 +7477,14 @@ os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS fd = _wopen(path->wide, flags, mode); -#endif +#else #ifdef HAVE_OPENAT if (dir_fd != DEFAULT_DIR_FD) fd = openat(dir_fd, path->narrow, flags, mode); else +#endif /* HAVE_OPENAT */ fd = open(path->narrow, flags, mode); -#endif +#endif /* !MS_WINDOWS */ Py_END_ALLOW_THREADS } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); _Py_END_SUPPRESS_IPH -- cgit v1.2.1 From cb4ad5cff9012b50a5b727b9e95f57c1199db640 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Sun, 11 Sep 2016 20:19:32 -0700 Subject: Adds missing assert suppression. --- Modules/posixmodule.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ce646846df..43e3c77cbb 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5030,11 +5030,13 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnv(mode, path->wide, argvlist); #else spawnval = _spawnv(mode, path->narrow, argvlist); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS free_string_array(argvlist, argc); @@ -5122,11 +5124,13 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnve(mode, path->wide, argvlist, envlist); #else spawnval = _spawnve(mode, path->narrow, argvlist, envlist); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (spawnval == -1) -- cgit v1.2.1 From 4f3920fccc1a41608c9615ec78038232b0382f8f Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Thu, 15 Sep 2016 20:19:47 +0300 Subject: Issue #28114: Fix a crash in parse_envlist() when env contains byte strings Patch by Eryk Sun. --- Modules/posixmodule.c | 56 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 43e3c77cbb..32d097872b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4729,28 +4729,31 @@ free_string_array(EXECV_CHAR **array, Py_ssize_t count) PyMem_DEL(array); } -static -int fsconvert_strdup(PyObject *o, EXECV_CHAR**out) +static int +fsconvert_strdup(PyObject *o, EXECV_CHAR **out) { Py_ssize_t size; + PyObject *ub; + int result = 0; #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) - *out = PyUnicode_AsWideCharString(o, &size); - if (!*out) + if (!PyUnicode_FSDecoder(o, &ub)) return 0; + *out = PyUnicode_AsWideCharString(ub, &size); + if (*out) + result = 1; #else - PyObject *bytes; - if (!PyUnicode_FSConverter(o, &bytes)) + if (!PyUnicode_FSConverter(o, &ub)) return 0; - size = PyBytes_GET_SIZE(bytes); - *out = PyMem_Malloc(size+1); - if (!*out) { + size = PyBytes_GET_SIZE(ub); + *out = PyMem_Malloc(size + 1); + if (*out) { + memcpy(*out, PyBytes_AS_STRING(ub), size + 1); + result = 1; + } else PyErr_NoMemory(); - return 0; - } - memcpy(*out, PyBytes_AsString(bytes), size+1); - Py_DECREF(bytes); #endif - return 1; + Py_DECREF(ub); + return result; } #endif @@ -4760,7 +4763,7 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { Py_ssize_t i, pos, envc; PyObject *keys=NULL, *vals=NULL; - PyObject *key, *val, *keyval; + PyObject *key, *val, *key2, *val2, *keyval; EXECV_CHAR **envlist; i = PyMapping_Size(env); @@ -4790,7 +4793,26 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) if (!key || !val) goto error; - keyval = PyUnicode_FromFormat("%U=%U", key, val); +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + if (!PyUnicode_FSDecoder(key, &key2)) + goto error; + if (!PyUnicode_FSDecoder(val, &val2)) { + Py_DECREF(key2); + goto error; + } + keyval = PyUnicode_FromFormat("%U=%U", key2, val2); +#else + if (!PyUnicode_FSConverter(key, &key2)) + goto error; + if (!PyUnicode_FSConverter(val, &val2)) { + Py_DECREF(key2); + goto error; + } + keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), + PyBytes_AS_STRING(val2)); +#endif + Py_DECREF(key2); + Py_DECREF(val2); if (!keyval) goto error; @@ -4798,7 +4820,7 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) Py_DECREF(keyval); goto error; } - + Py_DECREF(keyval); } Py_DECREF(vals); -- cgit v1.2.1 From 772efee82991c09e48737aae39aca2705a04aa83 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Thu, 15 Sep 2016 20:45:16 +0300 Subject: Issue #28156: Export os.getpid() conditionally Patch by Ed Schouten. --- Modules/posixmodule.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 32d097872b..84566d80ad 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5895,6 +5895,7 @@ os_getgid_impl(PyObject *module) #endif /* HAVE_GETGID */ +#ifdef HAVE_GETPID /*[clinic input] os.getpid @@ -5907,6 +5908,7 @@ os_getpid_impl(PyObject *module) { return PyLong_FromPid(getpid()); } +#endif /* HAVE_GETPID */ #ifdef HAVE_GETGROUPLIST -- cgit v1.2.1 From b03e7e664401971a2852b522273d32cae445f7cd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 19 Sep 2016 11:55:44 +0200 Subject: Fix memory leak in path_converter() Issue #28200: Replace PyUnicode_AsWideCharString() with PyUnicode_AsUnicodeAndSize(). --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ba54249684..470ee92fa1 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -920,7 +920,7 @@ path_converter(PyObject *o, void *p) if (is_unicode) { #ifdef MS_WINDOWS - wide = PyUnicode_AsWideCharString(o, &length); + wide = PyUnicode_AsUnicodeAndSize(o, &length); if (!wide) { goto exit; } -- cgit v1.2.1 From a57fe851b0eaecba2b49390200a01bc3bc7c549c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 20 Sep 2016 23:00:59 +0200 Subject: Fix memleak in os.getrandom() Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is interrupted by a signal and a signal handler raises a Python exception. Modify also os_getrandom_impl() to avoid the temporary buffer, use directly a Python bytes object. --- Modules/posixmodule.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 470ee92fa1..28d30b0f9a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12047,42 +12047,50 @@ static PyObject * os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ { - char *buffer; - Py_ssize_t n; PyObject *bytes; + Py_ssize_t n; if (size < 0) { errno = EINVAL; return posix_error(); } - buffer = PyMem_Malloc(size); - if (buffer == NULL) { + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) { PyErr_NoMemory(); return NULL; } while (1) { - n = syscall(SYS_getrandom, buffer, size, flags); + n = syscall(SYS_getrandom, + PyBytes_AS_STRING(bytes), + PyBytes_GET_SIZE(bytes), + flags); if (n < 0 && errno == EINTR) { if (PyErr_CheckSignals() < 0) { - return NULL; + goto error; } + + /* getrandom() was interrupted by a signal: retry */ continue; } break; } if (n < 0) { - PyMem_Free(buffer); PyErr_SetFromErrno(PyExc_OSError); - return NULL; + goto error; } - bytes = PyBytes_FromStringAndSize(buffer, n); - PyMem_Free(buffer); + if (n != size) { + _PyBytes_Resize(&bytes, n); + } return bytes; + +error: + Py_DECREF(bytes); + return NULL; } #endif /* HAVE_GETRANDOM_SYSCALL */ -- cgit v1.2.1 From 516aa230aff72ee43e5507278f513e2c1472f293 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 8 Oct 2016 20:16:57 +0300 Subject: Issue #27998: Fixed bytes path support in os.scandir() on Windows. Patch by Eryk Sun. --- Modules/posixmodule.c | 89 +++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 46 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 01194aa850..ef17981ff7 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1337,29 +1337,39 @@ win32_error_object(const char* function, PyObject* filename) #endif /* MS_WINDOWS */ static PyObject * -path_error(path_t *path) +path_object_error(PyObject *path) { #ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, path->object); + return PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_OSError, 0, path); #else - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); #endif } - static PyObject * -path_error2(path_t *path, path_t *path2) +path_object_error2(PyObject *path, PyObject *path2) { #ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError, - 0, path->object, path2->object); + return PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyExc_OSError, 0, path, path2); #else - return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, - path->object, path2->object); + return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); #endif } +static PyObject * +path_error(path_t *path) +{ + return path_object_error(path->object); +} + +static PyObject * +path_error2(path_t *path, path_t *path2) +{ + return path_object_error2(path->object, path2->object); +} + /* POSIX generic methods */ @@ -11152,41 +11162,26 @@ static PyObject * DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) { int result; - struct _Py_stat_struct st; + STRUCT_STAT st; + PyObject *ub; #ifdef MS_WINDOWS - const wchar_t *path; - - path = PyUnicode_AsUnicode(self->path); - if (!path) - return NULL; - - if (follow_symlinks) - result = win32_stat(path, &st); - else - result = win32_lstat(path, &st); - - if (result != 0) { - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, self->path); - } + if (PyUnicode_FSDecoder(self->path, &ub)) { + const wchar_t *path = PyUnicode_AsUnicode(ub); #else /* POSIX */ - PyObject *bytes; - const char *path; - - if (!PyUnicode_FSConverter(self->path, &bytes)) + if (PyUnicode_FSConverter(self->path, &ub)) { + const char *path = PyBytes_AS_STRING(ub); +#endif + if (follow_symlinks) + result = STAT(path, &st); + else + result = LSTAT(path, &st); + Py_DECREF(ub); + } else return NULL; - path = PyBytes_AS_STRING(bytes); - - if (follow_symlinks) - result = STAT(path, &st); - else - result = LSTAT(path, &st); - Py_DECREF(bytes); if (result != 0) - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, self->path); -#endif + return path_object_error(self->path); return _pystat_fromstructstat(&st); } @@ -11356,17 +11351,19 @@ DirEntry_inode(DirEntry *self) { #ifdef MS_WINDOWS if (!self->got_file_index) { + PyObject *unicode; const wchar_t *path; - struct _Py_stat_struct stat; + STRUCT_STAT stat; + int result; - path = PyUnicode_AsUnicode(self->path); - if (!path) + if (!PyUnicode_FSDecoder(self->path, &unicode)) return NULL; + path = PyUnicode_AsUnicode(unicode); + result = LSTAT(path, &stat); + Py_DECREF(unicode); - if (win32_lstat(path, &stat) != 0) { - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, self->path); - } + if (result != 0) + return path_object_error(self->path); self->win32_file_index = stat.st_ino; self->got_file_index = 1; -- cgit v1.2.1 From 01c29c2b0cbe7645628250701cdda38f6d751d66 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Mon, 10 Oct 2016 00:38:21 +0000 Subject: Issue #28394: More typo fixes for 3.6+ --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ef17981ff7..7aae5c7d81 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -770,7 +770,7 @@ dir_fd_converter(PyObject *o, void *p) * path.narrow * Points to the path if it was expressed as bytes, * or it was Unicode and was encoded to bytes. (On Windows, - * is an non-zero integer if the path was expressed as bytes. + * is a non-zero integer if the path was expressed as bytes. * The type is deliberately incompatible to prevent misuse.) * path.fd * Contains a file descriptor if path.accept_fd was true -- cgit v1.2.1 From f67383d9e5dac2d1f1cb8d1d3cbbf28b8faca9fa Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Sat, 19 Nov 2016 18:53:19 -0800 Subject: Issue #28732: Raise ValueError when os.spawn*() is passed an empty tuple of arguments --- Modules/posixmodule.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a89da7091b..0482f2bbd0 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5042,6 +5042,11 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) "spawnv() arg 2 must be a tuple or list"); return NULL; } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnv() arg 2 cannot be empty"); + return NULL; + } argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { @@ -5127,6 +5132,11 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, "spawnve() arg 2 must be a tuple or list"); goto fail_0; } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnve() arg 2 cannot be empty"); + goto fail_0; + } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "spawnve() arg 3 must be a mapping object"); -- cgit v1.2.1 From 57c0f2e61c8a5893c37e576a3a03ba5e57c1132c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Nov 2016 09:13:07 +0200 Subject: Replaced outdated macros _PyUnicode_AsString and _PyUnicode_AsStringAndSize with PyUnicode_AsUTF8 and PyUnicode_AsUTF8AndSize. --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index acef3c31e8..ae251025cb 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9325,7 +9325,7 @@ conv_confname(PyObject *arg, int *valuep, struct constdef *table, "configuration names must be strings or integers"); return 0; } - confname = _PyUnicode_AsString(arg); + confname = PyUnicode_AsUTF8(arg); if (confname == NULL) return 0; while (lo < hi) { -- cgit v1.2.1 From 9bc3d0b51b40160cfed36dbf717ba1d674d901aa Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sun, 8 Jan 2017 23:26:57 +0800 Subject: Issue #29034: Fix memory leak and use-after-free in path_converter. --- Modules/posixmodule.c | 109 ++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 53 deletions(-) (limited to 'Modules/posixmodule.c') diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ae251025cb..33ee70d8d5 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -785,7 +785,9 @@ dir_fd_converter(PyObject *o, void *p) * The length of the path in characters, if specified as * a string. * path.object - * The original object passed in. + * The original object passed in (if get a PathLike object, + * the result of PyOS_FSPath() is treated as the original object). + * Own a reference to the object. * path.cleanup * For internal use only. May point to a temporary object. * (Pay no attention to the man behind the curtain.) @@ -836,24 +838,22 @@ typedef struct { #endif static void -path_cleanup(path_t *path) { - if (path->cleanup) { - Py_CLEAR(path->cleanup); - } +path_cleanup(path_t *path) +{ + Py_CLEAR(path->object); + Py_CLEAR(path->cleanup); } static int path_converter(PyObject *o, void *p) { path_t *path = (path_t *)p; - PyObject *bytes, *to_cleanup = NULL; - Py_ssize_t length; + PyObject *bytes = NULL; + Py_ssize_t length = 0; int is_index, is_buffer, is_bytes, is_unicode; - /* Default to failure, forcing explicit signaling of succcess. */ - int ret = 0; const char *narrow; #ifdef MS_WINDOWS - PyObject *wo; + PyObject *wo = NULL; const wchar_t *wide; #endif @@ -870,7 +870,9 @@ path_converter(PyObject *o, void *p) } /* Ensure it's always safe to call path_cleanup(). */ - path->cleanup = NULL; + path->object = path->cleanup = NULL; + /* path->object owns a reference to the original object */ + Py_INCREF(o); if ((o == Py_None) && path->nullable) { path->wide = NULL; @@ -879,10 +881,8 @@ path_converter(PyObject *o, void *p) #else path->narrow = NULL; #endif - path->length = 0; - path->object = o; path->fd = -1; - return 1; + goto success_exit; } /* Only call this here so that we don't treat the return value of @@ -899,10 +899,11 @@ path_converter(PyObject *o, void *p) func = _PyObject_LookupSpecial(o, &PyId___fspath__); if (NULL == func) { - goto error_exit; + goto error_format; } - - o = to_cleanup = PyObject_CallFunctionObjArgs(func, NULL); + /* still owns a reference to the original object */ + Py_DECREF(o); + o = _PyObject_CallNoArg(func); Py_DECREF(func); if (NULL == o) { goto error_exit; @@ -914,7 +915,7 @@ path_converter(PyObject *o, void *p) is_bytes = 1; } else { - goto error_exit; + goto error_format; } } @@ -922,26 +923,24 @@ path_converter(PyObject *o, void *p) #ifdef MS_WINDOWS wide = PyUnicode_AsUnicodeAndSize(o, &length); if (!wide) { - goto exit; + goto error_exit; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto exit; + goto error_exit; } if (wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto exit; + goto error_exit; } path->wide = wide; - path->length = length; - path->object = o; + path->narrow = FALSE; path->fd = -1; - ret = 1; - goto exit; + goto success_exit; #else if (!PyUnicode_FSConverter(o, &bytes)) { - goto exit; + goto error_exit; } #endif } @@ -961,16 +960,16 @@ path_converter(PyObject *o, void *p) path->nullable ? "string, bytes, os.PathLike or None" : "string, bytes or os.PathLike", Py_TYPE(o)->tp_name)) { - goto exit; + goto error_exit; } bytes = PyBytes_FromObject(o); if (!bytes) { - goto exit; + goto error_exit; } } else if (is_index) { if (!_fd_converter(o, &path->fd)) { - goto exit; + goto error_exit; } path->wide = NULL; #ifdef MS_WINDOWS @@ -978,13 +977,10 @@ path_converter(PyObject *o, void *p) #else path->narrow = NULL; #endif - path->length = 0; - path->object = o; - ret = 1; - goto exit; + goto success_exit; } else { - error_exit: + error_format: PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", path->function_name ? path->function_name : "", path->function_name ? ": " : "", @@ -995,15 +991,14 @@ path_converter(PyObject *o, void *p) path->nullable ? "string, bytes, os.PathLike or None" : "string, bytes or os.PathLike", Py_TYPE(o)->tp_name); - goto exit; + goto error_exit; } length = PyBytes_GET_SIZE(bytes); narrow = PyBytes_AS_STRING(bytes); if ((size_t)length != strlen(narrow)) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - Py_DECREF(bytes); - goto exit; + goto error_exit; } #ifdef MS_WINDOWS @@ -1012,43 +1007,51 @@ path_converter(PyObject *o, void *p) length ); if (!wo) { - goto exit; + goto error_exit; } - wide = PyUnicode_AsWideCharString(wo, &length); - Py_DECREF(wo); - + wide = PyUnicode_AsUnicodeAndSize(wo, &length); if (!wide) { - goto exit; + goto error_exit; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto exit; + goto error_exit; } if (wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto exit; + goto error_exit; } path->wide = wide; path->narrow = TRUE; + path->cleanup = wo; + Py_DECREF(bytes); #else path->wide = NULL; path->narrow = narrow; -#endif - path->length = length; - path->object = o; - path->fd = -1; if (bytes == o) { + /* Still a reference owned by path->object, don't have to + worry about path->narrow is used after free. */ Py_DECREF(bytes); - ret = 1; } else { path->cleanup = bytes; - ret = Py_CLEANUP_SUPPORTED; } - exit: - Py_XDECREF(to_cleanup); - return ret; +#endif + path->fd = -1; + + success_exit: + path->length = length; + path->object = o; + return Py_CLEANUP_SUPPORTED; + + error_exit: + Py_XDECREF(o); + Py_XDECREF(bytes); +#ifdef MS_WINDOWS + Py_XDECREF(wo); +#endif + return 0; } static void -- cgit v1.2.1