diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-12-23 21:03:17 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-12-23 21:03:17 +0000 |
commit | 70030aaec339f7c331f80b907a2d147591840d6f (patch) | |
tree | e8366071f295dd1e40522931118cb82ea23e5910 | |
parent | 49583e3d84ad6904b09ea42b76fdcf891c31c79b (diff) | |
parent | d4d523686429f0bbe2484d8d24652f671c53f310 (diff) | |
download | cts-70030aaec339f7c331f80b907a2d147591840d6f.tar.gz |
Merge changes I6b247672,Ie8ea452b,I9ef52453 into pie-cts-dev
* changes:
RESTRICT AUTOMERGE Strict SQLiteQueryBuilder needs to be stricter.
DO NOT MERGE fixes a security vulnerability in slice provider
DO NOT MERGE CTS: Test column name with spaces
3 files changed, 265 insertions, 13 deletions
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java index 97b0b8f5475..4479a5d393c 100644 --- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java +++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java @@ -18,6 +18,7 @@ package android.database.sqlite.cts; import android.content.Context; +import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteCursor; import android.database.sqlite.SQLiteCursorDriver; @@ -28,12 +29,15 @@ import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.test.AndroidTestCase; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Semaphore; public class SQLiteQueryBuilderTest extends AndroidTestCase { private SQLiteDatabase mDatabase; + private SQLiteQueryBuilder mStrictBuilder; + private final String TEST_TABLE_NAME = "test"; private final String EMPLOYEE_TABLE_NAME = "employee"; private static final String DATABASE_FILE = "database_test.db"; @@ -45,6 +49,9 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { getContext().deleteDatabase(DATABASE_FILE); mDatabase = getContext().openOrCreateDatabase(DATABASE_FILE, Context.MODE_PRIVATE, null); assertNotNull(mDatabase); + + createEmployeeTable(); + createStrictQueryBuilder(); } @Override @@ -202,8 +209,6 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { } public void testQuery() { - createEmployeeTable(); - SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder(); sqliteQueryBuilder.setTables("Employee"); Cursor cursor = sqliteQueryBuilder.query(mDatabase, @@ -276,8 +281,6 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { } public void testCancelableQuery_WhenNotCanceled_ReturnsResultSet() { - createEmployeeTable(); - CancellationSignal cancellationSignal = new CancellationSignal(); SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder(); sqliteQueryBuilder.setTables("Employee"); @@ -289,8 +292,6 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { } public void testCancelableQuery_WhenCanceledBeforeQuery_ThrowsImmediately() { - createEmployeeTable(); - CancellationSignal cancellationSignal = new CancellationSignal(); SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder(); sqliteQueryBuilder.setTables("Employee"); @@ -307,8 +308,6 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { } public void testCancelableQuery_WhenCanceledAfterQuery_ThrowsWhenExecuted() { - createEmployeeTable(); - CancellationSignal cancellationSignal = new CancellationSignal(); SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder(); sqliteQueryBuilder.setTables("Employee"); @@ -327,8 +326,6 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { } public void testCancelableQuery_WhenCanceledDueToContention_StopsWaitingAndThrows() { - createEmployeeTable(); - for (int i = 0; i < 5; i++) { final CancellationSignal cancellationSignal = new CancellationSignal(); final Semaphore barrier1 = new Semaphore(0); @@ -460,6 +457,152 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { fail("Could not prove that the query actually canceled midway during execution."); } + public void testStrictQuery() throws Exception { + final SQLiteQueryBuilder qb = mStrictBuilder; + + // Should normally only be able to see one row + try (Cursor c = qb.query(mDatabase, null, null, null, null, null, null)) { + assertEquals(1, c.getCount()); + } + + // Trying sneaky queries should fail; even if they somehow succeed, we + // shouldn't get to see any other data. + try (Cursor c = qb.query(mDatabase, null, "1=1", null, null, null, null)) { + assertEquals(1, c.getCount()); + } catch (Exception tolerated) { + } + try (Cursor c = qb.query(mDatabase, null, "1=1 --", null, null, null, null)) { + assertEquals(1, c.getCount()); + } catch (Exception tolerated) { + } + try (Cursor c = qb.query(mDatabase, null, "1=1) OR (1=1", null, null, null, null)) { + assertEquals(1, c.getCount()); + } catch (Exception tolerated) { + } + try (Cursor c = qb.query(mDatabase, null, "1=1)) OR ((1=1", null, null, null, null)) { + assertEquals(1, c.getCount()); + } catch (Exception tolerated) { + } + } + + private static final String[] COLUMNS_VALID = new String[] { + "_id", + }; + + private static final String[] COLUMNS_INVALID = new String[] { + "salary", + "MAX(salary)", + "undefined", + "(secret_column IN secret_table)", + "(SELECT secret_column FROM secret_table)", + }; + + public void testStrictQueryProjection() throws Exception { + for (String column : COLUMNS_VALID) { + assertStrictQueryValid( + new String[] { column }, null, null, null, null, null, null); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + new String[] { column }, null, null, null, null, null, null); + } + } + + public void testStrictQueryWhere() throws Exception { + for (String column : COLUMNS_VALID) { + assertStrictQueryValid( + null, column + ">0", null, null, null, null, null); + assertStrictQueryValid( + null, "_id>" + column, null, null, null, null, null); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + null, column + ">0", null, null, null, null, null); + assertStrictQueryInvalid( + null, "_id>" + column, null, null, null, null, null); + } + } + + public void testStrictQueryGroupBy() { + for (String column : COLUMNS_VALID) { + assertStrictQueryValid( + null, null, null, column, null, null, null); + assertStrictQueryValid( + null, null, null, "_id," + column, null, null, null); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + null, null, null, column, null, null, null); + assertStrictQueryInvalid( + null, null, null, "_id," + column, null, null, null); + } + } + + public void testStrictQueryHaving() { + for (String column : COLUMNS_VALID) { + assertStrictQueryValid( + null, null, null, "_id", column, null, null); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + null, null, null, "_id", column, null, null); + } + } + + public void testStrictQueryOrderBy() { + for (String column : COLUMNS_VALID) { + assertStrictQueryValid( + null, null, null, null, null, column, null); + assertStrictQueryValid( + null, null, null, null, null, column + " ASC", null); + assertStrictQueryValid( + null, null, null, null, null, "_id COLLATE NOCASE ASC," + column, null); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + null, null, null, null, null, column, null); + assertStrictQueryInvalid( + null, null, null, null, null, column + " ASC", null); + assertStrictQueryInvalid( + null, null, null, null, null, "_id COLLATE NOCASE ASC," + column, null); + } + } + + public void testStrictQueryLimit() { + assertStrictQueryValid( + null, null, null, null, null, null, "32"); + assertStrictQueryValid( + null, null, null, null, null, null, "0,32"); + assertStrictQueryValid( + null, null, null, null, null, null, "32 OFFSET 0"); + + for (String column : COLUMNS_VALID) { + assertStrictQueryInvalid( + null, null, null, null, null, null, column); + } + for (String column : COLUMNS_INVALID) { + assertStrictQueryInvalid( + null, null, null, null, null, null, column); + } + } + + private void assertStrictQueryValid(String[] projectionIn, String selection, + String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) { + try (Cursor c = mStrictBuilder.query(mDatabase, projectionIn, selection, selectionArgs, + groupBy, having, sortOrder, limit, null)) { + } + } + + private void assertStrictQueryInvalid(String[] projectionIn, String selection, + String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) { + try (Cursor c = mStrictBuilder.query(mDatabase, projectionIn, selection, selectionArgs, + groupBy, having, sortOrder, limit, null)) { + fail(Arrays.asList(projectionIn, selection, selectionArgs, + groupBy, having, sortOrder, limit).toString()); + } catch (Exception expected) { + } + } + private void createEmployeeTable() { mDatabase.execSQL("CREATE TABLE employee (_id INTEGER PRIMARY KEY, " + "name TEXT, month INTEGER, salary INTEGER);"); @@ -476,4 +619,17 @@ public class SQLiteQueryBuilderTest extends AndroidTestCase { mDatabase.execSQL("INSERT INTO employee (name, month, salary) " + "VALUES ('Jim', '3', '3500');"); } + + private void createStrictQueryBuilder() { + mStrictBuilder = new SQLiteQueryBuilder(); + mStrictBuilder.setTables("employee"); + mStrictBuilder.setStrict(true); + mStrictBuilder.appendWhere("month=2"); + + final Map<String, String> projectionMap = new HashMap<>(); + projectionMap.put("_id", "_id"); + projectionMap.put("name", "name"); + projectionMap.put("month", "month"); + mStrictBuilder.setProjectionMap(projectionMap); + } } diff --git a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java new file mode 100644 index 00000000000..2a2e8e46b1a --- /dev/null +++ b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.slice.cts; + +import android.app.slice.Slice; +import android.app.slice.SliceSpec; +import android.content.ContentResolver; +import android.net.Uri; +import android.os.Bundle; + +import androidx.test.rule.ActivityTestRule; +import androidx.test.runner.AndroidJUnit4; + +import com.google.android.collect.Lists; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class SliceProviderTest { + + private static final String VALID_AUTHORITY = "android.slice.cts"; + private static final String SUSPICIOUS_AUTHORITY = "com.suspicious.www"; + private static final String ACTION_BLUETOOTH = "/action/bluetooth"; + private static final String VALID_BASE_URI_STRING = "content://" + VALID_AUTHORITY; + private static final String VALID_ACTION_URI_STRING = + "content://" + VALID_AUTHORITY + ACTION_BLUETOOTH; + private static final String SHADY_ACTION_URI_STRING = + "content://" + SUSPICIOUS_AUTHORITY + ACTION_BLUETOOTH; + + @Rule + public ActivityTestRule<Launcher> mLauncherActivityTestRule = new ActivityTestRule<>(Launcher.class); + + private Uri validBaseUri = Uri.parse(VALID_BASE_URI_STRING); + private Uri validActionUri = Uri.parse(VALID_ACTION_URI_STRING); + private Uri shadyActionUri = Uri.parse(SHADY_ACTION_URI_STRING); + + private ContentResolver mContentResolver; + + @Before + public void setUp() { + mContentResolver = mLauncherActivityTestRule.getActivity().getContentResolver(); + } + + @Test + public void testCallSliceUri_ValidAuthority() { + doQuery(validActionUri); + } + + @Test(expected = SecurityException.class) + public void testCallSliceUri_ShadyAuthority() { + doQuery(shadyActionUri); + } + + private Slice doQuery(Uri actionUri) { + Bundle extras = new Bundle(); + extras.putParcelable("slice_uri", actionUri); + extras.putParcelableArrayList("supported_specs", Lists.newArrayList( + new SliceSpec("androidx.slice.LIST", 1), + new SliceSpec("androidx.app.slice.BASIC", 1), + new SliceSpec("androidx.slice.BASIC", 1), + new SliceSpec("androidx.app.slice.LIST", 1) + )); + Bundle result = mContentResolver.call( + validBaseUri, + SliceProvider.METHOD_SLICE, + null, + extras + ); + return result.getParcelable(SliceProvider.EXTRA_SLICE); + } + +} diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java index 27c388a9153..6314ec59209 100644 --- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java +++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java @@ -105,7 +105,8 @@ public class TvContractTest extends AndroidTestCase { private static final String WHITE_SPACES = " \r \n \t \f "; private static final String PARAM_CANONICAL_GENRE = "canonical_genre"; - private static final String NON_EXISTING_COLUMN_NAME = "non_existing_column"; + private static final String[] NON_EXISTING_COLUMN_NAMES = + {"non_existing_column", "another non-existing column --"}; private String mInputId; private ContentResolver mContentResolver; @@ -336,15 +337,20 @@ public class TvContractTest extends AndroidTestCase { private void verifyNonExistingColumn(Uri channelUri, long channelId) { String[] projection = { Channels._ID, - NON_EXISTING_COLUMN_NAME + NON_EXISTING_COLUMN_NAMES[0], + NON_EXISTING_COLUMN_NAMES[1] }; try (Cursor cursor = mContentResolver.query(channelUri, projection, null, null, null)) { assertNotNull(cursor); assertEquals(cursor.getCount(), 1); assertTrue(cursor.moveToNext()); assertEquals(channelId, cursor.getLong(0)); + assertEquals(NON_EXISTING_COLUMN_NAMES[0], cursor.getColumnName(1)); assertNull(cursor.getString(1)); assertEquals(0, cursor.getInt(1)); + assertEquals(NON_EXISTING_COLUMN_NAMES[1], cursor.getColumnName(2)); + assertNull(cursor.getString(2)); + assertEquals(0, cursor.getInt(2)); } } @@ -533,7 +539,8 @@ public class TvContractTest extends AndroidTestCase { return; } ContentValues values = createDummyChannelValues(mInputId, false); - values.put(NON_EXISTING_COLUMN_NAME, "dummy value"); + values.put(NON_EXISTING_COLUMN_NAMES[0], "dummy value 0"); + values.put(NON_EXISTING_COLUMN_NAMES[1], "dummy value 1"); Uri rowUri = mContentResolver.insert(mChannelsUri, values); long channelId = ContentUris.parseId(rowUri); Uri channelUri = TvContract.buildChannelUri(channelId); |