Add error messages for unexpected state to ease debugging

This commit is contained in:
Torsten Grote 2019-12-18 15:50:34 -03:00
parent bb9d498ea8
commit 177e714001
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
10 changed files with 30 additions and 20 deletions

View file

@ -87,7 +87,9 @@ class CryptoImpl(
override fun encryptSegment(outputStream: OutputStream, cleartext: ByteArray) { override fun encryptSegment(outputStream: OutputStream, cleartext: ByteArray) {
val cipher = cipherFactory.createEncryptionCipher() val cipher = cipherFactory.createEncryptionCipher()
check(cipher.getOutputSize(cleartext.size) <= MAX_SEGMENT_LENGTH) check(cipher.getOutputSize(cleartext.size) <= MAX_SEGMENT_LENGTH) {
"Cipher's output size ${cipher.getOutputSize(cleartext.size)} is larger than maximum segment length ($MAX_SEGMENT_LENGTH)"
}
val encrypted = cipher.doFinal(cleartext) val encrypted = cipher.doFinal(cleartext)
val segmentHeader = SegmentHeader(encrypted.size.toShort(), cipher.iv) val segmentHeader = SegmentHeader(encrypted.size.toShort(), cipher.iv)

View file

@ -15,8 +15,12 @@ data class VersionHeader(
internal val key: String? = null // ?? bytes internal val key: String? = null // ?? bytes
) { ) {
init { init {
check(packageName.length <= MAX_PACKAGE_LENGTH_SIZE) check(packageName.length <= MAX_PACKAGE_LENGTH_SIZE) {
key?.let { check(key.length <= MAX_KEY_LENGTH_SIZE) } "Package $packageName has name longer than $MAX_PACKAGE_LENGTH_SIZE"
}
key?.let {
check(key.length <= MAX_KEY_LENGTH_SIZE) { "Key $key is longer than $MAX_KEY_LENGTH_SIZE" }
}
} }
} }
@ -34,6 +38,8 @@ class SegmentHeader(
internal val nonce: ByteArray // 12 bytes internal val nonce: ByteArray // 12 bytes
) { ) {
init { init {
check(nonce.size == IV_SIZE) check(nonce.size == IV_SIZE) {
"Nonce size of ${nonce.size} is not the expected IV size of $IV_SIZE"
}
} }
} }

View file

@ -62,7 +62,7 @@ class RestoreViewModel(app: Application) : RequireProvisioningViewModel(app), Re
override fun onRestoreSetClicked(set: RestoreSet) { override fun onRestoreSetClicked(set: RestoreSet) {
val session = this.session val session = this.session
check(session != null) check(session != null) { "Restore set clicked, but no session available" }
session.restoreAll(set.token, observer, monitor) session.restoreAll(set.token, observer, monitor)
mChosenRestoreSet.value = set mChosenRestoreSet.value = set

View file

@ -35,7 +35,7 @@ class SettingsManager(context: Context) {
fun getStorage(): Storage? { fun getStorage(): Storage? {
val uriStr = prefs.getString(PREF_KEY_STORAGE_URI, null) ?: return null val uriStr = prefs.getString(PREF_KEY_STORAGE_URI, null) ?: return null
val uri = Uri.parse(uriStr) val uri = Uri.parse(uriStr)
val name = prefs.getString(PREF_KEY_STORAGE_NAME, null) ?: throw IllegalStateException() val name = prefs.getString(PREF_KEY_STORAGE_NAME, null) ?: throw IllegalStateException("no storage name")
val isUsb = prefs.getBoolean(PREF_KEY_STORAGE_IS_USB, false) val isUsb = prefs.getBoolean(PREF_KEY_STORAGE_IS_USB, false)
return Storage(uri, name, isUsb) return Storage(uri, name, isUsb)
} }

View file

@ -33,7 +33,7 @@ class ConfigurableBackupTransportService : Service() {
} }
override fun onBind(intent: Intent): IBinder { override fun onBind(intent: Intent): IBinder {
val transport = this.transport ?: throw IllegalStateException() val transport = this.transport ?: throw IllegalStateException("no transport in onBind()")
return transport.binder.apply { return transport.binder.apply {
Log.d(TAG, "Transport bound.") Log.d(TAG, "Transport bound.")
} }

View file

@ -178,11 +178,11 @@ class BackupCoordinator(
fun finishBackup(): Int = when { fun finishBackup(): Int = when {
kv.hasState() -> { kv.hasState() -> {
check(!full.hasState()) check(!full.hasState()) { "K/V backup has state, but full backup has dangling state as well" }
kv.finishBackup() kv.finishBackup()
} }
full.hasState() -> { full.hasState() -> {
check(!kv.hasState()) check(!kv.hasState()) { "Full backup has state, but K/V backup has dangling state as well" }
full.finishBackup() full.finishBackup()
} }
calledInitialize || calledClearBackupData -> { calledInitialize || calledClearBackupData -> {
@ -190,7 +190,7 @@ class BackupCoordinator(
calledClearBackupData = false calledClearBackupData = false
TRANSPORT_OK TRANSPORT_OK
} }
else -> throw IllegalStateException() else -> throw IllegalStateException("Unexpected state in finishBackup()")
} }
@Throws(IOException::class) @Throws(IOException::class)

View file

@ -77,7 +77,7 @@ internal class FullRestore(
*/ */
fun getNextFullRestoreDataChunk(socket: ParcelFileDescriptor): Int { fun getNextFullRestoreDataChunk(socket: ParcelFileDescriptor): Int {
Log.i(TAG, "Get next full restore data chunk.") Log.i(TAG, "Get next full restore data chunk.")
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
val packageName = state.packageInfo.packageName val packageName = state.packageInfo.packageName
if (state.inputStream == null) { if (state.inputStream == null) {
@ -103,9 +103,9 @@ internal class FullRestore(
} }
private fun readInputStream(socket: ParcelFileDescriptor): Int = socket.use { fileDescriptor -> private fun readInputStream(socket: ParcelFileDescriptor): Int = socket.use { fileDescriptor ->
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
val packageName = state.packageInfo.packageName val packageName = state.packageInfo.packageName
val inputStream = state.inputStream ?: throw IllegalStateException() val inputStream = state.inputStream ?: throw IllegalStateException("no stream")
val outputStream = outputFactory.getOutputStream(fileDescriptor) val outputStream = outputFactory.getOutputStream(fileDescriptor)
try { try {
@ -144,7 +144,7 @@ internal class FullRestore(
* with no further attempts to restore app data. * with no further attempts to restore app data.
*/ */
fun abortFullRestore(): Int { fun abortFullRestore(): Int {
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
Log.i(TAG, "Abort full restore of ${state.packageInfo.packageName}!") Log.i(TAG, "Abort full restore of ${state.packageInfo.packageName}!")
resetState() resetState()
@ -156,7 +156,7 @@ internal class FullRestore(
* freeing any resources and connections used during the restore process. * freeing any resources and connections used during the restore process.
*/ */
fun finishRestore() { fun finishRestore() {
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
Log.i(TAG, "Finish restore of ${state.packageInfo.packageName}!") Log.i(TAG, "Finish restore of ${state.packageInfo.packageName}!")
resetState() resetState()

View file

@ -55,7 +55,7 @@ internal class KVRestore(
* or [TRANSPORT_ERROR] (an error occurred, the restore should be aborted and rescheduled). * or [TRANSPORT_ERROR] (an error occurred, the restore should be aborted and rescheduled).
*/ */
fun getRestoreData(data: ParcelFileDescriptor): Int { fun getRestoreData(data: ParcelFileDescriptor): Int {
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
// The restore set is the concatenation of the individual record blobs, // The restore set is the concatenation of the individual record blobs,
// each of which is a file in the package's directory. // each of which is a file in the package's directory.

View file

@ -43,7 +43,9 @@ internal class RestoreCoordinator(
val restoreSets = ArrayList<RestoreSet>() val restoreSets = ArrayList<RestoreSet>()
for (encryptedMetadata in availableBackups) { for (encryptedMetadata in availableBackups) {
if (encryptedMetadata.error) continue if (encryptedMetadata.error) continue
check(encryptedMetadata.inputStream != null) // if there's no error, there must be a stream check(encryptedMetadata.inputStream != null) {
"No error when getting encrypted metadata, but stream is still missing."
}
try { try {
val metadata = metadataReader.readMetadata(encryptedMetadata.inputStream, encryptedMetadata.token) val metadata = metadataReader.readMetadata(encryptedMetadata.inputStream, encryptedMetadata.token)
val set = RestoreSet(metadata.deviceName, metadata.deviceName, metadata.token) val set = RestoreSet(metadata.deviceName, metadata.deviceName, metadata.token)
@ -93,7 +95,7 @@ internal class RestoreCoordinator(
* or [TRANSPORT_ERROR] (an error occurred, the restore should be aborted and rescheduled). * or [TRANSPORT_ERROR] (an error occurred, the restore should be aborted and rescheduled).
*/ */
fun startRestore(token: Long, packages: Array<out PackageInfo>): Int { fun startRestore(token: Long, packages: Array<out PackageInfo>): Int {
check(state == null) check(state == null) { "Started new restore with existing state" }
Log.i(TAG, "Start restore with ${packages.map { info -> info.packageName }}") Log.i(TAG, "Start restore with ${packages.map { info -> info.packageName }}")
state = RestoreCoordinatorState(token, packages.iterator()) state = RestoreCoordinatorState(token, packages.iterator())
return TRANSPORT_OK return TRANSPORT_OK
@ -127,7 +129,7 @@ internal class RestoreCoordinator(
*/ */
fun nextRestorePackage(): RestoreDescription? { fun nextRestorePackage(): RestoreDescription? {
Log.i(TAG, "Next restore package!") Log.i(TAG, "Next restore package!")
val state = this.state ?: throw IllegalStateException() val state = this.state ?: throw IllegalStateException("no state")
if (!state.packages.hasNext()) return NO_MORE_PACKAGES if (!state.packages.hasNext()) return NO_MORE_PACKAGES
val packageInfo = state.packages.next() val packageInfo = state.packages.next()

View file

@ -87,7 +87,7 @@ internal abstract class StorageViewModel(private val app: Application) : Android
*/ */
protected fun saveStorage(uri: Uri): Boolean { protected fun saveStorage(uri: Uri): Boolean {
// store backup storage location in settings // store backup storage location in settings
val root = storageRoot ?: throw IllegalStateException() val root = storageRoot ?: throw IllegalStateException("no storage root")
val name = if (root.isInternal()) { val name = if (root.isInternal()) {
"${root.title} (${app.getString(R.string.settings_backup_location_internal)})" "${root.title} (${app.getString(R.string.settings_backup_location_internal)})"
} else { } else {