Crash on android SQLCipher Update


#1

I have updated the android SQLCipher library from 2.x to 3.3 and I execute the relevant update code:

if (!isMigrated)
{
SQLiteDatabaseHook hook = new SQLiteDatabaseHook()
{
public void preKey(final SQLiteDatabase database)
{
}

            public void postKey(final SQLiteDatabase database) 
            {
                int value = QueryHelper.singleIntegerValueFromQuery(database, "PRAGMA cipher_migrate");
                status[0] = Integer.valueOf(value).equals(Integer.valueOf(0));
            }
        };
            
        File destinationFile = context.getDatabasePath(fileName);
        SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(destinationFile, password , null, hook);

        if (database != null) 
        {
            database.close();
        }
    
        prefs.edit().putBoolean(DATABASE_UPDATE, status[0]).commit();
        
        return status[0];  
    }
    else
    {
        return true;
    }

The method “singleIntegerValueFromQuery” is:

protected static int singleIntegerValueFromQuery(final SQLiteDatabase database, final String query)
{
Cursor cursor = database.rawQuery(query, new String[] {});
int value = 0;

         if (cursor != null) 
         {
             cursor.moveToFirst();
             value = cursor.getInt(0);
             cursor.close();
         }
         return value;
     }

As far as I have tested, it works properly. However it leads to crash exactly on the update to some users with diverse android devices. The line of the crash is:

SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(destinationFile, password , null, hook);

The error message is:

net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SourceFile:2096)
at net.sqlcipher.database.SQLiteDatabase.(SourceFile:1962)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SourceFile:881)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SourceFile:874)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SourceFile:909)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SourceFile:905)

What is wrong in the above update and what is a potential resaon of the crash? How should it be executed to avoid the crash?


#2

Hi @AppsDev

On situations where you receive an error with the call to native_setLocale(…), what was the result of the PRAGMA cipher_migrate; command? Are you able to pull the database off a device that crashes and inspect the database file using the SQLCipher command line tool?


#3

No, I do not have this opportunity, since I have not any of those devices. On each device I have tested it, it works properly.
From the stacktrace I deduce that the crash happens exactly on the update (due to the fact that the exeption is thrown on the method “openOrCreateDatabe”) and I find it quite strange. It does not merely fail on the update, which would make the database inaccessible, but it crashes instead. Is there anything to be done additionally to avoid the crash?


#4

Hello @AppsDev

It would be recommended to log the return value from PRAGMA cipher_migrate; to understand what result code is returned during the migration process. The SQLiteDatabaseHook is run before the the locale is set, which is the location at which your exception is triggered. Also, there were some changes recently introduced within the master branch of SQLCipher for Android which may help identify the issue you are seeing. You would need to build from source as a new binary is not available at this time containing those changes.