From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yuri Lin <yurilin@google.com>
Date: Mon, 29 Aug 2022 17:40:14 -0400
Subject: [PATCH] Trim any long string inputs that come in to AutomaticZenRule

This change both prevents any rules from being unable to be written to disk and also avoids risk of running out of memory while handling all the zen rules.

Bug: 242703460
Bug: 242703505
Bug: 242703780
Bug: 242704043
Bug: 243794204
Test: cts AutomaticZenRuleTest; atest android.app.AutomaticZenRuleTest; manually confirmed each exploit example either saves the rule successfully with a truncated string (in the case of name & conditionId) or may fail to save the rule at all (if the owner/configactivity is invalid). Additionally ran the memory-exhausting PoC without device crashes.

Change-Id: I110172a43f28528dd274b3b346eb29c3796ff2c6
Merged-In: I110172a43f28528dd274b3b346eb29c3796ff2c6
(cherry picked from commit de172ba0d434c940be9e2aad8685719731ab7da2)
(cherry picked from commit c4b2c877ec28e2473104d9fcdcf321bd81da881b)
Merged-In: I110172a43f28528dd274b3b346eb29c3796ff2c6
---
 core/java/android/app/AutomaticZenRule.java | 52 ++++++++++++++++++---
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index cd4ace669b6c..c152b6b438ef 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -36,6 +36,13 @@ public final class AutomaticZenRule implements Parcelable {
     private ComponentName owner;
     private long creationTime;
 
+    /**
+     * The maximum string length for any string contained in this automatic zen rule. This pertains
+     * both to fields in the rule itself (such as its name) and items with sub-fields.
+     * @hide
+     */
+    public static final int MAX_STRING_LENGTH = 1000;
+
     /**
      * Creates an automatic zen rule.
      *
@@ -50,9 +57,9 @@ public final class AutomaticZenRule implements Parcelable {
      */
     public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
             int interruptionFilter, boolean enabled) {
-        this.name = name;
-        this.owner = owner;
-        this.conditionId = conditionId;
+        this.name = getTrimmedString(name);
+        this.owner = getTrimmedComponentName(owner);
+        this.conditionId = getTrimmedUri(conditionId);
         this.interruptionFilter = interruptionFilter;
         this.enabled = enabled;
     }
@@ -70,11 +77,11 @@ public final class AutomaticZenRule implements Parcelable {
     public AutomaticZenRule(Parcel source) {
         enabled = source.readInt() == 1;
         if (source.readInt() == 1) {
-            name = source.readString();
+            name = getTrimmedString(source.readString());
         }
         interruptionFilter = source.readInt();
         conditionId = source.readParcelable(null);
-        owner = source.readParcelable(null);
+        owner = getTrimmedComponentName(source.readParcelable(null));
         creationTime = source.readLong();
     }
 
@@ -124,7 +131,7 @@ public final class AutomaticZenRule implements Parcelable {
      * Sets the representation of the state that causes this rule to become active.
      */
     public void setConditionId(Uri conditionId) {
-        this.conditionId = conditionId;
+        this.conditionId = getTrimmedUri(conditionId);
     }
 
     /**
@@ -139,7 +146,7 @@ public final class AutomaticZenRule implements Parcelable {
      * Sets the name of this rule.
      */
     public void setName(String name) {
-        this.name = name;
+        this.name = getTrimmedString(name);
     }
 
     /**
@@ -210,4 +217,35 @@ public final class AutomaticZenRule implements Parcelable {
             return new AutomaticZenRule[size];
         }
     };
+
+    /**
+     * If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
+     * return a trimmed version that truncates each of the package and class name at the max length.
+     */
+    private static ComponentName getTrimmedComponentName(ComponentName cn) {
+        if (cn == null) return null;
+        return new ComponentName(getTrimmedString(cn.getPackageName()),
+                getTrimmedString(cn.getClassName()));
+    }
+
+    /**
+     * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
+     */
+    private static String getTrimmedString(String input) {
+        if (input != null && input.length() > MAX_STRING_LENGTH) {
+            return input.substring(0, MAX_STRING_LENGTH);
+        }
+        return input;
+    }
+
+    /**
+     * Returns a truncated copy of the Uri by trimming the string representation to the maximum
+     * string length.
+     */
+    private static Uri getTrimmedUri(Uri input) {
+        if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
+            return Uri.parse(getTrimmedString(input.toString()));
+        }
+        return input;
+    }
 }
