From 670bb713a2072ebc85240508647aa2489601bc89 Mon Sep 17 00:00:00 2001 From: hakril Date: Wed, 7 Aug 2019 09:47:31 +0200 Subject: [PATCH] Fix a bug about REG_SZ key non-null terminated in values enumeration --- tests/test_registry.py | 23 ++++++++++++++++++++++- windows/winobject/registry.py | 9 ++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/tests/test_registry.py b/tests/test_registry.py index 82d3e5f..411fe38 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -51,11 +51,27 @@ UNICODE_RU_STRING = u"\u0441\u0443\u043a\u0430\u0020\u0431\u043b\u044f\u0442\u04 # But was the cause a special bug / reimplem due to _winreg using ANSI functions # So create a special test with a very identifiable name / bug cause -@pytest.mark.parametrize("unistr", [UNICODE_PATH_NAME, UNICODE_RU_STRING, u""]) +@pytest.mark.parametrize("unistr", ['\u52a9' * 126, UNICODE_PATH_NAME, UNICODE_RU_STRING, u""]) def test_registry_unicode_string_value(unistr): basekeytest["tst3"] = unistr assert basekeytest["tst3"].value == unistr +@pytest.mark.parametrize("unistr", [ + # Looks like this value with this size MAY lead to non-existing NULL BYTE ? + # This bug is tested in test_registry_Reg2Py_SZ + u'c:\\users\\hakril\\appdata\\local\\temp\\test_unicode_\u4e2d\u56fd\u94f6\u884c\u7f51\u94f6\u52a9\u624bdbqsm3', + u'\u52a9' * 126, + UNICODE_PATH_NAME, + UNICODE_PATH_NAME * 10, + UNICODE_RU_STRING * 10, + UNICODE_RU_STRING +]) +def test_registry_unicode_string_values_enumeration(unistr): + basekeytest["tst5"] = unistr + values_by_name = {x.name: x for x in basekeytest.values} + assert values_by_name["tst5"].value == unistr + + def test_registry_unicode_multi_string(): TST_MULTI = [UNICODE_PATH_NAME, "Hello World", UNICODE_RU_STRING] basekeytest["tst4"] = (TST_MULTI, gdef.REG_MULTI_SZ) @@ -164,4 +180,9 @@ def test_registry_unicode_subkeys_enumerate(): assert name2 in subkey_names +# Test Py<->REG conversion bug + +# [99, 0, 58, 0, 92, 0, 117, 0, 115, 0, 101, 0, 114, 0, 115, 0, 92, 0, 104, 0, 97, 0, 107, 0, 114, 0, 105, 0, 108, 0, 92, 0, 97, 0, 112, 0, 112, 0, 100, 0, 97, 0, 116, 0, 97, 0, 92, 0, 108, 0, 111, 0, 99, 0, 97, 0, 108, 0, 92, 0, 116, 0, 101, 0, 109, 0, 112, 0, 92, 0, 116, 0, 101, 0, 115, 0, 116, 0, 95, 0, 117, 0, 110, 0, 105, 0, 99, 0, 111, 0, 100, 0, 101, 0, 95, 0, 45, 78, 253, 86, 246, 148, 76, 136, 81, 127, 246, 148, 169, 82, 75, 98, 100, 0, 98, 0, 113, 0, 115, 0, 109, 0, 51, 0, 0] +# 124 +# def test_registry_Reg2Py_SZ( diff --git a/windows/winobject/registry.py b/windows/winobject/registry.py index fd956e5..1962530 100644 --- a/windows/winobject/registry.py +++ b/windows/winobject/registry.py @@ -18,7 +18,7 @@ class WinRegistryKey(gdef.HKEY): _close_function = staticmethod(winproxy.RegCloseKey) def __del__(self): - if sys.path is None: # Late shutdown (not sur winproxy is still up + if sys is None or sys.path is None: # Late shutdown (not sur winproxy is still up) return if self: # Not NULL handle ? dbgprint(u"Closing registry key handle {0:#x}".format(self.value), 'REGISTRY') @@ -62,7 +62,7 @@ def Reg2Py_SZ(buffer, size): # Buffer is UTF16. buffer is extended-buffer if size == 0: return u"" - if buffer[size] == 0 and buffer[size - 1] == 0: + if buffer[size - 1] == 0 and buffer[size - 2] == 0: # NULL TERMINATED: EASY return buffer.as_wstring() # Not null terminated: keep last byte @@ -198,7 +198,7 @@ class PyHKey(object): max_name_size, max_data_size = self.get_key_size_info() # Null terminators max_name_size += 1 - max_data_size += 1 + max_data_size += 2 with ExpectWindowsError(259): for i in itertools.count(): value_type = gdef.DWORD() @@ -218,14 +218,13 @@ class PyHKey(object): # Update the sizes / buffers & try again :) max_name_size, max_data_size = self.get_key_size_info() max_name_size += 1 - max_data_size += 1 + max_data_size += 2 namesize = gdef.DWORD(max_name_size) keyname = ctypes.create_unicode_buffer(namesize.value) datasize = gdef.DWORD(max_data_size) databuffer = windows.utils.BUFFER(gdef.BYTE, nbelt=datasize.value)() vobj = ENCODE_DECODE_METHODS[value_type.value][DECODE_METHOD](databuffer, datasize.value) res.append(KeyValue(keyname.value, vobj, value_type.value)) - # res.append(vobj) return res