From 83440f4029ac541e90d38132fbe6536c6643b855 Mon Sep 17 00:00:00 2001 From: Olaf Pichler Date: Tue, 9 Apr 2024 23:38:53 +0200 Subject: [PATCH] Return `None` if `deref` encouters a broken reference (fixes #384) (#386) * Return `None` if `deref` finds a broken reference This commit introduces a check before a referenced entry is resolved. If the referenced entry is not found `deref` will return `None`. The commit also includes a test case for this behavior. Fixes: https://github.com/libkeepass/pykeepass/issues/384 * update docstring --------- Co-authored-by: evan --- pykeepass/pykeepass.py | 4 +++- tests/tests.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pykeepass/pykeepass.py b/pykeepass/pykeepass.py index 0e4b37ee..ac43ae7b 100644 --- a/pykeepass/pykeepass.py +++ b/pykeepass/pykeepass.py @@ -687,7 +687,7 @@ def deref(self, value): ref (str): KeePass reference string to another field Returns: - str or uuid.UUID + str, uuid.UUID or None if no match found [fieldref]: https://keepass.info/help/base/fieldrefs.html """ @@ -710,6 +710,8 @@ def deref(self, value): if search_in == 'uuid': search_value = uuid.UUID(search_value) ref_entry = self.find_entries(first=True, **{search_in: search_value}) + if ref_entry is None: + return None value = value.replace(ref, getattr(ref_entry, wanted_field)) return self.deref(value) diff --git a/tests/tests.py b/tests/tests.py index 5bc02b6d..dfe2f539 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -528,6 +528,20 @@ def test_references(self): self.assertNotEqual(original_entry, clone1) self.assertNotEqual(clone1, clone2) + def test_broken_reference(self): + # TODO: move the entry into test databases + broken_entry_title = 'broken reference' + self.kp.add_entry( + self.kp.root_group, + title=broken_entry_title, + username='{REF:U@I:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}', + password='{REF:P@I:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}', + ) + broken_entry = self.kp.find_entries(title=broken_entry_title, first=True) + self.assertEqual(broken_entry.deref('username'), None) + self.assertEqual(broken_entry.deref('password'), None) + self.kp.delete_entry(broken_entry) + def test_set_and_get_fields(self): time = datetime.now(timezone.utc).replace(microsecond=0) changed_time = time + timedelta(hours=9)