Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e79e6600 authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Report double-quoted string literals in SQL statements" into main

parents 56707cdd 6d11f4d1
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -236,15 +236,21 @@ public final class SQLiteDatabase extends SQLiteClosable {
     *
     * {@more} Note that the value of this flag is 0, so it is the default.
     */
    public static final int OPEN_READWRITE = 0x00000000;          // update native code if changing
    // LINT.IfChange
    public static final int OPEN_READWRITE = 0x00000000;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    /**
     * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
     * This is the only reliable way to open a database if the disk may be full.
     */
    public static final int OPEN_READONLY = 0x00000001;           // update native code if changing
    // LINT.IfChange
    public static final int OPEN_READONLY = 0x00000001;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    private static final int OPEN_READ_MASK = 0x00000001;         // update native code if changing
    // LINT.IfChange
    private static final int OPEN_READ_MASK = 0x00000001;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    /**
     * Open flag: Flag for {@link #openDatabase} to open the database without support for
@@ -254,13 +260,31 @@ public final class SQLiteDatabase extends SQLiteClosable {
     * You must be consistent when using this flag to use the setting the database was
     * created with.  If this is set, {@link #setLocale} will do nothing.
     */
    public static final int NO_LOCALIZED_COLLATORS = 0x00000010;  // update native code if changing
    // LINT.IfChange
    public static final int NO_LOCALIZED_COLLATORS = 0x00000010;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    /**
     * Open flag: Flag for {@link #openDatabase} to open a database, disallowing double-quoted
     * strings.
     *
     * This causes sqlite to reject SQL statements with double-quoted string literals.  String
     * literals must be enclosed in single quotes; double-quotes are reserved for identifiers like
     * column names.
     * See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted
     * @hide
     */
    // LINT.IfChange
    public static final int NO_DOUBLE_QUOTED_STRS = 0x00000020;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    /**
     * Open flag: Flag for {@link #openDatabase} to create the database file if it does not
     * already exist.
     */
    public static final int CREATE_IF_NECESSARY = 0x10000000;     // update native code if changing
    // LINT.IfChange
    public static final int CREATE_IF_NECESSARY = 0x10000000;
    // LINT.ThenChange(/core/jni/android_database_SQLiteConnection.cpp)

    /**
     * Open flag: Flag for {@link #openDatabase} to open the database file with
@@ -490,6 +514,9 @@ public final class SQLiteDatabase extends SQLiteClosable {
        if (SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled()) {
            mConfigurationLocked.openFlags |= ENABLE_LEGACY_COMPATIBILITY_WAL;
        }
        if (SQLiteDebug.NoPreloadHolder.NO_DOUBLE_QUOTED_STRS) {
            mConfigurationLocked.openFlags |= NO_DOUBLE_QUOTED_STRS;
        }
        mConfigurationLocked.journalMode = journalMode;
        mConfigurationLocked.syncMode = syncMode;
    }
@@ -3275,6 +3302,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
            OPEN_READONLY,
            CREATE_IF_NECESSARY,
            NO_LOCALIZED_COLLATORS,
            NO_DOUBLE_QUOTED_STRS,
            ENABLE_WRITE_AHEAD_LOGGING
    })
    @Retention(RetentionPolicy.SOURCE)
+9 −1
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@ public final class SQLiteDebug {
        public static final boolean DEBUG_SQL_TIME =
                Log.isLoggable("SQLiteTime", Log.VERBOSE);


        /**
         * True to enable database performance testing instrumentation.
         */
@@ -83,6 +82,15 @@ public final class SQLiteDebug {
         */
        public static final boolean DEBUG_LOG_DETAILED = Build.IS_DEBUGGABLE
                && SystemProperties.getBoolean("db.log.detailed", false);

        /**
         * Whether to accept double-quoted strings in SQL statements.  Double-quoted strings are a
         * syntax error but are accepted by sqlite in compatibility mode (the default).  If the
         * property is set to true, double-quoted strings will be treated by sqlite as a syntax
         * error.
         */
        public static final boolean NO_DOUBLE_QUOTED_STRS =
                SystemProperties.getBoolean("debug.sqlite.no_double_quoted_strs", false);
    }

    private SQLiteDebug() {
+15 −0
Original line number Diff line number Diff line
@@ -70,11 +70,14 @@ struct SQLiteConnection {
    // Open flags.
    // Must be kept in sync with the constants defined in SQLiteDatabase.java.
    enum {
        // LINT.IfChange
        OPEN_READWRITE          = 0x00000000,
        OPEN_READONLY           = 0x00000001,
        OPEN_READ_MASK          = 0x00000001,
        NO_LOCALIZED_COLLATORS  = 0x00000010,
        NO_DOUBLE_QUOTED_STRS   = 0x00000020,
        CREATE_IF_NECESSARY     = 0x10000000,
        // LINT.ThenChange(/core/java/android/database/sqlite/SQLiteDatabase.java)
    };

    sqlite3* const db;
@@ -156,6 +159,18 @@ static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFla
        }
    }

    // Disallow double-quoted string literals if the proper flag is set.
    if ((openFlags & SQLiteConnection::NO_DOUBLE_QUOTED_STRS) != 0) {
        void *setting = 0;
        int err = 0;
        if ((err = sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, setting)) != SQLITE_OK) {
            ALOGE("failed to configure SQLITE_DBCONFIG_DQS_DDL: %d", err);
        }
        if ((err = sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, setting)) != SQLITE_OK) {
            ALOGE("failed to configure SQLITE_DBCONFIG_DQS_DML: %d", err);
        }
    }

    // Check that the database is really read/write when that is what we asked for.
    if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) {
        throw_sqlite3_exception(env, db, "Could not open the database in read/write mode.");
+54 −0
Original line number Diff line number Diff line
@@ -538,4 +538,58 @@ public class SQLiteDatabaseTest {

        assertEquals(1, db.mConnection.size());
    }

    // Create and open the database, allowing or disallowing double-quoted strings.
    private void createDatabase(boolean noDoubleQuotedStrs) throws Exception {
        // The open-flags that do not change in this test.
        int flags = SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.OPEN_READWRITE;

        // The flag to be tested.
        int flagUnderTest = SQLiteDatabase.NO_DOUBLE_QUOTED_STRS;

        if (noDoubleQuotedStrs) {
            flags |= flagUnderTest;
        } else {
            flags &= ~flagUnderTest;
        }
        mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile.getPath(), null, flags, null);
    }

    /**
     * This test verifies that the NO_DOUBLE_QUOTED_STRS flag works as expected when opening a
     * database.  This does not test that the flag is initialized as expected from the system
     * properties.
     */
    @Test
    public void testNoDoubleQuotedStrings() throws Exception {
        closeAndDeleteDatabase();
        createDatabase(/* noDoubleQuotedStrs */ false);

        mDatabase.beginTransaction();
        try {
            mDatabase.execSQL("CREATE TABLE t1 (t text);");
            // Insert a value in double-quotes.  This is invalid but accepted.
            mDatabase.execSQL("INSERT INTO t1 (t) VALUES (\"foo\")");
        } finally {
            mDatabase.endTransaction();
        }

        closeAndDeleteDatabase();
        createDatabase(/* noDoubleQuotedStrs */ true);

        mDatabase.beginTransaction();
        try {
            mDatabase.execSQL("CREATE TABLE t1 (t text);");
            try {
                // Insert a value in double-quotes.  This is invalid and must throw.
                mDatabase.execSQL("INSERT INTO t1 (t) VALUES (\"foo\")");
                fail("expected an exception");
            } catch (SQLiteException e) {
                assertTrue(e.toString().contains("no such column"));
            }
        } finally {
            mDatabase.endTransaction();
        }
        closeAndDeleteDatabase();
    }
}