From 704b5b0f729709c91b69c2fc4632a749cf45eb44 Mon Sep 17 00:00:00 2001 From: Artemiy Sartakov Date: Thu, 2 Dec 2021 15:23:56 +0700 Subject: [PATCH] SourceToSinkFlowInspection: support for kotlin primary constructor parameter (IDEA-282918) GitOrigin-RevId: 9d89e42e7d7891237b180ede447d7bd6b3e134af --- .../sourceToSink/TaintAnalyzer.java | 32 +++++++++++-------- .../sourceToSink/propagate/PropagateFix.java | 10 +----- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/TaintAnalyzer.java b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/TaintAnalyzer.java index 4b8d42f32792..81be376e23b4 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/TaintAnalyzer.java +++ b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/TaintAnalyzer.java @@ -4,6 +4,7 @@ package com.intellij.codeInspection.sourceToSink; import com.intellij.psi.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.ObjectUtils; +import com.intellij.util.SmartList; import com.siyeh.ig.psiutils.ExpressionUtils; import one.util.streamex.MoreCollectors; import one.util.streamex.StreamEx; @@ -73,11 +74,11 @@ public class TaintAnalyzer { return codeBlock == null ? TaintValue.UNTAINTED : analyze(taintValue, codeBlock, psiVariable); } - private TaintValue analyze(@NotNull TaintValue taintValue, @NotNull UBlockExpression codeBlock, @NotNull PsiVariable psiVariable) { + private @NotNull TaintValue analyze(@NotNull TaintValue taintValue, @NotNull UBlockExpression codeBlock, @NotNull PsiVariable psiVariable) { class VarAnalyzer extends AbstractUastVisitor { private TaintValue myTaintValue; - VarAnalyzer(TaintValue taintValue) { + VarAnalyzer(@NotNull TaintValue taintValue) { myTaintValue = taintValue; } @@ -110,27 +111,30 @@ public class TaintAnalyzer { } private @Nullable TaintValue fromParam(@Nullable PsiElement target) { + PsiParameter psiParameter = ObjectUtils.tryCast(target, PsiParameter.class); + if (psiParameter == null) return null; UParameter uParameter = UastContextKt.toUElement(target, UParameter.class); if (uParameter == null) return null; - PsiParameter psiParameter = ObjectUtils.tryCast(uParameter.getSourcePsi(), PsiParameter.class); - if (psiParameter == null) return null; - UMethod uMethod = ObjectUtils.tryCast(uParameter.getUastParent(), UMethod.class); - if (uMethod == null) return TaintValue.UNTAINTED; - UBlockExpression uBlock = ObjectUtils.tryCast(uMethod.getUastBody(), UBlockExpression.class); - if (uBlock == null) return TaintValue.UNTAINTED; // default parameter value UExpression uInitializer = uParameter.getUastInitializer(); TaintValue taintValue = fromExpression(uInitializer, true); if (taintValue == TaintValue.TAINTED) return taintValue; - taintValue = analyze(taintValue, uBlock, psiParameter); + UMethod uMethod = ObjectUtils.tryCast(uParameter.getUastParent(), UMethod.class); + if (uMethod == null) return TaintValue.UNTAINTED; + UBlockExpression uBlock = ObjectUtils.tryCast(uMethod.getUastBody(), UBlockExpression.class); + if (uBlock != null) taintValue = analyze(taintValue, uBlock, psiParameter); if (taintValue == TaintValue.TAINTED) return taintValue; - int paramIdx = uMethod.getUastParameters().indexOf(uParameter); + SmartList nonMarkedElements = new SmartList<>(); + // this might happen when we analyze kotlin primary constructor parameter + if (uBlock == null) nonMarkedElements.addAll(findAssignments(target)); PsiMethod psiMethod = ObjectUtils.tryCast(uMethod.getSourcePsi(), PsiMethod.class); // TODO: handle varargs - if (psiMethod == null || psiMethod.isVarArgs()) return TaintValue.UNTAINTED; - Collection args = findArgs(psiMethod, paramIdx); - if (args.isEmpty()) return taintValue; - myNonMarkedElements.addAll(args); + if (psiMethod != null && !psiMethod.isVarArgs()) { + int paramIdx = uMethod.getUastParameters().indexOf(uParameter); + nonMarkedElements.addAll(findArgs(psiMethod, paramIdx)); + } + if (nonMarkedElements.isEmpty()) return taintValue; + myNonMarkedElements.addAll(nonMarkedElements); return TaintValue.UNKNOWN; } diff --git a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/propagate/PropagateFix.java b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/propagate/PropagateFix.java index 7d7e8978c93b..28afc030a3b9 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/propagate/PropagateFix.java +++ b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/sourceToSink/propagate/PropagateFix.java @@ -16,13 +16,9 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.content.Content; import com.intellij.usageView.UsageViewContentManager; -import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,11 +55,7 @@ public class PropagateFix extends LocalQuickFixAndIntentionActionOnPsiElement { if (reportedElement == null) return; TaintAnalyzer analyzer = new TaintAnalyzer(); if (analyzer.analyze(uExpression) != TaintValue.UNKNOWN) return; - PsiModifierListOwner target = ObjectUtils.tryCast(((UResolvable)uExpression).resolve(), PsiModifierListOwner.class); - if (target == null) return; - // TODO: won't work if we start from kotlin - PsiMethod method = PsiTreeUtil.getParentOfType(reportedElement, PsiMethod.class); - if (method == null) return; + PsiElement target = ((UResolvable)uExpression).resolve(); String title = JvmAnalysisBundle.message("jvm.inspections.source.unsafe.to.sink.flow.propagate.safe.toolwindow.title"); TaintNode root = new TaintNode(null, target, reportedElement); if (ApplicationManager.getApplication().isHeadlessEnvironment()) {