Skip to content

Commit c2bc050

Browse files
author
Chris Brody
committed
Native SQLiteDatabase check read/write database and specific exception messages
Use throw_sqlite3_exception_errcode() if sqlite3_open_v2() fails Needed to help diagnose exceptions in sqlcipher#139 & sqlcipher#161 Some credit to https://github.com/android/platform_frameworks_base/blob/master/core/jni/android_database_SQLiteConnection.cpp
1 parent 7e704f0 commit c2bc050

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

jni/net_sqlcipher_database_SQLiteDatabase.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@
2525

2626
#include <sqlite3.h>
2727
#include <sqlite3_android.h>
28-
#include <string.h>
28+
2929
#include <utils/Log.h>
3030
#include <utils/threads.h>
3131
#include <utils/List.h>
3232
#include <utils/Errors.h>
33+
3334
#include <ctype.h>
3435

3536
#include <stdio.h>
3637
#include <sys/types.h>
37-
#include <string.h>
3838
#include <sys/ioctl.h>
3939

4040
#include <unicode/utypes.h>
@@ -277,7 +277,13 @@ void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags)
277277
err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL);
278278
if (err != SQLITE_OK) {
279279
LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags);
280-
throw_sqlite3_exception(env, handle);
280+
throw_sqlite3_exception_errcode(env, err, "Could not open database");
281+
goto done;
282+
}
283+
284+
// Check that the database is really read/write when that is what we asked for.
285+
if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(handle, NULL)) {
286+
throw_sqlite3_exception(env, handle, "Could not open the database in read/write mode.");
281287
goto done;
282288
}
283289

@@ -290,7 +296,7 @@ void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags)
290296
err = sqlite3_busy_timeout(handle, 1000 /* ms */);
291297
if (err != SQLITE_OK) {
292298
LOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8);
293-
throw_sqlite3_exception(env, handle);
299+
throw_sqlite3_exception(env, handle, "Could not set busy timeout");
294300
goto done;
295301
}
296302

@@ -299,7 +305,7 @@ void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags)
299305
err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL);
300306
if (err != SQLITE_OK) {
301307
LOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8);
302-
throw_sqlite3_exception(env, handle);
308+
throw_sqlite3_exception(env, handle, "sqlite_prepare_v2(handle, \"pragma integrity_check(1);\") failed");
303309
goto done;
304310
}
305311

@@ -321,7 +327,7 @@ void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags)
321327

322328
err = register_android_functions(handle, UTF16_STORAGE);
323329
if (err) {
324-
throw_sqlite3_exception(env, handle);
330+
throw_sqlite3_exception(env, handle, "Could not register Android SQL functions.");
325331
goto done;
326332
}
327333

