Skip to content

Commit

Permalink
Migrate WebViewsFileAccessCheck to kotlin-analysis-api
Browse files Browse the repository at this point in the history
Co-authored-by: Marharyta Nedzelska <[email protected]>
Co-authored-by: Evgeny Mandrikov <[email protected]>
  • Loading branch information
Godin and leveretka committed Feb 2, 2025
1 parent 6df424e commit 87bf68d
Showing 1 changed file with 14 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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<KaCallableMemberCall<*, *>>()
)
) {
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)
}
}
Expand Down

0 comments on commit 87bf68d

Please sign in to comment.