From 87bf68d4ef867571acf61fbd473325b89474c194 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sun, 2 Feb 2025 22:58:21 +0100 Subject: [PATCH] Migrate WebViewsFileAccessCheck to kotlin-analysis-api Co-authored-by: Marharyta Nedzelska Co-authored-by: Evgeny Mandrikov --- .../kotlin/checks/WebViewsFileAccessCheck.kt | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt index 110c9e53d..5b2f5ec6a 100644 --- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt +++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt @@ -16,29 +16,23 @@ */ package org.sonarsource.kotlin.checks +import org.jetbrains.kotlin.analysis.api.resolution.KaCallableMemberCall +import org.jetbrains.kotlin.analysis.api.resolution.KaFunctionCall +import org.jetbrains.kotlin.analysis.api.resolution.successfulCallOrNull import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtPsiUtil -import org.jetbrains.kotlin.resolve.calls.util.getFirstArgumentExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.sonar.check.Rule import org.sonarsource.kotlin.api.checks.CallAbstractCheck import org.sonarsource.kotlin.api.checks.FunMatcher +import org.sonarsource.kotlin.api.checks.getFirstArgumentExpression import org.sonarsource.kotlin.api.checks.predictRuntimeBooleanValue -import org.sonarsource.kotlin.api.checks.setterMatches import org.sonarsource.kotlin.api.frontend.KotlinFileContext +import org.sonarsource.kotlin.api.visiting.withKaSession private const val MESSAGE = "Make sure that enabling file access is safe here." -private val PROPERTY_NAMES = arrayOf( - "allowFileAccess", - "allowFileAccessFromFileURLs", - "allowContentAccess", - "allowUniversalAccessFromFileURLs", -).asSequence() - private val ANDROID_FILE_ACCESS_MATCHER = FunMatcher(definingSupertype = "android.webkit.WebSettings") { withNames( "setAllowFileAccess", @@ -49,27 +43,27 @@ private val ANDROID_FILE_ACCESS_MATCHER = FunMatcher(definingSupertype = "androi withArguments("kotlin.Boolean") } -@org.sonarsource.kotlin.api.frontend.K1only @Rule(key = "S6363") class WebViewsFileAccessCheck : CallAbstractCheck() { override val functionsToVisit = listOf(ANDROID_FILE_ACCESS_MATCHER) - override fun visitFunctionCall(callExpression: KtCallExpression, resolvedCall: ResolvedCall<*>, kotlinFileContext: KotlinFileContext) { + override fun visitFunctionCall(callExpression: KtCallExpression, resolvedCall: KaFunctionCall<*>, kotlinFileContext: KotlinFileContext) { checkFileAccessArgument(kotlinFileContext, resolvedCall.getFirstArgumentExpression()) } - override fun visitBinaryExpression(expression: KtBinaryExpression, ctx: KotlinFileContext) { - val left = KtPsiUtil.deparenthesize(expression.left) ?: return - if (expression.operationToken == KtTokens.EQ) { - PROPERTY_NAMES - .firstOrNull { propertyName -> left.setterMatches(ctx.bindingContext, propertyName, ANDROID_FILE_ACCESS_MATCHER) } - ?.let { checkFileAccessArgument(ctx, expression.right) } + override fun visitBinaryExpression(expression: KtBinaryExpression, ctx: KotlinFileContext) = withKaSession { + if (expression.operationToken == KtTokens.EQ + && ANDROID_FILE_ACCESS_MATCHER.matches( + expression.resolveToCall()?.successfulCallOrNull>() + ) + ) { + checkFileAccessArgument(ctx, expression.right) } } private fun checkFileAccessArgument(ctx: KotlinFileContext, argument: KtExpression?) { - if (argument?.predictRuntimeBooleanValue(ctx.bindingContext) == true) { + if (argument?.predictRuntimeBooleanValue() == true) { ctx.reportIssue(argument, MESSAGE) } }