<input>keyboard: Fix use-after-free on dead key completion.
When completing a dead key the already freed string was used to build the input method changed notification. Use an ArrayDeleter to simplify management of the two strings.
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -419,18 +420,20 @@ KeyboardDevice::_ControlThread()
|
|||||||
char* string = NULL;
|
char* string = NULL;
|
||||||
char* rawString = NULL;
|
char* rawString = NULL;
|
||||||
int32 numBytes = 0, rawNumBytes = 0;
|
int32 numBytes = 0, rawNumBytes = 0;
|
||||||
|
|
||||||
|
ArrayDeleter<char> stringDeleter;
|
||||||
if (newDeadKey == 0) {
|
if (newDeadKey == 0) {
|
||||||
fKeymap.GetChars(keycode, fModifiers, activeDeadKey, &string,
|
fKeymap.GetChars(keycode, fModifiers, activeDeadKey, &string,
|
||||||
&numBytes);
|
&numBytes);
|
||||||
|
stringDeleter.SetTo(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
fKeymap.GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
|
fKeymap.GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
|
||||||
|
ArrayDeleter<char> rawStringDeleter(rawString);
|
||||||
|
|
||||||
BMessage* msg = new BMessage;
|
BMessage* msg = new BMessage;
|
||||||
if (msg == NULL) {
|
if (msg == NULL)
|
||||||
delete[] string;
|
|
||||||
delete[] rawString;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (numBytes > 0)
|
if (numBytes > 0)
|
||||||
msg->what = isKeyDown ? B_KEY_DOWN : B_KEY_UP;
|
msg->what = isKeyDown ? B_KEY_DOWN : B_KEY_UP;
|
||||||
@@ -448,24 +451,19 @@ KeyboardDevice::_ControlThread()
|
|||||||
|
|
||||||
if (rawNumBytes <= 0) {
|
if (rawNumBytes <= 0) {
|
||||||
rawNumBytes = 1;
|
rawNumBytes = 1;
|
||||||
delete[] rawString;
|
|
||||||
rawString = string;
|
rawString = string;
|
||||||
} else
|
}
|
||||||
delete[] string;
|
|
||||||
|
|
||||||
if (isKeyDown && lastKeyCode == keycode) {
|
if (isKeyDown && lastKeyCode == keycode) {
|
||||||
repeatCount++;
|
repeatCount++;
|
||||||
msg->AddInt32("be:key_repeat", repeatCount);
|
msg->AddInt32("be:key_repeat", repeatCount);
|
||||||
} else
|
} else
|
||||||
repeatCount = 1;
|
repeatCount = 1;
|
||||||
} else
|
}
|
||||||
delete[] string;
|
|
||||||
|
|
||||||
if (rawNumBytes > 0)
|
if (rawNumBytes > 0)
|
||||||
msg->AddInt32("raw_char", (uint32)((uint8)rawString[0] & 0x7f));
|
msg->AddInt32("raw_char", (uint32)((uint8)rawString[0] & 0x7f));
|
||||||
|
|
||||||
delete[] rawString;
|
|
||||||
|
|
||||||
if (newDeadKey == 0) {
|
if (newDeadKey == 0) {
|
||||||
if (isKeyDown && !modifiers && activeDeadKey != 0) {
|
if (isKeyDown && !modifiers && activeDeadKey != 0) {
|
||||||
// a dead key was completed
|
// a dead key was completed
|
||||||
|
|||||||
Reference in New Issue
Block a user