@@ -396,8 +402,8 @@ static void dbclose(JNIEnv* env, jobject object)
396402
env->SetIntField(object, offset_db_handle, 0);
397403
} else {
398404
// This can happen if sub-objects aren't closed first. Make sure the caller knows.
399-
throw_sqlite3_exception(env, handle);
400405
LOGE("sqlite3_close(%p) failed: %d\n", handle, result);
406+
throw_sqlite3_exception(env, handle, "sqlite3_close() failed");
401407
}
402408
}
403409
}
@@ -498,7 +504,7 @@ static void native_setLocale(JNIEnv* env, jobject object, jstring localeString,
498504
err = sqlite3_exec(handle, createSql, NULL, NULL, NULL);
499505
if (err != SQLITE_OK) {
500506
LOGE("CREATE TABLE " ANDROID_TABLE " failed\n");
501-
throw_sqlite3_exception(env, handle);
507+
throw_sqlite3_exception(env, handle, "create locale table failed");
502508
goto done;
503509
}
504510
}
@@ -508,7 +514,7 @@ static void native_setLocale(JNIEnv* env, jobject object, jstring localeString,
508514
err = sqlite3_get_table(handle, selectSql, &meta, &rowCount, &colCount, NULL);
509515
if (err != SQLITE_OK) {
510516
LOGE("SELECT locale FROM " ANDROID_TABLE " failed\n");
511-
throw_sqlite3_exception(env, handle);
517+
throw_sqlite3_exception(env, handle, "select locale failed");
512518
goto done;
513519
}
514520

@@ -525,66 +531,66 @@ static void native_setLocale(JNIEnv* env, jobject object, jstring localeString,
525531
// read-only database, so we're going to have to put up with whatever we got
526532
// For registering new index. Not for modifing the read-only database.
527533
err = register_localized_collators(handle, locale8, UTF16_STORAGE);
528-
if (err != SQLITE_OK) throw_sqlite3_exception(env, handle);
534+
if (err != SQLITE_OK) throw_sqlite3_exception(env, handle, "register localized collators failed");
529535
goto done;
530536
}
531537

532538
// need to update android_metadata and indexes atomically, so use a transaction...
533539
err = sqlite3_exec(handle, "BEGIN TRANSACTION", NULL, NULL, NULL);
534540
if (err != SQLITE_OK) {
535541
LOGE("BEGIN TRANSACTION failed setting locale\n");
536-
throw_sqlite3_exception(env, handle);
542+
throw_sqlite3_exception(env, handle, "BEGIN TRANSACTION failed setting locale");
537543
goto done;
538544
}
539545

540546
err = register_localized_collators(handle, locale8, UTF16_STORAGE);
541547
if (err != SQLITE_OK) {
542548
LOGE("register_localized_collators() failed setting locale\n");
543-
throw_sqlite3_exception(env, handle);
549+
throw_sqlite3_exception(env, handle, "register_localized_collators() failed setting locale");
544550
goto rollback;
545551
}
546552

547553
err = sqlite3_exec(handle, "DELETE FROM " ANDROID_TABLE, NULL, NULL, NULL);
548554
if (err != SQLITE_OK) {
549555
LOGE("DELETE failed setting locale\n");
550-
throw_sqlite3_exception(env, handle);
556+
throw_sqlite3_exception(env, handle, "DELETE failed setting locale");
551557
goto rollback;
552558
}
553559

554560
static const char *sql = "INSERT INTO " ANDROID_TABLE " (locale) VALUES(?);";
555561
err = sqlite3_prepare_v2(handle, sql, -1, &stmt, NULL);
556562
if (err != SQLITE_OK) {
557563
LOGE("sqlite3_prepare_v2(\"%s\") failed\n", sql);
558-
throw_sqlite3_exception(env, handle);
564+
throw_sqlite3_exception(env, handle, "sqlite3_prepare_v2() failed setting locale");
559565
goto rollback;
560566
}
561567

562568
err = sqlite3_bind_text(stmt, 1, locale8, -1, SQLITE_TRANSIENT);
563569
if (err != SQLITE_OK) {
564570
LOGE("sqlite3_bind_text() failed setting locale\n");
565-
throw_sqlite3_exception(env, handle);
571+
throw_sqlite3_exception(env, handle, "sqlite3_bind_text() failed setting locale");
566572
goto rollback;
567573
}
568574

569575
err = sqlite3_step(stmt);
570576
if (err != SQLITE_OK && err != SQLITE_DONE) {
571577
LOGE("sqlite3_step(\"%s\") failed setting locale\n", sql);
572-
throw_sqlite3_exception(env, handle);
578+
throw_sqlite3_exception(env, handle, "sqlite3_step() failed setting locale");
573579
goto rollback;
574580
}
575581

576582
err = sqlite3_exec(handle, "REINDEX LOCALIZED", NULL, NULL, NULL);
577583
if (err != SQLITE_OK) {
578584
LOGE("REINDEX LOCALIZED failed\n");
579-
throw_sqlite3_exception(env, handle);
585+
throw_sqlite3_exception(env, handle, "REINDEX LOCALIZED failed");
580586
goto rollback;
581587
}
582588

583589
// all done, yay!
584590
err = sqlite3_exec(handle, "COMMIT TRANSACTION", NULL, NULL, NULL);
585591
if (err != SQLITE_OK) {
586592
LOGE("COMMIT TRANSACTION failed setting locale\n");
587-
throw_sqlite3_exception(env, handle);
593+
throw_sqlite3_exception(env, handle, "COMMIT TRANSACTION failed setting locale");
588594
goto done;
589595
}
590596

0 commit comments

Comments
 (0)