Loading core/java/android/os/Parcel.java +23 −4 Original line number Diff line number Diff line Loading @@ -614,7 +614,7 @@ public final class Parcel { int startPos; for (int i=0; i<N; i++) { if (DEBUG_ARRAY_MAP) startPos = dataPosition(); writeValue(val.keyAt(i)); writeString(val.keyAt(i)); writeValue(val.valueAt(i)); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Write #" + i + " " + (dataPosition()-startPos) + " bytes: key=0x" Loading @@ -623,6 +623,13 @@ public final class Parcel { } } /** * @hide For testing only. */ public void writeArrayMap(ArrayMap<String, Object> val) { writeArrayMapInternal(val); } /** * Flatten a Bundle into the parcel at the current dataPosition(), * growing dataCapacity() if needed. Loading Loading @@ -2321,7 +2328,7 @@ public final class Parcel { int startPos; while (N > 0) { if (DEBUG_ARRAY_MAP) startPos = dataPosition(); Object key = readValue(loader); String key = readString(); Object value = readValue(loader); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read #" + (N-1) + " " + (dataPosition()-startPos) + " bytes: key=0x" Loading @@ -2329,6 +2336,7 @@ public final class Parcel { outVal.append(key, value); N--; } outVal.validate(); } /* package */ void readArrayMapSafelyInternal(ArrayMap outVal, int N, Loading @@ -2339,7 +2347,7 @@ public final class Parcel { Log.d(TAG, "Reading safely " + N + " ArrayMap entries", here); } while (N > 0) { Object key = readValue(loader); String key = readString(); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read safe #" + (N-1) + ": key=0x" + (key != null ? key.hashCode() : 0) + " " + key); Object value = readValue(loader); Loading @@ -2348,6 +2356,17 @@ public final class Parcel { } } /** * @hide For testing only. */ public void readArrayMap(ArrayMap outVal, ClassLoader loader) { final int N = readInt(); if (N < 0) { return; } readArrayMapInternal(outVal, N, loader); } private void readListInternal(List outVal, int N, ClassLoader loader) { while (N > 0) { Loading core/java/android/util/ArrayMap.java +38 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,44 @@ public final class ArrayMap<K, V> implements Map<K, V> { mArray[index+1] = value; } /** * The use of the {@link #append} function can result in invalid array maps, in particular * an array map where the same key appears multiple times. This function verifies that * the array map is valid, throwing IllegalArgumentException if a problem is found. The * main use for this method is validating an array map after unpacking from an IPC, to * protect against malicious callers. * @hide */ public void validate() { final int N = mSize; if (N <= 1) { // There can't be dups. return; } int basehash = mHashes[0]; int basei = 0; for (int i=1; i<N; i++) { int hash = mHashes[i]; if (hash != basehash) { basehash = hash; basei = i; continue; } // We are in a run of entries with the same hash code. Go backwards through // the array to see if any keys are the same. final Object cur = mArray[i<<1]; for (int j=i-1; j>=basei; j--) { final Object prev = mArray[j<<1]; if (cur == prev) { throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur); } if (cur != null && prev != null && cur.equals(prev)) { throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur); } } } } /** * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var> * @param array The array whose contents are to be retrieved. Loading Loading
core/java/android/os/Parcel.java +23 −4 Original line number Diff line number Diff line Loading @@ -614,7 +614,7 @@ public final class Parcel { int startPos; for (int i=0; i<N; i++) { if (DEBUG_ARRAY_MAP) startPos = dataPosition(); writeValue(val.keyAt(i)); writeString(val.keyAt(i)); writeValue(val.valueAt(i)); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Write #" + i + " " + (dataPosition()-startPos) + " bytes: key=0x" Loading @@ -623,6 +623,13 @@ public final class Parcel { } } /** * @hide For testing only. */ public void writeArrayMap(ArrayMap<String, Object> val) { writeArrayMapInternal(val); } /** * Flatten a Bundle into the parcel at the current dataPosition(), * growing dataCapacity() if needed. Loading Loading @@ -2321,7 +2328,7 @@ public final class Parcel { int startPos; while (N > 0) { if (DEBUG_ARRAY_MAP) startPos = dataPosition(); Object key = readValue(loader); String key = readString(); Object value = readValue(loader); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read #" + (N-1) + " " + (dataPosition()-startPos) + " bytes: key=0x" Loading @@ -2329,6 +2336,7 @@ public final class Parcel { outVal.append(key, value); N--; } outVal.validate(); } /* package */ void readArrayMapSafelyInternal(ArrayMap outVal, int N, Loading @@ -2339,7 +2347,7 @@ public final class Parcel { Log.d(TAG, "Reading safely " + N + " ArrayMap entries", here); } while (N > 0) { Object key = readValue(loader); String key = readString(); if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read safe #" + (N-1) + ": key=0x" + (key != null ? key.hashCode() : 0) + " " + key); Object value = readValue(loader); Loading @@ -2348,6 +2356,17 @@ public final class Parcel { } } /** * @hide For testing only. */ public void readArrayMap(ArrayMap outVal, ClassLoader loader) { final int N = readInt(); if (N < 0) { return; } readArrayMapInternal(outVal, N, loader); } private void readListInternal(List outVal, int N, ClassLoader loader) { while (N > 0) { Loading
core/java/android/util/ArrayMap.java +38 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,44 @@ public final class ArrayMap<K, V> implements Map<K, V> { mArray[index+1] = value; } /** * The use of the {@link #append} function can result in invalid array maps, in particular * an array map where the same key appears multiple times. This function verifies that * the array map is valid, throwing IllegalArgumentException if a problem is found. The * main use for this method is validating an array map after unpacking from an IPC, to * protect against malicious callers. * @hide */ public void validate() { final int N = mSize; if (N <= 1) { // There can't be dups. return; } int basehash = mHashes[0]; int basei = 0; for (int i=1; i<N; i++) { int hash = mHashes[i]; if (hash != basehash) { basehash = hash; basei = i; continue; } // We are in a run of entries with the same hash code. Go backwards through // the array to see if any keys are the same. final Object cur = mArray[i<<1]; for (int j=i-1; j>=basei; j--) { final Object prev = mArray[j<<1]; if (cur == prev) { throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur); } if (cur != null && prev != null && cur.equals(prev)) { throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur); } } } } /** * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var> * @param array The array whose contents are to be retrieved. Loading