Search in sources :

Example 1 with Variable

use of com.jetbrains.php.lang.psi.elements.Variable in project phpinspectionsea by kalessil.

the class ExplodeMissUseInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            /* general structure expectations */
            final String functionName = reference.getName();
            if (functionName == null || !semanticMapping.containsKey(functionName)) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length != 1) {
                return;
            }
            /* discover possible values */
            final Set<PsiElement> values = PossibleValuesDiscoveryUtil.discover(arguments[0]);
            /* do not analyze invariants */
            if (1 == values.size()) {
                final PsiElement value = values.iterator().next();
                values.clear();
                if (OpenapiTypesUtil.isFunctionReference(value)) {
                    /* inner call must be explode() */
                    final FunctionReference innerCall = (FunctionReference) value;
                    final String innerFunctionName = innerCall.getName();
                    if (innerFunctionName == null || !innerFunctionName.equals("explode")) {
                        return;
                    }
                    final PsiElement[] innerArguments = innerCall.getParameters();
                    if (innerArguments.length != 2) {
                        return;
                    }
                    /* if the parameter is a variable, ensure it used only 2 times (write, read) */
                    if (arguments[0] instanceof Variable) {
                        final PhpScopeHolder parentScope = ExpressionSemanticUtil.getScope(reference);
                        if (null != parentScope) {
                            final PhpAccessVariableInstruction[] usages = PhpControlFlowUtil.getFollowingVariableAccessInstructions(parentScope.getControlFlow().getEntryPoint(), ((Variable) arguments[0]).getName(), false);
                            if (2 != usages.length) {
                                return;
                            }
                        }
                    }
                    final String replacement = semanticMapping.get(functionName).replace("%f%", innerArguments[0].getText()).replace("%s%", innerArguments[1].getText());
                    final String message = messagePattern.replace("%e%", replacement);
                    if (arguments[0] == value) {
                        holder.registerProblem(reference, message, new UseAlternativeFix(replacement));
                    } else {
                        holder.registerProblem(reference, message);
                    }
                }
            }
            values.clear();
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpAccessVariableInstruction(com.jetbrains.php.codeInsight.controlFlow.instructions.PhpAccessVariableInstruction) Variable(com.jetbrains.php.lang.psi.elements.Variable) PhpScopeHolder(com.jetbrains.php.codeInsight.PhpScopeHolder) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with Variable

use of com.jetbrains.php.lang.psi.elements.Variable in project phpinspectionsea by kalessil.

