Merge "Escape the LIKE clause for list()" into main
diff --git a/core/java/com/android/internal/net/ConnectivityBlobStore.java b/core/java/com/android/internal/net/ConnectivityBlobStore.java
index 1b18485..f8eb5be 100644
--- a/core/java/com/android/internal/net/ConnectivityBlobStore.java
+++ b/core/java/com/android/internal/net/ConnectivityBlobStore.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.content.ContentValues;
 import android.database.Cursor;
+import android.database.DatabaseUtils;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Binder;
@@ -153,8 +154,11 @@
         final List<String> names = new ArrayList<String>();
         try (Cursor cursor = mDb.query(TABLENAME,
                 new String[] {"name"} /* columns */,
-                "owner=? AND name LIKE ?" /* selection */,
-                new String[] {Integer.toString(ownerUid), prefix + "%"} /* selectionArgs */,
+                "owner=? AND name LIKE ? ESCAPE '\\'" /* selection */,
+                new String[] {
+                        Integer.toString(ownerUid),
+                        DatabaseUtils.escapeForLike(prefix) + "%"
+                } /* selectionArgs */,
                 null /* groupBy */,
                 null /* having */,
                 "name ASC" /* orderBy */)) {
diff --git a/core/tests/coretests/src/com/android/internal/net/ConnectivityBlobStoreTest.java b/core/tests/coretests/src/com/android/internal/net/ConnectivityBlobStoreTest.java
index 68545cf..ad4ccc9 100644
--- a/core/tests/coretests/src/com/android/internal/net/ConnectivityBlobStoreTest.java
+++ b/core/tests/coretests/src/com/android/internal/net/ConnectivityBlobStoreTest.java
@@ -153,4 +153,41 @@
         final String[] actual = connectivityBlobStore.list(TEST_NAME /* prefix */);
         assertArrayEquals(expected, actual);
     }
+
+    @Test
+    public void testList_underscoreInPrefix() throws Exception {
+        final String prefix = TEST_NAME + "_";
+        final String[] unsortedNames = new String[] {
+                prefix + "000",
+                TEST_NAME + "123",
+        };
+        // The '_' in the prefix should not be treated as a wildcard so the only match is "000".
+        final String[] expected = new String[] {"000"};
+        final ConnectivityBlobStore connectivityBlobStore = createConnectivityBlobStore();
+
+        for (int i = 0; i < unsortedNames.length; i++) {
+            assertTrue(connectivityBlobStore.put(unsortedNames[i], TEST_BLOB));
+        }
+        final String[] actual = connectivityBlobStore.list(prefix);
+        assertArrayEquals(expected, actual);
+    }
+
+    @Test
+    public void testList_percentInPrefix() throws Exception {
+        final String prefix = "%" + TEST_NAME + "%";
+        final String[] unsortedNames = new String[] {
+                TEST_NAME + "12345",
+                prefix + "0",
+                "abc" + TEST_NAME + "987",
+        };
+        // The '%' in the prefix should not be treated as a wildcard so the only match is "0".
+        final String[] expected = new String[] {"0"};
+        final ConnectivityBlobStore connectivityBlobStore = createConnectivityBlobStore();
+
+        for (int i = 0; i < unsortedNames.length; i++) {
+            assertTrue(connectivityBlobStore.put(unsortedNames[i], TEST_BLOB));
+        }
+        final String[] actual = connectivityBlobStore.list(prefix);
+        assertArrayEquals(expected, actual);
+    }
 }