From 86906b7cb471fa0f9f7fd8a391d3b10b2fc29046 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 2 Jun 2023 13:57:57 +0000 Subject: InputMethodSubtypeArray: prevent negative count injection Fixes an issue where negative counts could be injected via the Parcel constructor. The writeToParcel method in that case would write data that a subsequent read would not consume. Fixes: 277916797 Fixes: 354682735 Test: atest InputMethodSubtypeArrayTest Merged-In: I7e881d82415051179c59bf5df97f8ba0a41e693e Change-Id: I7e881d82415051179c59bf5df97f8ba0a41e693e --- .../view/inputmethod/InputMethodSubtypeArray.java | 4 +++ .../inputmethod/InputMethodSubtypeArrayTest.java | 36 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java index 50e95c80cfed..ee36dc72e346 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java +++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java @@ -17,6 +17,7 @@ package android.view.inputmethod; import android.compat.annotation.UnsupportedAppUsage; +import android.os.BadParcelableException; import android.os.Parcel; import android.util.Slog; @@ -69,6 +70,9 @@ public class InputMethodSubtypeArray { */ public InputMethodSubtypeArray(final Parcel source) { mCount = source.readInt(); + if (mCount < 0) { + throw new BadParcelableException("mCount must be non-negative."); + } if (mCount > 0) { mDecompressedSize = source.readInt(); mCompressedData = source.createByteArray(); diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java index e2fb46af5b64..5af8558ccde9 100644 --- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java @@ -16,9 +16,14 @@ package android.view.inputmethod; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + import static org.junit.Assert.assertEquals; +import android.os.BadParcelableException; import android.os.Parcel; +import android.platform.test.annotations.Presubmit; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import androidx.test.filters.SmallTest; @@ -31,6 +36,7 @@ import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) +@Presubmit public class InputMethodSubtypeArrayTest { @Test @@ -59,6 +65,36 @@ public class InputMethodSubtypeArrayTest { assertEquals(clonedArray.get(2), clonedClonedArray.get(2)); } + @Test + public void testNegativeCount() throws Exception { + InputMethodSubtypeArray negativeCountArray; + try { + // Construct a InputMethodSubtypeArray with: mCount = -1 + Parcel p = Parcel.obtain(); + p.writeInt(-1); + p.setDataPosition(0); + negativeCountArray = new InputMethodSubtypeArray(p); + } catch (BadParcelableException e) { + // Expected with fix: Prevent negative mCount + assertThat(e).hasMessageThat().contains("mCount"); + return; + } + assertWithMessage("Test set-up failed") + .that(negativeCountArray.getCount()).isEqualTo(-1); + + Parcel p = Parcel.obtain(); + // Writes: int (mCount), int (mDecompressedSize), byte[] (mCompressedData) + negativeCountArray.writeToParcel(p); + p.setDataPosition(0); + // Reads: int (mCount) + // Leaves: int (mDecompressedSize), byte[] (mCompressedData) + new InputMethodSubtypeArray(p); + + assertWithMessage("Didn't read all data that was previously written") + .that(p.dataPosition()) + .isEqualTo(p.dataSize()); + } + InputMethodSubtypeArray cloneViaParcel(final InputMethodSubtypeArray original) { Parcel parcel = null; try { -- cgit v1.2.3-59-g8ed1b