BWindow: Fix confusion between modifiers and "prepared modifiers".
The former must have B_NO_COMMAND_KEY if the shortcut has no command key, while the latter should simply not have B_COMMAND_KEY. This mixup meant that modifiers flags without either set were passed back to BMenuItem, which then used them when calling RemoveShortcut(), but that method expects B_NO_COMMAND_KEY to be specified, so the shortcuts weren't really removed, resulting in use-after-frees. Fixes #19426 and related issues.
This commit is contained in:
@@ -97,10 +97,11 @@ public:
|
|||||||
BMessage* message, BHandler* target);
|
BMessage* message, BHandler* target);
|
||||||
~Shortcut();
|
~Shortcut();
|
||||||
|
|
||||||
bool Matches(uint32 key, uint32 modifiers) const;
|
bool Matches(uint32 key, uint32 preparedModifiers) const;
|
||||||
|
|
||||||
uint32 Key() const { return fKey; };
|
uint32 Key() const { return fKey; };
|
||||||
uint32 Modifiers() const { return fModifiers; };
|
uint32 Modifiers() const;
|
||||||
|
uint32 PreparedModifiers() const { return fPreparedModifiers; };
|
||||||
BMenuItem* MenuItem() const { return fMenuItem; }
|
BMenuItem* MenuItem() const { return fMenuItem; }
|
||||||
BMessage* Message() const { return fMessage; }
|
BMessage* Message() const { return fMessage; }
|
||||||
BHandler* Target() const { return fTarget; }
|
BHandler* Target() const { return fTarget; }
|
||||||
@@ -111,7 +112,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 fKey;
|
uint32 fKey;
|
||||||
uint32 fModifiers;
|
uint32 fPreparedModifiers;
|
||||||
BMenuItem* fMenuItem;
|
BMenuItem* fMenuItem;
|
||||||
BMessage* fMessage;
|
BMessage* fMessage;
|
||||||
BHandler* fTarget;
|
BHandler* fTarget;
|
||||||
@@ -244,7 +245,7 @@ BWindow::unpack_cookie::unpack_cookie()
|
|||||||
BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item)
|
BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item)
|
||||||
:
|
:
|
||||||
fKey(PrepareKey(key)),
|
fKey(PrepareKey(key)),
|
||||||
fModifiers(PrepareModifiers(modifiers)),
|
fPreparedModifiers(PrepareModifiers(modifiers)),
|
||||||
fMenuItem(item),
|
fMenuItem(item),
|
||||||
fMessage(NULL),
|
fMessage(NULL),
|
||||||
fTarget(NULL)
|
fTarget(NULL)
|
||||||
@@ -256,7 +257,7 @@ BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMessage* message,
|
|||||||
BHandler* target)
|
BHandler* target)
|
||||||
:
|
:
|
||||||
fKey(PrepareKey(key)),
|
fKey(PrepareKey(key)),
|
||||||
fModifiers(PrepareModifiers(modifiers)),
|
fPreparedModifiers(PrepareModifiers(modifiers)),
|
||||||
fMenuItem(NULL),
|
fMenuItem(NULL),
|
||||||
fMessage(message),
|
fMessage(message),
|
||||||
fTarget(target)
|
fTarget(target)
|
||||||
@@ -272,9 +273,17 @@ BWindow::Shortcut::~Shortcut()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BWindow::Shortcut::Matches(uint32 key, uint32 modifiers) const
|
BWindow::Shortcut::Matches(uint32 key, uint32 preparedModifiers) const
|
||||||
{
|
{
|
||||||
return fKey == key && fModifiers == modifiers;
|
return fKey == key && fPreparedModifiers == preparedModifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
BWindow::Shortcut::Modifiers() const
|
||||||
|
{
|
||||||
|
return fPreparedModifiers
|
||||||
|
| (((fPreparedModifiers & B_COMMAND_KEY) == 0) ? B_NO_COMMAND_KEY : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3897,12 +3906,12 @@ BWindow::Shortcut*
|
|||||||
BWindow::_FindShortcut(uint32 key, uint32 modifiers)
|
BWindow::_FindShortcut(uint32 key, uint32 modifiers)
|
||||||
{
|
{
|
||||||
key = Shortcut::PrepareKey(key);
|
key = Shortcut::PrepareKey(key);
|
||||||
modifiers = Shortcut::PrepareModifiers(modifiers);
|
uint32 preparedModifiers = Shortcut::PrepareModifiers(modifiers);
|
||||||
|
|
||||||
int32 shortcutCount = fShortcuts.CountItems();
|
int32 shortcutCount = fShortcuts.CountItems();
|
||||||
for (int32 index = 0; index < shortcutCount; index++) {
|
for (int32 index = 0; index < shortcutCount; index++) {
|
||||||
Shortcut* shortcut = (Shortcut*)fShortcuts.ItemAt(index);
|
Shortcut* shortcut = (Shortcut*)fShortcuts.ItemAt(index);
|
||||||
if (shortcut != NULL && shortcut->Matches(key, modifiers))
|
if (shortcut != NULL && shortcut->Matches(key, preparedModifiers))
|
||||||
return shortcut;
|
return shortcut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user