From 40fa26606d0dc3adfa05ae4a760b3b6b189df075 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Sat, 17 Dec 2016 13:30:27 -0800 Subject: Issue #25778: winreg does not truncase string correctly (Patch by Eryk Sun) --- Lib/test/test_winreg.py | 14 +++++++++++++- Misc/NEWS | 2 ++ PC/winreg.c | 13 ++++++------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index d642b13..2be61ae 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -57,7 +57,7 @@ class BaseWinregTests(unittest.TestCase): def delete_tree(self, root, subkey): try: - hkey = OpenKey(root, subkey, KEY_ALL_ACCESS) + hkey = OpenKey(root, subkey, 0, KEY_ALL_ACCESS) except OSError: # subkey does not exist return @@ -368,6 +368,18 @@ class LocalWinregTests(BaseWinregTests): finally: DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_read_string_containing_null(self): + # Test for issue 25778: REG_SZ should not contain null characters + try: + with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: + self.assertNotEqual(ck.handle, 0) + test_val = "A string\x00 with a null" + SetValueEx(ck, "test_name", 0, REG_SZ, test_val) + ret_val, ret_type = QueryValueEx(ck, "test_name") + self.assertEqual(ret_type, REG_SZ) + self.assertEqual(ret_val, "A string") + finally: + DeleteKey(HKEY_CURRENT_USER, test_key_name) @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests") diff --git a/Misc/NEWS b/Misc/NEWS index ed10395..4a39f06 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,8 @@ Library Windows ------- +- Issue #25778: winreg does not truncase string correctly (Patch by Eryk Sun) + - Issue #28896: Deprecate WindowsRegistryFinder and disable it by default. Tests diff --git a/PC/winreg.c b/PC/winreg.c index 9524838..5efdc5e 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -719,14 +719,13 @@ Reg2Py(BYTE *retDataBuf, DWORD retDataSize, DWORD typ) case REG_SZ: case REG_EXPAND_SZ: { - /* the buffer may or may not have a trailing NULL */ + /* REG_SZ should be a NUL terminated string, but only by + * convention. The buffer may have been saved without a NUL + * or with embedded NULs. To be consistent with reg.exe and + * regedit.exe, consume only up to the first NUL. */ wchar_t *data = (wchar_t *)retDataBuf; - int len = retDataSize / 2; - if (retDataSize && data[len-1] == '\0') - retDataSize -= 2; - if (retDataSize <= 0) - data = L""; - obData = PyUnicode_FromWideChar(data, retDataSize/2); + size_t len = wcsnlen(data, retDataSize / sizeof(wchar_t)); + obData = PyUnicode_FromWideChar(data, len); break; } case REG_MULTI_SZ: -- cgit v0.12