From bb385084d0d16a06319487e67ebbc1a0516e3751 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Fri, 7 Oct 2022 19:26:48 +0530 Subject: [PATCH] chore: re-roll Detekt baselines --- detekt-baselines/app.xml | 30 ++++++++++++++-------------- detekt-baselines/autofill-parser.xml | 17 ++++++++-------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/detekt-baselines/app.xml b/detekt-baselines/app.xml index cbbe4a17..5a5f9df9 100644 --- a/detekt-baselines/app.xml +++ b/detekt-baselines/app.xml @@ -1,6 +1,6 @@ - + - + ComplexCondition:AutofillFilterView.kt$AutofillFilterView$(list.isEmpty() && rvPasswordSwitcher.nextView.id == rvPasswordEmpty.id) || (list.isNotEmpty() && rvPasswordSwitcher.nextView.id == rvPassword.id) ComplexCondition:BaseGitActivity.kt$BaseGitActivity$(rootCause is org.eclipse.jgit.errors.TransportException || rootCause is org.eclipse.jgit.api.errors.TransportException || rootCause is org.eclipse.jgit.api.errors.InvalidRemoteException || (rootCause is UserAuthException && rootCause.message == "Exhausted available authentication methods")) @@ -8,32 +8,32 @@ ComplexCondition:PasswordCreationActivity.kt$PasswordCreationActivity$(!editing || (editing && suggestedName != file.nameWithoutExtension)) && file.exists() ComplexCondition:PasswordStore.kt$PasswordStore$(keyCode == KeyEvent.KEYCODE_SEARCH || keyCode == KeyEvent.KEYCODE_F && event.isCtrlPressed) && !searchItem.isActionViewExpanded ComplexMethod:AutofillFilterView.kt$AutofillFilterView$private fun bindUI() - ComplexMethod:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> + ComplexMethod:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> ComplexMethod:GitServerConfigActivity.kt$GitServerConfigActivity$override fun onCreate(savedInstanceState: Bundle?) ComplexMethod:Migrations.kt$private fun migrateToGitUrlBasedConfig(sharedPrefs: SharedPreferences, gitSettings: GitSettings) ComplexMethod:PasswordCreationActivity.kt$PasswordCreationActivity$override fun onCreate(savedInstanceState: Bundle?) ComplexMethod:PasswordCreationActivity.kt$PasswordCreationActivity$private fun encrypt() ComplexMethod:PasswordFragment.kt$PasswordFragment$private fun initializePasswordList() EmptyDoWhileBlock:PasswordDialog.kt$PasswordDialog${} - EmptyFunctionBlock:BasicBottomSheet.kt$BasicBottomSheet.<no name provided>${} - EmptyFunctionBlock:ItemCreationBottomSheet.kt$ItemCreationBottomSheet.<no name provided>${} - EmptyFunctionBlock:PasswordFragment.kt$PasswordFragment.<no name provided>.<no name provided>${} + EmptyFunctionBlock:BasicBottomSheet.kt$BasicBottomSheet.<no name provided>${} + EmptyFunctionBlock:ItemCreationBottomSheet.kt$ItemCreationBottomSheet.<no name provided>${} + EmptyFunctionBlock:PasswordFragment.kt$PasswordFragment.<no name provided>.<no name provided>${} ForbiddenComment:Api30AutofillResponseBuilder.kt$Api30AutofillResponseBuilder$// TODO: Support multi-step authentication flows in apps via FLAG_DELAY_SAVE ForbiddenComment:AutofillResponseBuilder.kt$AutofillResponseBuilder$// TODO: Support multi-step authentication flows in apps via FLAG_DELAY_SAVE ForbiddenComment:AutofillResponseBuilder.kt$AutofillResponseBuilder.Companion$// FIXME: We should clone the original dataset here and add the credentials to be filled ForbiddenComment:OreoAutofillService.kt$OreoAutofillService.Companion$// TODO: Provide a user-configurable denylist ImplicitDefaultLocale:PasswordExportService.kt$PasswordExportService$String.format("%tFT%<tRZ", Calendar.getInstance(TimeZone.getTimeZone("Z"))) LongMethod:AutofillFilterView.kt$AutofillFilterView$private fun bindUI() - LongMethod:CredentialFinder.kt$CredentialFinder$override fun askForPassword(cont: Continuation<String?>, isRetry: Boolean) + LongMethod:CredentialFinder.kt$CredentialFinder$override fun askForPassword(cont: Continuation<String?>, isRetry: Boolean) LongMethod:GeneralSettings.kt$GeneralSettings$override fun provideSettings(builder: PreferenceScreen.Builder) - LongMethod:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> + LongMethod:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> LongMethod:GitServerConfigActivity.kt$GitServerConfigActivity$override fun onCreate(savedInstanceState: Bundle?) LongMethod:GitServerConfigActivity.kt$GitServerConfigActivity$private fun cloneRepository() LongMethod:PasswordCreationActivity.kt$PasswordCreationActivity$override fun onCreate(savedInstanceState: Bundle?) LongMethod:PasswordCreationActivity.kt$PasswordCreationActivity$private fun encrypt() LongMethod:PasswordFragment.kt$PasswordFragment$private fun initializePasswordList() LongMethod:RepositorySettings.kt$RepositorySettings$override fun provideSettings(builder: PreferenceScreen.Builder) - LoopWithTooManyJumpStatements:AutofillMatcher.kt$AutofillMatcher.Companion$for ((key, value) in prefs.all) { if (!key.startsWith(PREFERENCE_PREFIX_MATCHES)) continue // We know that preferences starting with `PREFERENCE_PREFIX_MATCHES` were // created with `putStringSet`. @Suppress("UNCHECKED_CAST") val oldMatches = value as? Set<String> if (oldMatches == null) { logcat(WARN) { "Failed to read matches for $key" } continue } // Delete all matches for file locations that are going to be overwritten, then // transfer matches over to the files at their new locations. val newMatches = oldMatches .asSequence() .minus(deletePathList) .minus(oldNewPathMap.values) .map { match -> val newPath = oldNewPathMap[match] ?: return@map match logcat { "Updating match for $key: $match --> $newPath" } newPath } .toSet() if (newMatches != oldMatches) prefs.edit { putStringSet(key, newMatches) } } + LoopWithTooManyJumpStatements:AutofillMatcher.kt$AutofillMatcher.Companion$for ((key, value) in prefs.all) { if (!key.startsWith(PREFERENCE_PREFIX_MATCHES)) continue // We know that preferences starting with `PREFERENCE_PREFIX_MATCHES` were // created with `putStringSet`. @Suppress("UNCHECKED_CAST") val oldMatches = value as? Set<String> if (oldMatches == null) { logcat(WARN) { "Failed to read matches for $key" } continue } // Delete all matches for file locations that are going to be overwritten, then // transfer matches over to the files at their new locations. val newMatches = oldMatches .asSequence() .minus(deletePathList) .minus(oldNewPathMap.values) .map { match -> val newPath = oldNewPathMap[match] ?: return@map match logcat { "Updating match for $key: $match --> $newPath" } newPath } .toSet() if (newMatches != oldMatches) prefs.edit { putStringSet(key, newMatches) } } LoopWithTooManyJumpStatements:ErrorMessages.kt$ErrorMessages$while (cause.cause != null) { if (cause is GitException) break val nextCause = cause.cause!! if (nextCause is RemoteException) break cause = nextCause } MagicNumber:ClipboardService.kt$ClipboardService$1000 MagicNumber:ClipboardService.kt$ClipboardService$1000L @@ -62,9 +62,10 @@ MatchingDeclarationName:AutofillViewUtils.kt$DatasetMetadata MaxLineLength:BaseGitActivity.kt$BaseGitActivity$"The server does not support multiple Git operations per SSH session. Please try again, a slower fallback mode will be used." MaxLineLength:BaseGitActivity.kt$BaseGitActivity$"WARNING: The remote host key has changed. If this is expected, please go to Git server settings and clear the saved host key." + MaxLineLength:DecryptScreen.kt$ |otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30 MaxLineLength:UriTotpFinderTest.kt$UriTotpFinderTest.Companion$"otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA256&digits=12&period=25" - NestedBlockDepth:FieldItemAdapter.kt$FieldItemAdapter.FieldItemViewHolder$fun bind(fieldItem: FieldItem, showPassword: Boolean, copyTextToClipboard: (String?) -> Unit) - NestedBlockDepth:GitOperation.kt$GitOperation$suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> + NestedBlockDepth:FieldItemAdapter.kt$FieldItemAdapter.FieldItemViewHolder$fun bind(fieldItem: FieldItem, showPassword: Boolean, copyTextToClipboard: (String?) -> Unit) + NestedBlockDepth:GitOperation.kt$GitOperation$suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> NestedBlockDepth:PasswordExportService.kt$PasswordExportService$override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int ReturnCount:Api30AutofillResponseBuilder.kt$Api30AutofillResponseBuilder$private fun makeFillOtpFromSmsDataset( context: Context, imeSpec: InlinePresentationSpec? ): Dataset? ReturnCount:Api30AutofillResponseBuilder.kt$Api30AutofillResponseBuilder$private fun makeSaveInfo(): SaveInfo? @@ -72,10 +73,10 @@ ReturnCount:AutofillResponseBuilder.kt$AutofillResponseBuilder$private fun makeFillOtpFromSmsDataset(context: Context): Dataset? ReturnCount:AutofillResponseBuilder.kt$AutofillResponseBuilder$private fun makeSaveInfo(): SaveInfo? ReturnCount:AutofillViewUtils.kt$@SuppressLint("RestrictedApi") fun makeInlinePresentation( context: Context, imeSpec: InlinePresentationSpec, metadata: DatasetMetadata ): InlinePresentation? - ReturnCount:BaseGitActivity.kt$BaseGitActivity$suspend fun launchGitOperation(operation: GitOp): Result<Unit, Throwable> + ReturnCount:BaseGitActivity.kt$BaseGitActivity$suspend fun launchGitOperation(operation: GitOp): Result<Unit, Throwable> ReturnCount:ClipboardService.kt$ClipboardService$override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int ReturnCount:Extensions.kt$fun File.contains(other: File): Boolean - ReturnCount:GitOperation.kt$GitOperation$suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> + ReturnCount:GitOperation.kt$GitOperation$suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> ReturnCount:GitSettings.kt$GitSettings$fun updateConnectionSettingsIfValid( newAuthMode: AuthMode, newUrl: String, newBranch: String ): UpdateConnectionSettingsResult ReturnCount:OreoAutofillService.kt$OreoAutofillService$override fun onFillRequest( request: FillRequest, cancellationSignal: CancellationSignal, callback: FillCallback ) ReturnCount:OreoAutofillService.kt$OreoAutofillService$override fun onSaveRequest(request: SaveRequest, callback: SaveCallback) @@ -89,13 +90,12 @@ SpreadOperator:ErrorMessages.kt$GitException$(res, *fmt) SpreadOperator:ErrorMessages.kt$GitException.PullException$(res, *fmt) SpreadOperator:ErrorMessages.kt$GitException.PushException$(res, *fmt) - ThrowsCount:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> + ThrowsCount:GitCommandExecutor.kt$GitCommandExecutor$suspend fun execute(): Result<Unit, Throwable> ThrowsCount:SshKey.kt$SshKey$fun import(uri: Uri) TooManyFunctions:PasswordStore.kt$PasswordStore : BaseGitActivity TooManyFunctions:SshjConfig.kt$AbstractLogger : Logger TopLevelPropertyNaming:AutofillMatcher.kt$private const val PREFERENCES_AUTOFILL_APP_MATCHES = "oreo_autofill_app_matches" TopLevelPropertyNaming:AutofillMatcher.kt$private const val PREFERENCES_AUTOFILL_WEB_MATCHES = "oreo_autofill_web_matches" - TopLevelPropertyNaming:Extensions.kt$/** The default OpenPGP provider for the app */ const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain" TopLevelPropertyNaming:PasswordStore.kt$const val PASSWORD_FRAGMENT_TAG = "PasswordsList" TopLevelPropertyNaming:SshKey.kt$private const val ANDROIDX_SECURITY_KEYSET_PREF_NAME = "androidx_sshkey_keyset_prefs" TopLevelPropertyNaming:SshKey.kt$private const val KEYSTORE_ALIAS = "sshkey" diff --git a/detekt-baselines/autofill-parser.xml b/detekt-baselines/autofill-parser.xml index 83f3316f..aea58ad6 100644 --- a/detekt-baselines/autofill-parser.xml +++ b/detekt-baselines/autofill-parser.xml @@ -1,31 +1,30 @@ - + - + - ComplexMethod:AutofillStrategyDsl.kt$AutofillRule$fun match( allPassword: List<FormField>, allUsername: List<FormField>, allOtp: List<FormField>, singleOriginMode: Boolean, isManualRequest: Boolean ): AutofillScenario<FormField>? + ComplexMethod:AutofillStrategyDsl.kt$AutofillRule$fun match( allPassword: List<FormField>, allUsername: List<FormField>, allOtp: List<FormField>, singleOriginMode: Boolean, isManualRequest: Boolean ): AutofillScenario<FormField>? DestructuringDeclarationWithTooManyEntries:AutofillStrategyDsl.kt$AutofillRule$(type, matcher, optional, matchHidden) ForbiddenComment:AutofillFormParser.kt$AutofillFormParser$// TODO: Support WebViews in apps via Digital Asset Links ForbiddenComment:AutofillStrategy.kt$// TODO: Introduce a custom fill/generate/update flow for this scenario ForbiddenComment:FormField.kt$FormField$// TODO: Revisit this decision in the future - LongMethod:ByteArray.kt$@Suppress("ComplexMethod", "NestedBlockDepth") internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): String? + LongMethod:ByteArray.kt$@Suppress("ComplexMethod", "NestedBlockDepth") internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): String? LoopWithTooManyJumpStatements:AutofillStrategyDsl.kt$PairOfFieldsMatcher$for ((i, tieBreaker) in tieBreakers.withIndex()) { val new = current.filter { tieBreaker(it, alreadyMatched) } if (new.isEmpty()) { logcat { "Tie breaker #${i + 1}: Didn't match any pair of fields; skipping" } continue } // and return if the available options have been narrowed to a single field. if (new.size == 1) { logcat { "Tie breaker #${i + 1}: Success" } current = new break } logcat { "Tie breaker #${i + 1}: Matched ${new.size} pairs of fields; continuing" } current = new } LoopWithTooManyJumpStatements:AutofillStrategyDsl.kt$SingleFieldMatcher$for ((i, tieBreaker) in tieBreakers.withIndex()) { // Successively filter matched fields via tie breakers... val new = current.filter { tieBreaker(it, alreadyMatched) } // skipping those tie breakers that are not satisfied for any remaining field... if (new.isEmpty()) { logcat { "Tie breaker #${i + 1}: Didn't match any field; skipping" } continue } // and return if the available options have been narrowed to a single field. if (new.size == 1) { logcat { "Tie breaker #${i + 1}: Success" } current = new break } logcat { "Tie breaker #${i + 1}: Matched ${new.size} fields; continuing" } current = new } LoopWithTooManyJumpStatements:ByteArray.kt$while (true) { val byte0 = if (expectDot) { expectDot = false '.'.code.toByte() } else { labels[currentLabelIndex][currentLabelByteIndex] and BITMASK } val byte1 = this[start + publicSuffixByteIndex] and BITMASK // Compare the bytes. Note that the file stores UTF-8 encoded bytes, so we must compare // the // unsigned bytes. compareResult = (byte0.toUByte() - byte1.toUByte()).toInt() if (compareResult != 0) { break } publicSuffixByteIndex++ currentLabelByteIndex++ if (publicSuffixByteIndex == publicSuffixLength) { break } if (labels[currentLabelIndex].size == currentLabelByteIndex) { // We've exhausted our current label. Either there are more labels to compare, in // which // case we expect a dot as the next character. Otherwise, we've checked all our // labels. if (currentLabelIndex == labels.size - 1) { break } else { currentLabelIndex++ currentLabelByteIndex = -1 expectDot = true } } } MagicNumber:AutofillHelper.kt$FixedSaveCallback$29 MagicNumber:AutofillScenario.kt$4 MagicNumber:AutofillScenario.kt$5 - MaxLineLength:FeatureAndTrustDetection.kt$/* In order to add a new browser, do the following: 1. Obtain the .apk from a trusted source. For example, download it from the Play Store on your phone and use adb pull to get it onto your computer. We will assume that it is called browser.apk. 2. Run aapt dump badging browser.apk | grep package: | grep -Eo " name='[a-zA-Z0-9_\.]*" | cut -c8- to obtain the package name (actually, the application ID) of the app in the .apk. 3. Run apksigner verify --print-certs browser.apk | grep "#1 certificate SHA-256" | grep -Eo "[a-f0-9]{64}" | tr -d '\n' | xxd -r -p | base64 to calculate the hash of browser.apk's first signing certificate. Note: This will only work if the apk has a single signing certificate. Apps with multiple signers are very rare, so there is probably no need to add them. Refer to computeCertificatesHash to learn how the hash would be computed in this case. 4. Verify the package name and the hash, for example by asking other people to repeat the steps above. 5. Add an entry with the browser apps's package name and the hash to TRUSTED_BROWSER_CERTIFICATE_HASH. 6. Optionally, try adding the browser's package name to BROWSERS_WITH_SAVE_SUPPORT and check whether a save request to Password Store is triggered when you submit a registration form. 7. Optionally, try adding the browser's package name to BROWSERS_WITH_MULTI_ORIGIN_SUPPORT and check whether it correctly distinguishes web origins even if iframes are present on the page. You can use https://fabianhenneke.github.io/Android-Password-Store/ as a test form. */ MaxLineLength:FormField.kt$FormField$"\"$hint\", \"$fieldId\"${if (isFocused) ", focused" else ""}${if (isVisible) ", visible" else ""}, $webOrigin, $htmlAttributesDebug, $autofillHints" ReturnCount:AutofillFormParser.kt$AutofillFormParser$private fun determineFormOrigin(context: Context): FormOrigin? ReturnCount:AutofillFormParser.kt$AutofillFormParser$private fun webOriginToFormOrigin(context: Context, origin: String): FormOrigin? ReturnCount:AutofillFormParser.kt$FormOrigin.Companion$public fun fromBundle(bundle: Bundle): FormOrigin? - ReturnCount:AutofillStrategyDsl.kt$AutofillRule$fun match( allPassword: List<FormField>, allUsername: List<FormField>, allOtp: List<FormField>, singleOriginMode: Boolean, isManualRequest: Boolean ): AutofillScenario<FormField>? + ReturnCount:AutofillStrategyDsl.kt$AutofillRule$fun match( allPassword: List<FormField>, allUsername: List<FormField>, allOtp: List<FormField>, singleOriginMode: Boolean, isManualRequest: Boolean ): AutofillScenario<FormField>? ReturnCount:PublicSuffixListCache.kt$private fun getSuffixPlusUpToOne(domain: String, suffix: String): String? - ReturnCount:PublicSuffixListData.kt$PublicSuffixListData$private fun findExceptionMatch(labels: List<ByteArray>, wildcardMatch: String?): String? - ReturnCount:PublicSuffixListData.kt$PublicSuffixListData$private fun findMatchingRule(domainLabels: List<String>): List<String> + ReturnCount:PublicSuffixListData.kt$PublicSuffixListData$private fun findExceptionMatch(labels: List<ByteArray>, wildcardMatch: String?): String? + ReturnCount:PublicSuffixListData.kt$PublicSuffixListData$private fun findMatchingRule(domainLabels: List<String>): List<String> TooGenericExceptionCaught:AutofillScenario.kt$AutofillScenario.Companion$e: Throwable TopLevelPropertyNaming:PublicSuffixListLoader.kt$private const val PUBLIC_SUFFIX_LIST_FILE = "publicsuffixes" - UnusedPrivateMember:AutofillStrategy.kt$private inline fun <T> Pair<T, T>.none(predicate: T.() -> Boolean) + UnusedPrivateMember:AutofillStrategy.kt$private inline fun <T> Pair<T, T>.none(predicate: T.() -> Boolean) UnusedPrivateMember:FormField.kt$FormField$// Ignored for now, see excludedByHints private val excludedByAutocompleteHint = htmlAutocomplete == "off"