mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 12:08:34 +00:00
Prevent nested SQL error handlers.
This commit is contained in:
committed by
Cody Henthorne
parent
1355a4a28d
commit
74619f6f8d
@@ -11,6 +11,7 @@ import org.signal.core.util.logging.Log
|
|||||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider
|
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,39 +19,53 @@ import java.util.concurrent.atomic.AtomicReference
|
|||||||
*/
|
*/
|
||||||
@Suppress("ClassName")
|
@Suppress("ClassName")
|
||||||
class SqlCipherErrorHandler(private val databaseName: String) : DatabaseErrorHandler {
|
class SqlCipherErrorHandler(private val databaseName: String) : DatabaseErrorHandler {
|
||||||
|
companion object {
|
||||||
|
private val TAG = Log.tag(SqlCipherErrorHandler::class.java)
|
||||||
|
|
||||||
|
private val errorHandlingInProgress = AtomicBoolean(false)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCorruption(db: SQLiteDatabase, message: String) {
|
override fun onCorruption(db: SQLiteDatabase, message: String) {
|
||||||
val result: DiagnosticResults = runDiagnostics(ApplicationDependencies.getApplication(), db)
|
if (errorHandlingInProgress.getAndSet(true)) {
|
||||||
var lines: List<String> = result.logs.split("\n")
|
Log.w(TAG, "Error handling already in progress, skipping.")
|
||||||
lines = listOf("Database '$databaseName' corrupted!", "[sqlite] $message", "Diagnostics results:") + lines
|
return
|
||||||
|
}
|
||||||
|
|
||||||
Log.e(TAG, "Database '$databaseName' corrupted!")
|
try {
|
||||||
Log.e(TAG, "[sqlite] $message")
|
val result: DiagnosticResults = runDiagnostics(ApplicationDependencies.getApplication(), db)
|
||||||
Log.e(TAG, "Diagnostic results:\n ${result.logs}")
|
var lines: List<String> = result.logs.split("\n")
|
||||||
|
lines = listOf("Database '$databaseName' corrupted!", "[sqlite] $message", "Diagnostics results:") + lines
|
||||||
|
|
||||||
if (result is DiagnosticResults.Success) {
|
Log.e(TAG, "Database '$databaseName' corrupted!")
|
||||||
if (result.pragma1Passes && result.pragma2Passes) {
|
Log.e(TAG, "[sqlite] $message")
|
||||||
var endCount = 0
|
Log.e(TAG, "Diagnostic results:\n ${result.logs}")
|
||||||
while (db.inTransaction() && endCount < 10) {
|
|
||||||
db.endTransaction()
|
if (result is DiagnosticResults.Success) {
|
||||||
endCount++
|
if (result.pragma1Passes && result.pragma2Passes) {
|
||||||
|
var endCount = 0
|
||||||
|
while (db.inTransaction() && endCount < 10) {
|
||||||
|
db.endTransaction()
|
||||||
|
endCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
attemptToClearFullTextSearchIndex(db)
|
||||||
|
throw DatabaseCorruptedError_BothChecksPass(lines)
|
||||||
|
} else if (!result.pragma1Passes && result.pragma2Passes) {
|
||||||
|
attemptToClearFullTextSearchIndex(db)
|
||||||
|
throw DatabaseCorruptedError_NormalCheckFailsCipherCheckPasses(lines)
|
||||||
|
} else if (result.pragma1Passes && !result.pragma2Passes) {
|
||||||
|
attemptToClearFullTextSearchIndex(db)
|
||||||
|
throw DatabaseCorruptedError_NormalCheckPassesCipherCheckFails(lines)
|
||||||
|
} else {
|
||||||
|
attemptToClearFullTextSearchIndex(db)
|
||||||
|
throw DatabaseCorruptedError_BothChecksFail(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
attemptToClearFullTextSearchIndex(db)
|
|
||||||
throw DatabaseCorruptedError_BothChecksPass(lines)
|
|
||||||
} else if (!result.pragma1Passes && result.pragma2Passes) {
|
|
||||||
attemptToClearFullTextSearchIndex(db)
|
|
||||||
throw DatabaseCorruptedError_NormalCheckFailsCipherCheckPasses(lines)
|
|
||||||
} else if (result.pragma1Passes && !result.pragma2Passes) {
|
|
||||||
attemptToClearFullTextSearchIndex(db)
|
|
||||||
throw DatabaseCorruptedError_NormalCheckPassesCipherCheckFails(lines)
|
|
||||||
} else {
|
} else {
|
||||||
attemptToClearFullTextSearchIndex(db)
|
attemptToClearFullTextSearchIndex(db)
|
||||||
throw DatabaseCorruptedError_BothChecksFail(lines)
|
throw DatabaseCorruptedError_FailedToRunChecks(lines)
|
||||||
}
|
}
|
||||||
} else {
|
} finally {
|
||||||
attemptToClearFullTextSearchIndex(db)
|
errorHandlingInProgress.set(false)
|
||||||
throw DatabaseCorruptedError_FailedToRunChecks(lines)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,8 +199,4 @@ class SqlCipherErrorHandler(private val databaseName: String) : DatabaseErrorHan
|
|||||||
private class DatabaseCorruptedError_NormalCheckFailsCipherCheckPasses constructor(lines: List<String>) : CustomTraceError(lines)
|
private class DatabaseCorruptedError_NormalCheckFailsCipherCheckPasses constructor(lines: List<String>) : CustomTraceError(lines)
|
||||||
private class DatabaseCorruptedError_NormalCheckPassesCipherCheckFails constructor(lines: List<String>) : CustomTraceError(lines)
|
private class DatabaseCorruptedError_NormalCheckPassesCipherCheckFails constructor(lines: List<String>) : CustomTraceError(lines)
|
||||||
private class DatabaseCorruptedError_FailedToRunChecks constructor(lines: List<String>) : CustomTraceError(lines)
|
private class DatabaseCorruptedError_FailedToRunChecks constructor(lines: List<String>) : CustomTraceError(lines)
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG = Log.tag(SqlCipherErrorHandler::class.java)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user