the class BadExceptionsProcessingInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpTry(@NotNull Try tryStatement) {
            final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(tryStatement);
            final int expressionsCount = body == null ? 0 : ExpressionSemanticUtil.countExpressionsInGroup(body);
            if (expressionsCount > 3) {
                holder.registerProblem(tryStatement.getFirstChild(), MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%c%", String.valueOf(expressionsCount))));
            }
        }

        @Override
        public void visitPhpCatch(@NotNull Catch catchStatement) {
            final Variable variable = catchStatement.getException();
            final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(catchStatement);
            if (variable != null && body != null) {
                final String variableName = variable.getName();
                if (!StringUtils.isEmpty(variableName)) {
                    /* incomplete catch statement */
                    boolean isVariableUsed = false;
                    for (final Variable usedVariable : PsiTreeUtil.findChildrenOfType(body, Variable.class)) {
                        if (usedVariable.getName().equals(variableName)) {
                            isVariableUsed = true;
                            break;
                        }
                    }
                    if (!isVariableUsed) {
                        if (ExpressionSemanticUtil.countExpressionsInGroup(body) == 0) {
                            holder.registerProblem(variable, MessagesPresentationUtil.prefixWithEa(messageFailSilently));
                        } else {
                            holder.registerProblem(variable, MessagesPresentationUtil.prefixWithEa(messageChainedException));
                        }
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) GroupStatement(com.jetbrains.php.lang.psi.elements.GroupStatement) Variable(com.jetbrains.php.lang.psi.elements.Variable) Catch(com.jetbrains.php.lang.psi.elements.Catch) Try(com.jetbrains.php.lang.psi.elements.Try) NotNull(org.jetbrains.annotations.NotNull) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with Variable

use of com.jetbrains.php.lang.psi.elements.Variable in project phpinspectionsea by kalessil.

the class UnserializeExploitsInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            final String functionName = reference.getName();
            if (functionName != null && functionName.equals("unserialize")) {
                final boolean supportsOptions = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP700);
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length == 1 && !this.isTestContext(reference)) {
                    /* pattern: use 2nd argument since PHP7 */
                    if (supportsOptions) {
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                    }
                    /* pattern: exploitable calls */
                    this.inspectExploits(holder, arguments[0]);
                } else if (arguments.length == 2 && !this.isTestContext(reference)) {
                    if (arguments[1] instanceof ArrayCreationExpression) {
                        final boolean hasClassesListed = arguments[1].getChildren().length > 0;
                        if (!hasClassesListed) {
                            holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                        }
                    } else if (PhpLanguageUtil.isTrue(arguments[1])) {
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                    }
                }
            }
        }

        private void inspectExploits(@NotNull ProblemsHolder holder, @NotNull PsiElement argument) {
            final Set<PsiElement> values = PossibleValuesDiscoveryUtil.discover(argument);
            if (!values.isEmpty()) {
                final List<String> reporting = new ArrayList<>();
                for (PsiElement value : values) {
                    if (OpenapiTypesUtil.isFunctionReference(value)) {
                        final FunctionReference call = (FunctionReference) value;
                        final String functionName = call.getName();
                        if (functionName != null && untrustedFunctions.contains(functionName)) {
                            reporting.add(functionName + "(...)");
                        }
                        continue;
                    }
                    /* extract array access variable */
                    if (value instanceof ArrayAccessExpression) {
                        PsiElement container = value;
                        while (container instanceof ArrayAccessExpression) {
                            container = ((ArrayAccessExpression) container).getValue();
                        }
                        if (container instanceof Variable) {
                            value = container;
                        }
                    }
                    if (value instanceof Variable && untrustedVars.contains(((Variable) value).getName())) {
                        reporting.add(value.getText());
                    // continue
                    }
                /* other expressions are not supported currently */
                }
                /* got something for reporting */
                if (!reporting.isEmpty()) {
                    /* sort reporting list to produce testable results */
                    Collections.sort(reporting);
                    holder.registerProblem(argument, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%e%", String.join(", ", reporting))), ProblemHighlightType.GENERIC_ERROR);
                    reporting.clear();
                }
            }
            values.clear();
        }
    };
}
Also used : Variable(com.jetbrains.php.lang.psi.elements.Variable) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) NotNull(org.jetbrains.annotations.NotNull) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ArrayAccessExpression(com.jetbrains.php.lang.psi.elements.ArrayAccessExpression) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with Variable

use of com.jetbrains.php.lang.psi.elements.Variable in project phpinspectionsea by kalessil.

the class ShortListSyntaxCanBeUsedInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        public void visitPhpMultiassignmentExpression(MultiassignmentExpression multiassignmentExpression) {
            /* ensure php version is at least PHP 7.1 */
            final PhpLanguageLevel phpVersion = PhpProjectConfigurationFacade.getInstance(holder.getProject()).getLanguageLevel();
            if (phpVersion.compareTo(PhpLanguageLevel.PHP710) < 0) {
                return;
            }
            /* verify if it's dedicated statement and it's the list(...) construction */
            final PsiElement parent = multiassignmentExpression.getParent();
            if (!OpenapiTypesUtil.isStatementImpl(parent)) {
                return;
            }
            final PsiElement listKeyword = multiassignmentExpression.getFirstChild();
            if (null != listKeyword && PhpTokenTypes.kwLIST == listKeyword.getNode().getElementType()) {
                holder.registerProblem(listKeyword, messageAssign, ProblemHighlightType.WEAK_WARNING, new TheLocalFix());
            }
        }

        public void visitPhpForeach(ForeachStatement foreach) {
            /* ensure php version is at least PHP 7.1 */
            final PhpLanguageLevel phpVersion = PhpProjectConfigurationFacade.getInstance(holder.getProject()).getLanguageLevel();
            if (phpVersion.compareTo(PhpLanguageLevel.PHP710) < 0) {
                return;
            }
            final List<Variable> variables = foreach.getVariables();
            if (variables.size() > 0) {
                PsiElement childNode = foreach.getFirstChild();
                while (null != childNode) {
                    if (childNode.getClass() == LeafPsiElement.class && PhpTokenTypes.kwLIST == childNode.getNode().getElementType()) {
                        holder.registerProblem(childNode, messageForeach, ProblemHighlightType.WEAK_WARNING, new TheLocalFix());
                        break;
                    }
                    childNode = childNode.getNextSibling();
                    if (childNode instanceof GroupStatement) {
                        break;
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) GroupStatement(com.jetbrains.php.lang.psi.elements.GroupStatement) Variable(com.jetbrains.php.lang.psi.elements.Variable) LeafPsiElement(com.intellij.psi.impl.source.tree.LeafPsiElement) MultiassignmentExpression(com.jetbrains.php.lang.psi.elements.MultiassignmentExpression) PhpLanguageLevel(com.jetbrains.php.config.PhpLanguageLevel) LeafPsiElement(com.intellij.psi.impl.source.tree.LeafPsiElement) PsiElement(com.intellij.psi.PsiElement) ForeachStatement(com.jetbrains.php.lang.psi.elements.ForeachStatement) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with Variable

use of com.jetbrains.php.lang.psi.elements.Variable in project phpinspectionsea by kalessil.

the class ArgumentUnpackingCanBeUsedInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            final PhpLanguageLevel php = PhpProjectConfigurationFacade.getInstance(holder.getProject()).getLanguageLevel();
            if (php.compareTo(PhpLanguageLevel.PHP560) >= 0) {
                final String functionName = reference.getName();
                if (functionName != null && functionName.equals("call_user_func_array")) {
                    final PsiElement[] arguments = reference.getParameters();
                    if (arguments.length == 2) {
                        final boolean isContainerValid = arguments[1] instanceof Variable || arguments[1] instanceof ArrayCreationExpression || arguments[1] instanceof FunctionReference;
                        if (isContainerValid && arguments[0] instanceof StringLiteralExpression) {
                            /* do not process strings with injections */
                            final StringLiteralExpression targetFunction = (StringLiteralExpression) arguments[0];
                            if (targetFunction.getFirstPsiChild() == null) {
                                final String replacement = "%f%(...%a%)".replace("%a%", arguments[1].getText()).replace("%f%", targetFunction.getContents());
                                final String message = messagePattern.replace("%e%", replacement);
                                holder.registerProblem(reference, message, new UnpackFix(replacement));
                            }
                        }
                    }
                }
            }
        // TODO: if (isContainerValid && params[0] instanceof ArrayCreationExpression) {
        // TODO: call_user_func_array([...], ...); string method name must not contain ::
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) Variable(com.jetbrains.php.lang.psi.elements.Variable) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) NotNull(org.jetbrains.annotations.NotNull) PhpLanguageLevel(com.jetbrains.php.config.PhpLanguageLevel) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Variable (com.jetbrains.php.lang.psi.elements.Variable)5 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)5 NotNull (org.jetbrains.annotations.NotNull)5 PsiElement (com.intellij.psi.PsiElement)4 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)3 PhpLanguageLevel (com.jetbrains.php.config.PhpLanguageLevel)2 ArrayCreationExpression (com.jetbrains.php.lang.psi.elements.ArrayCreationExpression)2 GroupStatement (com.jetbrains.php.lang.psi.elements.GroupStatement)2 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)1 LeafPsiElement (com.intellij.psi.impl.source.tree.LeafPsiElement)1 PhpScopeHolder (com.jetbrains.php.codeInsight.PhpScopeHolder)1 PhpAccessVariableInstruction (com.jetbrains.php.codeInsight.controlFlow.instructions.PhpAccessVariableInstruction)1 ArrayAccessExpression (com.jetbrains.php.lang.psi.elements.ArrayAccessExpression)1 Catch (com.jetbrains.php.lang.psi.elements.Catch)1 ForeachStatement (com.jetbrains.php.lang.psi.elements.ForeachStatement)1 MultiassignmentExpression (com.jetbrains.php.lang.psi.elements.MultiassignmentExpression)1 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)1 Try (com.jetbrains.php.lang.psi.elements.Try)1