Truncate WindowInfo.name during parcelling.

This is a mitigation for an exploit of one-way binder call overflow.

Bug: 433251166
Test: presubmit
Flag: EXEMPT BUGFIX
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:03b9ecf49d11630d5992da30265fb03621846ce1
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:1d4bb5d8bef543769e3fef7d4f4bc720696cd7cd
Merged-In: I7ed75c7a11e9ca30b2dd1287953b2f0e426c3415
Change-Id: I7ed75c7a11e9ca30b2dd1287953b2f0e426c3415
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 3fb66d1..817ca5e 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -28,6 +28,26 @@
 
 namespace {
 
+constexpr size_t kMaxBytesName = 1024;
+
+// Avoiding pulling in ICU here.
+status_t writeUtf8AsUtf16WithTruncation(Parcel* parcel, const std::string& str, size_t max_bytes) {
+    if (str.size() <= max_bytes) {
+        return parcel->writeUtf8AsUtf16(str);
+    }
+    std::string truncated;
+    truncated.reserve(max_bytes);
+    static constexpr std::string_view kTail = "[TRUNC]";
+    size_t truncated_length = max_bytes - kTail.size();
+    while (truncated_length > 0 &&
+           (static_cast<unsigned char>(str[truncated_length]) & 0xC0) == 0x80) {
+        truncated_length--;
+    }
+    truncated.append(str.substr(0, truncated_length));
+    truncated.append(kTail);
+    return parcel->writeUtf8AsUtf16(truncated);
+}
+
 std::ostream& operator<<(std::ostream& out, const sp<IBinder>& binder) {
     if (binder == nullptr) {
         out << "<null>";
@@ -147,7 +167,7 @@
     status_t status = parcel->writeStrongBinder(token) ?:
         parcel->writeInt64(dispatchingTimeout.count()) ?:
         parcel->writeInt32(id) ?:
-        parcel->writeUtf8AsUtf16(name) ?:
+        writeUtf8AsUtf16WithTruncation(parcel, name, kMaxBytesName) ?:
         parcel->writeInt32(layoutParamsFlags.get()) ?:
         parcel->writeInt32(
                 static_cast<std::underlying_type_t<WindowInfo::Type>>(layoutParamsType)) ?:
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index e3f9a07..4da653f 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <gmock/gmock-matchers.h>
 #include <gtest/gtest.h>
 
 #include <binder/Binder.h>
@@ -116,6 +117,34 @@
     ASSERT_EQ(i.cloneLayerStackTransform, i2.cloneLayerStackTransform);
 }
 
+TEST(WindowInfo, ParcelNameTruncation) {
+    WindowInfo writeInfo;
+    // Construct a long string with a 3-byte UTF-8 character ('あ') to test truncation.
+    // 342 characters * 3 bytes/char = 1026 bytes, which is > 1024.
+    std::string_view c = "あ";
+    ASSERT_EQ(3u, c.size());
+    std::string longName;
+    longName.reserve(342 * 3);
+    for (int i = 0; i < 342; i++) {
+        longName.append(c);
+    }
+
+    ASSERT_GT(longName.length(), 1024u);
+    writeInfo.name = longName;
+
+    Parcel p;
+    ASSERT_EQ(OK, writeInfo.writeToParcel(&p));
+    p.setDataPosition(0);
+
+    WindowInfo readInfo;
+    ASSERT_EQ(OK, readInfo.readFromParcel(&p));
+
+    // The name should be truncated to the last valid character boundary at or before 1024 bytes.
+    // 1024 / 3 = 341.33. So, 341 characters should remain. 341 * 3 = 1023 bytes.
+    EXPECT_EQ(readInfo.name.length(), 1024u);
+    EXPECT_THAT(readInfo.name, testing::EndsWith("[TRUNC]"));
+}
+
 TEST(InputApplicationInfo, Parcelling) {
     InputApplicationInfo i;
     i.token = new BBinder();