diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/database/DatabaseUtils.java | 29 | ||||
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabase.java | 4 |
2 files changed, 33 insertions, 0 deletions
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 34cc856e000f..9b809b86eae9 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -43,6 +43,7 @@ import com.android.internal.util.ArrayUtils; import java.io.FileNotFoundException; import java.io.PrintStream; import java.text.Collator; +import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -308,6 +309,34 @@ public class DatabaseUtils { } /** + * Make a deep copy of the given argument list, ensuring that the returned + * value is completely isolated from any changes to the original arguments. + * + * @hide + */ + public static @Nullable Object[] deepCopyOf(@Nullable Object[] args) { + if (args == null) return null; + + final Object[] res = new Object[args.length]; + for (int i = 0; i < args.length; i++) { + final Object arg = args[i]; + + if ((arg == null) || (arg instanceof Number) || (arg instanceof String)) { + // When the argument is immutable, we can copy by reference + res[i] = arg; + } else if (arg instanceof byte[]) { + // Need to deep copy blobs + final byte[] castArg = (byte[]) arg; + res[i] = Arrays.copyOf(castArg, castArg.length); + } else { + // Convert everything else to string, making it immutable + res[i] = String.valueOf(arg); + } + } + return res; + } + + /** * Returns data type of the given object's value. *<p> * Returned values are diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 24ac1527779e..7c4692c9e3af 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -1066,6 +1066,10 @@ public final class SQLiteDatabase extends SQLiteClosable { throws SQLException { Objects.requireNonNull(sql); + // Copy arguments to ensure that the caller doesn't accidentally change + // the values used by future connections + bindArgs = DatabaseUtils.deepCopyOf(bindArgs); + synchronized (mLock) { throwIfNotOpenLocked(); |
