summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSSE4 <tomskside@gmail.com>2018-02-12 17:10:35 (GMT)
committerBerker Peksag <berker.peksag@gmail.com>2018-02-12 17:10:35 (GMT)
commit3c34aad4e7a95913ec7db8e5e948a8fc69047bf7 (patch)
tree53894ed7dec376f07d8e9a6944e6ae97dc533156
parent6ea20fc719dcaf102d2cefa1786f0421514f7a58 (diff)
downloadcpython-3c34aad4e7a95913ec7db8e5e948a8fc69047bf7.zip
cpython-3c34aad4e7a95913ec7db8e5e948a8fc69047bf7.tar.gz
cpython-3c34aad4e7a95913ec7db8e5e948a8fc69047bf7.tar.bz2
bpo-29248: Fix os.readlink() on Windows (GH-5577)
The PrintNameOffset field of the reparse data buffer was treated as a number of characters instead of bytes.
-rw-r--r--Lib/test/test_os.py15
-rw-r--r--Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst3
-rw-r--r--Modules/posixmodule.c6
3 files changed, 21 insertions, 3 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 02611d2..77e4a00 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2165,6 +2165,21 @@ class Win32SymlinkTests(unittest.TestCase):
finally:
os.chdir(orig_dir)
+ @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users')
+ and os.path.exists(r'C:\ProgramData'),
+ 'Test directories not found')
+ def test_29248(self):
+ # os.symlink() calls CreateSymbolicLink, which creates
+ # the reparse data buffer with the print name stored
+ # first, so the offset is always 0. CreateSymbolicLink
+ # stores the "PrintName" DOS path (e.g. "C:\") first,
+ # with an offset of 0, followed by the "SubstituteName"
+ # NT path (e.g. "\??\C:\"). The "All Users" link, on
+ # the other hand, seems to have been created manually
+ # with an inverted order.
+ target = os.readlink(r'C:\Users\All Users')
+ self.assertTrue(os.path.samefile(target, r'C:\ProgramData'))
+
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
class Win32JunctionTests(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst
new file mode 100644
index 0000000..3030ef6
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst
@@ -0,0 +1,3 @@
+Fix :func:`os.readlink` on Windows, which was mistakenly treating the
+``PrintNameOffset`` field of the reparse data buffer as a number of
+characters instead of bytes. Patch by Craig Holmquist and SSE4.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 84b5b99..72fda6a 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -7439,11 +7439,11 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
"not a symbolic link");
return NULL;
}
- print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
- rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
+ print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
+ rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
result = PyUnicode_FromWideChar(print_name,
- rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
+ rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t));
return result;
}