SourceToSinkFlowInspection: support for kotlin primary constructor parameter (IDEA-282918)

GitOrigin-RevId: 9d89e42e7d7891237b180ede447d7bd6b3e134af
This commit is contained in:
Artemiy Sartakov
2021-12-03 06:41:31 +00:00
committed by intellij-monorepo-bot
parent 83c934c331
commit 704b5b0f72
2 changed files with 19 additions and 23 deletions
@@ -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<NonMarkedElement> 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<NonMarkedElement> 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;
}
@@ -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()) {