Issue #23908: os functions, open() and the io.FileIO constructor now reject
unicode paths with embedded null character on Windows instead of silently
truncate them.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 4fc3ef7..df3c326 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -1646,13 +1646,9 @@
PyObject *result;
#ifdef MS_WINDOWS
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, wformat, &po)) {
- Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
-
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, wformat, &wpath)) {
Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE result OK without
- thread lock as it is a simple dereference. */
res = wstatfunc(wpath, &st);
Py_END_ALLOW_THREADS
@@ -1706,12 +1702,10 @@
#ifdef MS_WINDOWS
DWORD attr;
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "ui:access", &wpath, &mode)) {
Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE OK without thread lock as
- it is a simple dereference. */
- attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
+ attr = GetFileAttributesW(wpath);
Py_END_ALLOW_THREADS
goto finish;
}
@@ -1858,23 +1852,22 @@
int res;
#ifdef MS_WINDOWS
DWORD attr;
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "ui|:chmod", &wpath, &i)) {
Py_BEGIN_ALLOW_THREADS
- attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
+ attr = GetFileAttributesW(wpath);
if (attr != 0xFFFFFFFF) {
if (i & _S_IWRITE)
attr &= ~FILE_ATTRIBUTE_READONLY;
else
attr |= FILE_ATTRIBUTE_READONLY;
- res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
+ res = SetFileAttributesW(wpath, attr);
}
else
res = 0;
Py_END_ALLOW_THREADS
if (!res)
- return win32_error_unicode("chmod",
- PyUnicode_AS_UNICODE(po));
+ return win32_error_unicode("chmod", wpath);
Py_INCREF(Py_None);
return Py_None;
}
@@ -2300,18 +2293,18 @@
char *bufptr = namebuf;
Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
- PyObject *po;
- if (PyArg_ParseTuple(args, "U:listdir", &po)) {
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "u:listdir", &wpath)) {
WIN32_FIND_DATAW wFileData;
Py_UNICODE *wnamebuf;
/* Overallocate for \\*.*\0 */
- len = PyUnicode_GET_SIZE(po);
+ len = wcslen(wpath);
wnamebuf = malloc((len + 5) * sizeof(wchar_t));
if (!wnamebuf) {
PyErr_NoMemory();
return NULL;
}
- wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po));
+ wcscpy(wnamebuf, wpath);
if (len > 0) {
Py_UNICODE wch = wnamebuf[len-1];
if (wch != L'/' && wch != L'\\' && wch != L':')
@@ -2615,9 +2608,8 @@
char outbuf[MAX_PATH*2];
char *temp;
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
- Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "u|:_getfullpathname", &wpath)) {
Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
Py_UNICODE *wtemp;
DWORD result;
@@ -2670,15 +2662,13 @@
int mode = 0777;
#ifdef MS_WINDOWS
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "u|i:mkdir", &wpath, &mode)) {
Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE OK without thread lock as
- it is a simple dereference. */
- res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
+ res = CreateDirectoryW(wpath, NULL);
Py_END_ALLOW_THREADS
if (!res)
- return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
+ return win32_error_unicode("mkdir", wpath);
Py_INCREF(Py_None);
return Py_None;
}
@@ -2689,8 +2679,6 @@
Py_FileSystemDefaultEncoding, &path, &mode))
return NULL;
Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE OK without thread lock as
- it is a simple dereference. */
res = CreateDirectoryA(path, NULL);
Py_END_ALLOW_THREADS
if (!res) {
@@ -2833,7 +2821,7 @@
posix_stat(PyObject *self, PyObject *args)
{
#ifdef MS_WINDOWS
- return posix_do_stat(self, args, "et:stat", STAT, "U:stat", win32_wstat);
+ return posix_do_stat(self, args, "et:stat", STAT, "u:stat", win32_wstat);
#else
return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
#endif
@@ -2969,7 +2957,6 @@
{
#ifdef MS_WINDOWS
PyObject *arg;
- PyUnicodeObject *obwpath;
wchar_t *wpath = NULL;
char *apath = NULL;
HANDLE hFile;
@@ -2978,8 +2965,7 @@
FILETIME atime, mtime;
PyObject *result = NULL;
- if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
- wpath = PyUnicode_AS_UNICODE(obwpath);
+ if (PyArg_ParseTuple(args, "uO|:utime", &wpath, &arg)) {
Py_BEGIN_ALLOW_THREADS
hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
NULL, OPEN_EXISTING,
@@ -4440,14 +4426,11 @@
static PyObject *
posix__isdir(PyObject *self, PyObject *args)
{
- PyObject *opath;
char *path;
- PyUnicodeObject *po;
+ Py_UNICODE *wpath;
DWORD attributes;
- if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
- Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
-
+ if (PyArg_ParseTuple(args, "u|:_isdir", &wpath)) {
attributes = GetFileAttributesW(wpath);
if (attributes == INVALID_FILE_ATTRIBUTES)
Py_RETURN_FALSE;
@@ -6326,7 +6309,7 @@
return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
#else /* !HAVE_LSTAT */
#ifdef MS_WINDOWS
- return posix_do_stat(self, args, "et:lstat", STAT, "U:lstat", win32_wstat);
+ return posix_do_stat(self, args, "et:lstat", STAT, "u:lstat", win32_wstat);
#else
return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
#endif
@@ -6600,12 +6583,10 @@
int fd;
#ifdef MS_WINDOWS
- PyUnicodeObject *po;
- if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) {
+ Py_UNICODE *wpath;
+ if (PyArg_ParseTuple(args, "ui|i:mkdir", &wpath, &flag, &mode)) {
Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE OK without thread
- lock as it is a simple dereference. */
- fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode);
+ fd = _wopen(wpath, flag, mode);
Py_END_ALLOW_THREADS
if (fd < 0)
return posix_error();
@@ -8662,12 +8643,13 @@
win32_startfile(PyObject *self, PyObject *args)
{
char *filepath;
+ Py_UNICODE *wpath;
char *operation = NULL;
HINSTANCE rc;
- PyObject *unipath, *woperation = NULL;
- if (!PyArg_ParseTuple(args, "U|s:startfile",
- &unipath, &operation)) {
+ PyObject *woperation = NULL;
+ if (!PyArg_ParseTuple(args, "u|s:startfile",
+ &wpath, &operation)) {
PyErr_Clear();
goto normal;
}
@@ -8684,14 +8666,13 @@
Py_BEGIN_ALLOW_THREADS
rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
- PyUnicode_AS_UNICODE(unipath),
+ wpath,
NULL, NULL, SW_SHOWNORMAL);
Py_END_ALLOW_THREADS
Py_XDECREF(woperation);
if (rc <= (HINSTANCE)32) {
- PyObject *errval = win32_error_unicode("startfile",
- PyUnicode_AS_UNICODE(unipath));
+ PyObject *errval = win32_error_unicode("startfile", wpath);
return errval;
}
Py_INCREF(Py_None);