Skip to content

Commit

Permalink
Migrate UnpredictableSecureRandomSaltCheck 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 3, 2025
1 parent 7636af7 commit 2251e36
Showing 1 changed file with 10 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand All @@ -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<KaCallableMemberCall<*, *>>()) &&
saltArg.isInitializedPredictably(predictedSaltValue)
) {
kotlinFileContext.reportIssue(saltArg, MESSAGE, listOf(kotlinFileContext.secondaryOf(predictedSaltValue)))
}
Expand Down

0 comments on commit 2251e36

Please sign in to comment.