From 851ec49de73913547a51476e9c80cccfd7c15572 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 12 Oct 2016 17:20:07 -0700 Subject: [PATCH] Fix issue #32125907: Intent.replaceUnsafeExtras() corrupts original bundle We now recursively generate new Bundle objects if we need to do any stripping. Change-Id: I4ca7896a0771c25264591ae7c79df85816d630d4 --- core/java/android/content/Intent.java | 2 +- core/java/android/os/Bundle.java | 34 +++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index cf6880a981f48..c6aaa48ddad09 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -6573,7 +6573,7 @@ public class Intent implements Parcelable, Cloneable { */ public void removeUnsafeExtras() { if (mExtras != null) { - mExtras.filterValues(); + mExtras = mExtras.filterValues(); } } diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index ca64a965af0b5..62fa7721702ee 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -309,25 +309,49 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * Filter values in Bundle to only basic types. * @hide */ - public void filterValues() { + public Bundle filterValues() { unparcel(); + Bundle bundle = this; if (mMap != null) { - for (int i = mMap.size() - 1; i >= 0; i--) { - Object value = mMap.valueAt(i); + ArrayMap map = mMap; + for (int i = map.size() - 1; i >= 0; i--) { + Object value = map.valueAt(i); if (PersistableBundle.isValidType(value)) { continue; } if (value instanceof Bundle) { - ((Bundle)value).filterValues(); + Bundle newBundle = ((Bundle)value).filterValues(); + if (newBundle != value) { + if (map == mMap) { + // The filter had to generate a new bundle, but we have not yet + // created a new one here. Do that now. + bundle = new Bundle(this); + // Note the ArrayMap<> constructor is guaranteed to generate + // a new object with items in the same order as the original. + map = bundle.mMap; + } + // Replace this current entry with the new child bundle. + map.setValueAt(i, newBundle); + } + continue; } if (value.getClass().getName().startsWith("android.")) { continue; } - mMap.removeAt(i); + if (map == mMap) { + // This is the first time we have had to remove something, that means we + // need to switch to a new Bundle. + bundle = new Bundle(this); + // Note the ArrayMap<> constructor is guaranteed to generate + // a new object with items in the same order as the original. + map = bundle.mMap; + } + map.removeAt(i); } } mFlags |= FLAG_HAS_FDS_KNOWN; mFlags &= ~FLAG_HAS_FDS; + return bundle; } /**