Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug where pressing home on empty tag field crashes the program. #11346

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

libklein
Copy link
Contributor

Fix bug where pressing home on empty tag field crashes the program.

Bug is caused by https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L340. The currentText().isEmpty() allows to invalidate the invariant if the current (and only) tag is empty. In this case, tags is resized to 0 (the only tag is erased) and the program crashes as currentText() accessed in https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L504 fails as the tags list is now empty (https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L387).

Fixes: #11344

  • ✅ Bug fix (non-breaking change that fixes an issue)

@@ -337,7 +337,7 @@ struct TagsEdit::Impl
assert(i < tags.size());
auto occurrencesOfCurrentText =
std::count_if(tags.cbegin(), tags.cend(), [this](const auto& tag) { return tag.text == currentText(); });
if (currentText().isEmpty() || occurrencesOfCurrentText > 1) {
if ((currentText().isEmpty() && tags.size() > 1) || occurrencesOfCurrentText > 1) {
tags.erase(std::next(tags.begin(), std::ptrdiff_t(editing_index)));
Copy link
Member

@droidmonkey droidmonkey Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes this line is ugly as sin. The line below this is what actually causes the crash because it decrements the editing index to -1. We also need to put guards in place in the currentText functions that blindly take the editing_index without any bounds checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change fixes the specific problem. The tags list will have at least size of 1, such that even after running the function, editing_index will be >=0 and the invariant hold.

Adding guards is probably a good idea, but I'd suggest to do some refactoring instead: What would be a good fallback for currentText() if editing_index is OoB? Crash gracefully? currentRect and currentText may return a reference.

Copy link
Member

@droidmonkey droidmonkey Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentText should return an empty string and currentRect a zero sized rect. At the end of the day the variables in this class are not safe and the class needs to be refactored to make it safer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the current design of the class, I'd consider handling out-of-bounds as follows:
If tags is not empty, set editing_index to 0, then return tags[editing_index].
If tags is empty, add an empty tag, set editing_index to 0 and return.

Alternatively, we could introduce set/get currentText()/currentRect() member functions to avoid the reference problem (currentText() and currentRect() return references that are actually written to https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L399. This would be my preferred option.

Copy link
Member

@droidmonkey droidmonkey Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just nuts, we should never be returning a reference to a QString. QString is optimized in the backend. If you are inside the class you don't/shouldn't generally use setter/getter functions. Those are meant for external users of the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

KeePassXC 2.7.9 crashes when pressing Home/End keyboard keys in the tag field on Linux
2 participants