Bug 1303273 part.5 UniCharsAndModifiers should hide mChars r?m_kato
Now, we have an security issue. mCommittedCharsAndModifiers may be initialized with multiple WM_(SYS)CHAR messages. However, if it's generated by odd (or malicious) middleware, mCommittedCharsAndModifiers may be overflown because it has only fixed array. For fixing this issue, first, we should hide the members for making the users not depend on the design of UniCharsAndModifiers.
This patch changes UniCharsAndModifiers to a class and hiding mChars and adding |CharAt() const|.
MozReview-Commit-ID: 5EjrIhmCdE4
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -620,26 +620,26 @@ ToString(const MSG& aMSG)
static const nsCString
ToString(const UniCharsAndModifiers& aUniCharsAndModifiers)
{
if (aUniCharsAndModifiers.IsEmpty()) {
return NS_LITERAL_CSTRING("{}");
}
nsAutoCString result;
result.AssignLiteral("{ ");
- result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[0]));
+ result.Append(GetCharacterCodeName(aUniCharsAndModifiers.CharAt(0)));
for (uint32_t i = 1; i < aUniCharsAndModifiers.mLength; ++i) {
if (aUniCharsAndModifiers.mModifiers[i - 1] !=
aUniCharsAndModifiers.mModifiers[i]) {
result.AppendLiteral(" [");
result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[0]));
result.AppendLiteral("]");
}
result.AppendLiteral(", ");
- result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[i]));
+ result.Append(GetCharacterCodeName(aUniCharsAndModifiers.CharAt(i)));
}
result.AppendLiteral(" [");
uint32_t lastIndex = aUniCharsAndModifiers.mLength - 1;
result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[lastIndex]));
result.AppendLiteral("] }");
return result;
}
@@ -3142,30 +3142,30 @@ NativeKey::ComputeInputtingStringWithKey
&mUnshiftedLatinChar,
&mShiftedLatinChar);
// If the mShiftedLatinChar isn't 0, the key code is NS_VK_[A-Z].
if (mShiftedLatinChar) {
// If the produced characters of the key on current keyboard layout
// are same as computed Latin characters, we shouldn't append the
// Latin characters to alternativeCharCode.
- if (mUnshiftedLatinChar == mUnshiftedString.mChars[0] &&
- mShiftedLatinChar == mShiftedString.mChars[0]) {
+ if (mUnshiftedLatinChar == mUnshiftedString.CharAt(0) &&
+ mShiftedLatinChar == mShiftedString.CharAt(0)) {
mShiftedLatinChar = mUnshiftedLatinChar = 0;
}
} else if (mUnshiftedLatinChar) {
// If the mShiftedLatinChar is 0, the mKeyCode doesn't produce
// alphabet character. At that time, the character may be produced
// with Shift key. E.g., on French keyboard layout, NS_VK_PERCENT
// key produces LATIN SMALL LETTER U WITH GRAVE (U+00F9) without
// Shift key but with Shift key, it produces '%'.
// If the mUnshiftedLatinChar is produced by the key on current
// keyboard layout, we shouldn't append it to alternativeCharCode.
- if (mUnshiftedLatinChar == mUnshiftedString.mChars[0] ||
- mUnshiftedLatinChar == mShiftedString.mChars[0]) {
+ if (mUnshiftedLatinChar == mUnshiftedString.CharAt(0) ||
+ mUnshiftedLatinChar == mShiftedString.CharAt(0)) {
mUnshiftedLatinChar = 0;
}
}
if (!mModKeyState.IsControl()) {
return;
}
@@ -3373,17 +3373,17 @@ NativeKey::WillDispatchKeyboardEvent(Wid
mInputtingStringAndModifiers.mModifiers[aIndex - skipUniChars]);
modKeyState.InitInputEvent(aKeyboardEvent);
MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
("%p NativeKey::WillDispatchKeyboardEvent(), "
"setting %uth modifier state to %s",
this, aIndex + 1, ToString(modKeyState).get()));
}
uint16_t uniChar =
- mInputtingStringAndModifiers.mChars[aIndex - skipUniChars];
+ mInputtingStringAndModifiers.CharAt(aIndex - skipUniChars);
// The mCharCode was set from mKeyValue. However, for example, when Ctrl key
// is pressed, its value should indicate an ASCII character for backward
// compatibility rather than inputting character without the modifiers.
// Therefore, we need to modify mCharCode value here.
aKeyboardEvent.SetCharCode(uniChar);
MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
("%p NativeKey::WillDispatchKeyboardEvent(), "
@@ -3409,20 +3409,20 @@ NativeKey::WillDispatchKeyboardEvent(Wid
count = longestLength - aIndex;
}
} else {
count = longestLength;
}
for (size_t i = 0; i < count; ++i) {
uint16_t shiftedChar = 0, unshiftedChar = 0;
if (skipShiftedChars <= aIndex + i) {
- shiftedChar = mShiftedString.mChars[aIndex + i - skipShiftedChars];
+ shiftedChar = mShiftedString.CharAt(aIndex + i - skipShiftedChars);
}
if (skipUnshiftedChars <= aIndex + i) {
- unshiftedChar = mUnshiftedString.mChars[aIndex + i - skipUnshiftedChars];
+ unshiftedChar = mUnshiftedString.CharAt(aIndex + i - skipUnshiftedChars);
}
if (shiftedChar || unshiftedChar) {
AlternativeCharCode chars(unshiftedChar, shiftedChar);
altArray.AppendElement(chars);
}
if (!isLastIndex) {
@@ -3443,18 +3443,18 @@ NativeKey::WillDispatchKeyboardEvent(Wid
char16_t charForOEMKeyCode = 0;
switch (mVirtualKeyCode) {
case VK_OEM_PLUS: charForOEMKeyCode = '+'; break;
case VK_OEM_COMMA: charForOEMKeyCode = ','; break;
case VK_OEM_MINUS: charForOEMKeyCode = '-'; break;
case VK_OEM_PERIOD: charForOEMKeyCode = '.'; break;
}
if (charForOEMKeyCode &&
- charForOEMKeyCode != mUnshiftedString.mChars[0] &&
- charForOEMKeyCode != mShiftedString.mChars[0] &&
+ charForOEMKeyCode != mUnshiftedString.CharAt(0) &&
+ charForOEMKeyCode != mShiftedString.CharAt(0) &&
charForOEMKeyCode != mUnshiftedLatinChar &&
charForOEMKeyCode != mShiftedLatinChar) {
AlternativeCharCode OEMChars(charForOEMKeyCode, charForOEMKeyCode);
altArray.AppendElement(OEMChars);
}
}
}
@@ -3780,22 +3780,22 @@ KeyboardLayout::MaybeInitNativeKeyWithCo
if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey)) ||
NS_WARN_IF(!IsPrintableCharKey(aNativeKey.mOriginalVirtualKeyCode))) {
return false;
}
UniCharsAndModifiers baseChars =
GetUniCharsAndModifiers(aNativeKey.mOriginalVirtualKeyCode, aModKeyState);
- if (baseChars.IsEmpty() || !baseChars.mChars[0]) {
+ if (baseChars.IsEmpty() || !baseChars.CharAt(0)) {
return false;
}
char16_t compositeChar =
- GetCompositeChar(mActiveDeadKey, mDeadKeyShiftState, baseChars.mChars[0]);
+ GetCompositeChar(mActiveDeadKey, mDeadKeyShiftState, baseChars.CharAt(0));
if (!compositeChar) {
return false;
}
// Active dead-key and base character does produce exactly one composite
// character.
aNativeKey.mCommittedCharsAndModifiers.Append(compositeChar,
baseChars.mModifiers[0]);
@@ -4429,25 +4429,25 @@ KeyboardLayout::ConvertNativeKeyCodeToDO
case VK_ABNT_C1:
{
NS_ASSERTION(IsPrintableCharKey(aNativeKeyCode),
"The key must be printable");
ModifierKeyState modKeyState(0);
UniCharsAndModifiers uniChars =
GetUniCharsAndModifiers(aNativeKeyCode, modKeyState);
if (uniChars.mLength != 1 ||
- uniChars.mChars[0] < ' ' || uniChars.mChars[0] > 0x7F) {
+ uniChars.CharAt(0) < ' ' || uniChars.CharAt(0) > 0x7F) {
modKeyState.Set(MODIFIER_SHIFT);
uniChars = GetUniCharsAndModifiers(aNativeKeyCode, modKeyState);
if (uniChars.mLength != 1 ||
- uniChars.mChars[0] < ' ' || uniChars.mChars[0] > 0x7F) {
+ uniChars.CharAt(0) < ' ' || uniChars.CharAt(0) > 0x7F) {
return 0;
}
}
- return WidgetUtils::ComputeKeyCodeFromChar(uniChars.mChars[0]);
+ return WidgetUtils::ComputeKeyCodeFromChar(uniChars.CharAt(0));
}
// IE sets 0xC2 to the DOM keyCode for VK_ABNT_C2. However, we're already
// using NS_VK_SEPARATOR for the separator key on Mac and Linux. Therefore,
// We should keep consistency between Gecko on all platforms rather than
// with other browsers since a lot of keyCode values are already different
// between browsers.
case VK_ABNT_C2:
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -52,41 +52,49 @@ static const uint32_t sModifierKeyMap[][
{ nsIWidget::CTRL_L, VK_CONTROL, VK_LCONTROL },
{ nsIWidget::CTRL_R, VK_CONTROL, VK_RCONTROL },
{ nsIWidget::ALT_L, VK_MENU, VK_LMENU },
{ nsIWidget::ALT_R, VK_MENU, VK_RMENU }
};
class KeyboardLayout;
-struct UniCharsAndModifiers
+class UniCharsAndModifiers final
{
+public:
// Dead-key + up to 4 characters
- char16_t mChars[5];
Modifiers mModifiers[5];
uint32_t mLength;
UniCharsAndModifiers() : mLength(0) {}
UniCharsAndModifiers operator+(const UniCharsAndModifiers& aOther) const;
UniCharsAndModifiers& operator+=(const UniCharsAndModifiers& aOther);
/**
* Append a pair of unicode character and the final modifier.
*/
void Append(char16_t aUniChar, Modifiers aModifiers);
void Clear() { mLength = 0; }
bool IsEmpty() const { return !mLength; }
+ char16_t CharAt(size_t aIndex) const
+ {
+ MOZ_ASSERT(aIndex < mLength);
+ return mChars[aIndex];
+ }
void FillModifiers(Modifiers aModifiers);
bool UniCharsEqual(const UniCharsAndModifiers& aOther) const;
bool UniCharsCaseInsensitiveEqual(const UniCharsAndModifiers& aOther) const;
bool BeginsWith(const UniCharsAndModifiers& aOther) const;
nsString ToString() const { return nsString(mChars, mLength); }
+
+private:
+ char16_t mChars[5];
};
struct DeadKeyEntry;
class DeadKeyTable;
class VirtualKey
{