From b5825aab4a246780cf968d964e93faf62307f766 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Sun, 2 Feb 2025 23:30:01 +0100 Subject: [PATCH] Migrate UnpredictableSecureRandomSaltCheck to kotlin-analysis-api Co-authored-by: Marharyta Nedzelska Co-authored-by: Evgeny Mandrikov --- .../UnpredictableSecureRandomSaltCheck.kt | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt index e39d9f405..6c97f73bf 100644 --- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt +++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt @@ -16,10 +16,11 @@ */ 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.singleCallOrNull import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtConstantExpression -import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.sonar.check.Rule import org.sonarsource.kotlin.api.checks.ArgumentMatcher import org.sonarsource.kotlin.api.checks.BYTE_ARRAY_CONSTRUCTOR_SIZE_ARG_ONLY @@ -28,16 +29,14 @@ import org.sonarsource.kotlin.api.checks.ConstructorMatcher import org.sonarsource.kotlin.api.checks.FunMatcher import org.sonarsource.kotlin.api.checks.isBytesInitializedFromString import org.sonarsource.kotlin.api.checks.isInitializedPredictably -import org.sonarsource.kotlin.api.checks.matches import org.sonarsource.kotlin.api.checks.predictRuntimeValueExpression import org.sonarsource.kotlin.api.frontend.secondaryOf -import org.sonarsource.kotlin.api.checks.simpleArgExpressionOrNull import org.sonarsource.kotlin.api.frontend.KotlinFileContext +import org.sonarsource.kotlin.api.visiting.withKaSession private const val MESSAGE = "Change this seed value to something unpredictable, or remove the seed." private const val SECURE_RANDOM = "java.security.SecureRandom" -@org.sonarsource.kotlin.api.frontend.K1only @Rule(key = "S4347") class UnpredictableSecureRandomSaltCheck : CallAbstractCheck() { override val functionsToVisit = listOf( @@ -47,17 +46,15 @@ class UnpredictableSecureRandomSaltCheck : CallAbstractCheck() { } ) - override fun visitFunctionCall(callExpression: KtCallExpression, resolvedCall: ResolvedCall<*>, kotlinFileContext: KotlinFileContext) { - val bindingContext = kotlinFileContext.bindingContext + override fun visitFunctionCall(callExpression: KtCallExpression, resolvedCall: KaFunctionCall<*>, kotlinFileContext: KotlinFileContext) = withKaSession { + val saltArg = resolvedCall.argumentMapping.keys.firstOrNull() ?: return@withKaSession + val predictedSaltValue = saltArg.predictRuntimeValueExpression() - val saltArg = resolvedCall.simpleArgExpressionOrNull(0) ?: return - val predictedSaltValue = saltArg.predictRuntimeValueExpression(bindingContext) - - if (predictedSaltValue is KtConstantExpression || predictedSaltValue.isBytesInitializedFromString(bindingContext)) { + if (predictedSaltValue is KtConstantExpression || predictedSaltValue.isBytesInitializedFromString()) { kotlinFileContext.reportIssue(saltArg, MESSAGE, listOf(kotlinFileContext.secondaryOf(predictedSaltValue))) } else if ( - predictedSaltValue.getResolvedCall(bindingContext) matches BYTE_ARRAY_CONSTRUCTOR_SIZE_ARG_ONLY && - saltArg.isInitializedPredictably(predictedSaltValue, bindingContext) + BYTE_ARRAY_CONSTRUCTOR_SIZE_ARG_ONLY.matches(predictedSaltValue.resolveToCall()?.singleCallOrNull>()) && + saltArg.isInitializedPredictably(predictedSaltValue) ) { kotlinFileContext.reportIssue(saltArg, MESSAGE, listOf(kotlinFileContext.secondaryOf(predictedSaltValue))) }