aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Zivkovic <zivkovic@google.com>2015-02-27 10:13:06 -0800
committerDan Zivkovic <zivkovic@google.com>2015-02-27 10:29:47 -0800
commit69c04cadc7c017f9de53f13ea045347b80316d4a (patch)
tree5593b38ec5da9bb611fa1ce2c6f30824812dc23d
parent8472b36886c1b94ad308cc3479acb2215ac44318 (diff)
downloadlatinime-69c04cadc7c017f9de53f13ea045347b80316d4a.tar.gz
latinime-69c04cadc7c017f9de53f13ea045347b80316d4a.tar.xz
latinime-69c04cadc7c017f9de53f13ea045347b80316d4a.zip
Race condition in cursor move.
The method WordComposer.moveCursorByAndReturnIfInsideComposingWord() iterates through all the code points in the word that's currently being composed, and it tries to adjust the cursor position by a given amount (left or right). It copies the code points to a new array while processing. But the code point count comes from a member variable. If the member variable changes while the method is processing the copy of the code points, it can run over the length of the code point array. Bug 18876474. Change-Id: Ib3a2d90a4e82b76d381efa774e6b3d6bca99c869
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java18
1 files changed, 10 insertions, 8 deletions
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 32ef1021d..8803edc88 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -232,31 +232,33 @@ public final class WordComposer {
* @return true if the cursor is still inside the composing word, false otherwise.
*/
public boolean moveCursorByAndReturnIfInsideComposingWord(final int expectedMoveAmount) {
- int actualMoveAmountWithinWord = 0;
+ int actualMoveAmount = 0;
int cursorPos = mCursorPositionWithinWord;
// TODO: Don't make that copy. We can do this directly from mTypedWordCache.
final int[] codePoints = StringUtils.toCodePointArray(mTypedWordCache);
if (expectedMoveAmount >= 0) {
// Moving the cursor forward for the expected amount or until the end of the word has
// been reached, whichever comes first.
- while (actualMoveAmountWithinWord < expectedMoveAmount && cursorPos < mCodePointSize) {
- actualMoveAmountWithinWord += Character.charCount(codePoints[cursorPos]);
+ while (actualMoveAmount < expectedMoveAmount && cursorPos < codePoints.length) {
+ actualMoveAmount += Character.charCount(codePoints[cursorPos]);
++cursorPos;
}
} else {
// Moving the cursor backward for the expected amount or until the start of the word
// has been reached, whichever comes first.
- while (actualMoveAmountWithinWord > expectedMoveAmount && cursorPos > 0) {
+ while (actualMoveAmount > expectedMoveAmount && cursorPos > 0) {
--cursorPos;
- actualMoveAmountWithinWord -= Character.charCount(codePoints[cursorPos]);
+ actualMoveAmount -= Character.charCount(codePoints[cursorPos]);
}
}
// If the actual and expected amounts differ, we crossed the start or the end of the word
// so the result would not be inside the composing word.
- if (actualMoveAmountWithinWord != expectedMoveAmount) return false;
+ if (actualMoveAmount != expectedMoveAmount) {
+ return false;
+ }
mCursorPositionWithinWord = cursorPos;
- mCombinerChain.applyProcessedEvent(mCombinerChain.processEvent(mEvents,
- Event.createCursorMovedEvent(cursorPos)));
+ mCombinerChain.applyProcessedEvent(mCombinerChain.processEvent(
+ mEvents, Event.createCursorMovedEvent(cursorPos)));
return true;
}