Skip to content

Commit 6fb871c

Browse files
leveretkaGodin
authored andcommitted
SONARKT-400 Migrate CipherBlockChainingCheck to kotlin-analysis-api
1 parent a9debb7 commit 6fb871c

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherBlockChainingCheck.kt

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
*/
1717
package org.sonarsource.kotlin.checks
1818

19+
import org.jetbrains.kotlin.analysis.api.resolution.KaFunctionCall
20+
import org.jetbrains.kotlin.analysis.api.resolution.successfulFunctionCallOrNull
1921
import org.jetbrains.kotlin.psi.KtCallExpression
2022
import org.jetbrains.kotlin.psi.KtExpression
21-
import org.jetbrains.kotlin.resolve.BindingContext
22-
import org.jetbrains.kotlin.resolve.calls.util.getCall
23-
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
2423
import org.sonar.check.Rule
2524
import org.sonarsource.kotlin.api.checks.CallAbstractCheck
2625
import org.sonarsource.kotlin.api.checks.ConstructorMatcher
@@ -32,8 +31,8 @@ import org.sonarsource.kotlin.api.checks.STRING_TYPE
3231
import org.sonarsource.kotlin.api.checks.predictReceiverExpression
3332
import org.sonarsource.kotlin.api.checks.predictRuntimeStringValue
3433
import org.sonarsource.kotlin.api.checks.predictRuntimeValueExpression
35-
3634
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
35+
import org.sonarsource.kotlin.api.visiting.withKaSession
3736

3837
private val CIPHER_INIT_MATCHER = FunMatcher(qualifier = "javax.crypto.Cipher", name = "init") {
3938
withArguments(INT_TYPE, "java.security.Key", "java.security.spec.AlgorithmParameterSpec")
@@ -46,43 +45,48 @@ private val GET_INSTANCE_MATCHER = FunMatcher(qualifier = "javax.crypto.Cipher",
4645
private val GET_BYTES_MATCHER = FunMatcher(qualifier = "kotlin.text", name = "toByteArray")
4746
private val IV_PARAMETER_SPEC_MATCHER = ConstructorMatcher("javax.crypto.spec.IvParameterSpec")
4847

49-
@org.sonarsource.kotlin.api.frontend.K1only
5048
@Rule(key = "S3329")
5149
class CipherBlockChainingCheck : CallAbstractCheck() {
5250
override val functionsToVisit = listOf(CIPHER_INIT_MATCHER)
5351

5452
override fun visitFunctionCall(
5553
callExpression: KtCallExpression,
56-
resolvedCall: ResolvedCall<*>,
54+
resolvedCall: KaFunctionCall<*>,
55+
matchedFun: FunMatcherImpl,
5756
kotlinFileContext: KotlinFileContext,
5857
) {
59-
val bindingContext = kotlinFileContext.bindingContext
6058
val calleeExpression = callExpression.calleeExpression ?: return
61-
val receiverExpression = callExpression.predictReceiverExpression(bindingContext) ?: return
59+
val receiverExpression = callExpression.predictReceiverExpression() ?: return
6260
val thirdArgument = callExpression.valueArguments[2].getArgumentExpression() ?: return
6361

64-
if (receiverExpression.isCBC(bindingContext) && thirdArgument.isInitializedWithToByteArray(bindingContext)) {
62+
if (receiverExpression.isCBC() && thirdArgument.isInitializedWithToByteArray()) {
6563
kotlinFileContext.reportIssue(calleeExpression, "Use a dynamically-generated, random IV.")
6664
}
6765
}
6866
}
6967

70-
private fun KtExpression.isInitializedWithToByteArray(bindingContext: BindingContext) =
71-
firstArgumentOfInitializer(bindingContext, IV_PARAMETER_SPEC_MATCHER)
72-
?.predictRuntimeValueExpression(bindingContext)
73-
?.getCall(bindingContext)?.let { expr ->
74-
GET_BYTES_MATCHER.matches(expr, bindingContext)
68+
private fun KtExpression.isInitializedWithToByteArray() = withKaSession {
69+
firstArgumentOfInitializer(IV_PARAMETER_SPEC_MATCHER)
70+
?.predictRuntimeValueExpression()
71+
?.resolveToCall()
72+
?.successfulFunctionCallOrNull()
73+
?.let { expr ->
74+
GET_BYTES_MATCHER.matches(expr)
7575
} ?: false
76+
}
7677

77-
private fun KtExpression.isCBC(bindingContext: BindingContext) =
78-
firstArgumentOfInitializer(bindingContext, GET_INSTANCE_MATCHER)
79-
?.predictRuntimeStringValue(bindingContext)
78+
private fun KtExpression.isCBC() =
79+
firstArgumentOfInitializer(GET_INSTANCE_MATCHER)
80+
?.predictRuntimeStringValue()
8081
?.contains("CBC", ignoreCase = true)
8182
?: false
8283

83-
private fun KtExpression.firstArgumentOfInitializer(bindingContext: BindingContext, matcher: FunMatcherImpl) =
84-
predictRuntimeValueExpression(bindingContext)
85-
.getCall(bindingContext)?.let {
86-
if (matcher.matches(it, bindingContext)) it.valueArguments[0].getArgumentExpression()
87-
else null
84+
private fun KtExpression.firstArgumentOfInitializer(matcher: FunMatcherImpl) = withKaSession {
85+
predictRuntimeValueExpression()
86+
.resolveToCall()
87+
?.successfulFunctionCallOrNull()?.let {
88+
if (matcher.matches(it)) {
89+
it.argumentMapping.keys.elementAt(0)
90+
} else null
8891
}
92+
}

0 commit comments

Comments
 (0)