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

Commit 9463f297 authored by Vasu Nori's avatar Vasu Nori
Browse files

sometimes database lock is not held before compiling a statement

indirectly uncovered by bug:2631971

Change-Id: I71059b6b62bc21612fc98689aefd4534884c8e7c
parent edd904fd
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -78,20 +78,13 @@ import android.util.Log;
     *  existing compiled SQL program already around
     */
    private void compile(String sql, boolean forceCompilation) {
        if (!mDatabase.isOpen()) {
            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
        }
        mDatabase.verifyLockOwner();
        // Only compile if we don't have a valid statement already or the caller has
        // explicitly requested a recompile.
        if (forceCompilation) {
            mDatabase.lock();
            try {
            // Note that the native_compile() takes care of destroying any previously
            // existing programs before it compiles.
            native_compile(sql);
            } finally {
                mDatabase.unlock();
            }
        }
    }

+24 −13
Original line number Diff line number Diff line
@@ -275,7 +275,10 @@ public class SQLiteDatabase extends SQLiteClosable {
                // if it needs to be removed to accommodate a new entry,
                //     close {@link SQLiteCompiledSql} represented by this entry, if not in use
                //     and then let it be removed from the Map.
                synchronized(mCompiledQueries) { // probably not necessary, but can't hurt
                // when this is called, the caller must be trying to add a just-compiled stmt
                // to cache; i.e., caller should already have acquired database lock AND
                // the lock on mCompiledQueries. do as assert of these two 2 facts.
                verifyLockOwner();
                if (this.size() <= mMaxSqlCacheSize) {
                    // cache is not full. nothing needs to be removed
                    return false;
@@ -289,7 +292,6 @@ public class SQLiteDatabase extends SQLiteClosable {
                // return true, so that this entry is removed automatically by the caller.
                return true;
            }
            }
        };
    /**
     * absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}
@@ -1979,6 +1981,15 @@ public class SQLiteDatabase extends SQLiteClosable {
        }
    }

    /* package */ void verifyLockOwner() {
        if (!isOpen()) {
            throw new IllegalStateException("database " + getPath() + " already closed");
        }
        if (!isDbLockedByCurrentThread() && mLockingEnabled) {
            throw new IllegalStateException("Don't have database lock!");
        }
    }

    /*
     * ============================================================================
     *
+4 −1
Original line number Diff line number Diff line
@@ -39,9 +39,11 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {

    public Cursor query(CursorFactory factory, String[] selectionArgs) {
        // Compile the query
        SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
        SQLiteQuery query = null;

        try {
            mDatabase.lock();
            query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
            // Arg binding
            int numArgs = selectionArgs == null ? 0 : selectionArgs.length;
            for (int i = 0; i < numArgs; i++) {
@@ -61,6 +63,7 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
        } finally {
            // Make sure this object is cleaned up if something happens
            if (query != null) query.close();
            mDatabase.unlock();
        }
    }