use of com.jetbrains.php.lang.psi.elements.ArrayAccessExpression in project phpinspectionsea by kalessil.
the class ArrayPushMissUseInspector 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("array_push")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 2 && OpenapiTypesUtil.isStatementImpl(reference.getParent())) {
PsiElement variadicCandidate = arguments[1].getPrevSibling();
if (variadicCandidate instanceof PsiWhiteSpace) {
variadicCandidate = variadicCandidate.getPrevSibling();
}
if (!OpenapiTypesUtil.is(variadicCandidate, PhpTokenTypes.opVARIADIC)) {
final String replacement = String.format("%s[] = %s", arguments[0].getText(), arguments[1].getText());
holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messageMisuse), replacement), new UseElementPushFix(replacement));
}
}
}
}
@Override
public void visitPhpArrayAccessExpression(@NotNull ArrayAccessExpression expression) {
if (REPORT_EXCESSIVE_COUNT_CALLS) {
final PsiElement parent = expression.getParent();
if (OpenapiTypesUtil.isAssignment(parent)) {
final PsiElement value = ((AssignmentExpression) parent).getValue();
if (value != expression) {
final ArrayIndex index = expression.getIndex();
if (index != null) {
final PsiElement candidate = index.getValue();
if (OpenapiTypesUtil.isFunctionReference(candidate)) {
final FunctionReference reference = (FunctionReference) candidate;
final String functionName = reference.getName();
if (functionName != null && functionName.equals("count")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 1) {
final PsiElement container = expression.getValue();
if (container != null && OpenapiEquivalenceUtil.areEqual(container, arguments[0])) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUnneeded), ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
}
}
}
}
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.ArrayAccessExpression in project phpinspectionsea by kalessil.
the class UnnecessaryIssetArgumentsInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpIsset(@NotNull PhpIsset issetExpression) {
final PsiElement[] arguments = issetExpression.getVariables();
if (arguments.length > 1) {
final Set<PsiElement> reported = new HashSet<>();
for (final PsiElement current : arguments) {
if (current instanceof ArrayAccessExpression && !reported.contains(current)) {
/* collect current element bases */
final List<PsiElement> bases = new ArrayList<>();
PsiElement base = current;
while (base instanceof ArrayAccessExpression) {
base = ((ArrayAccessExpression) base).getValue();
if (base != null) {
bases.add(base);
}
}
/* iterate arguments once more to match */
if (!bases.isEmpty()) {
for (final PsiElement discoveredBase : bases) {
for (final PsiElement match : arguments) {
if (match != current && !reported.contains(match) && OpenapiEquivalenceUtil.areEqual(discoveredBase, match)) {
holder.registerProblem(match, MessagesPresentationUtil.prefixWithEa(message), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropArgumentFix());
reported.add(match);
}
}
}
bases.clear();
}
}
}
reported.clear();
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.ArrayAccessExpression in project phpinspectionsea by kalessil.
the class OpAssignShortSyntaxInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpAssignmentExpression(@NotNull AssignmentExpression assignment) {
final PsiElement value = ExpressionSemanticUtil.getExpressionTroughParenthesis(assignment.getValue());
if (value instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) value;
final PsiElement operator = binary.getOperation();
if (operator != null) {
final PsiElement left = binary.getLeftOperand();
final PsiElement right = binary.getRightOperand();
final PsiElement variable = assignment.getVariable();
if (variable != null && left != null && right != null) {
final IElementType operation = operator.getNode().getElementType();
if (mapping.containsKey(operation)) {
final LinkedList<PsiElement> fragments = new LinkedList<>();
fragments.addLast(right);
PsiElement candidate = left;
while (candidate instanceof BinaryExpression) {
final BinaryExpression current = (BinaryExpression) candidate;
final PsiElement rightPart = current.getRightOperand();
if (rightPart != null) {
fragments.addLast(rightPart);
}
if (current.getOperationType() != operation) {
break;
}
candidate = current.getLeftOperand();
}
if (candidate != null && OpenapiEquivalenceUtil.areEqual(variable, candidate)) {
final boolean canShorten = (fragments.size() == 1 || chainingSafeOperators.contains(operation)) && fragments.stream().noneMatch(f -> f instanceof BinaryExpression);
if (canShorten) {
/* false-positives: string elements manipulation, causes a fatal error */
boolean isStringManipulation = false;
if (variable instanceof ArrayAccessExpression) {
final PsiElement stringCandidate = ((ArrayAccessExpression) variable).getValue();
if (stringCandidate instanceof PhpTypedElement) {
final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) stringCandidate, holder.getProject());
if (resolved != null && !resolved.hasUnknown()) {
isStringManipulation = resolved.getTypes().stream().anyMatch(t -> Types.getType(t).equals(Types.strString));
}
}
}
if (!isStringManipulation) {
Collections.reverse(fragments);
final String replacement = String.format("%s %s= %s", candidate.getText(), operator.getText(), fragments.stream().map(PsiElement::getText).collect(Collectors.joining(" " + operator.getText() + " ")));
holder.registerProblem(assignment, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new UseShorthandOperatorFix(replacement));
}
}
}
fragments.clear();
}
}
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.ArrayAccessExpression in project phpinspectionsea by kalessil.
the class GenerateAlternativeFromArrayKeyExistsStrategy method generate.
@Nullable
public static String generate(@NotNull TernaryExpression expression) {
/* handle inverted cases */
PsiElement callCandidate = ExpressionSemanticUtil.getExpressionTroughParenthesis(expression.getCondition());
boolean isInverted = false;
if (callCandidate instanceof UnaryExpression) {
final PsiElement operator = ((UnaryExpression) callCandidate).getOperation();
if (null != operator && PhpTokenTypes.opNOT == operator.getNode().getElementType()) {
isInverted = true;
callCandidate = ((UnaryExpression) callCandidate).getValue();
}
}
/* verify condition structure */
final FunctionReference call = OpenapiTypesUtil.isFunctionReference(callCandidate) ? (FunctionReference) callCandidate : null;
final String functionName = null == call ? null : call.getName();
if (null == functionName || 2 != call.getParameters().length || !functionName.equals("array_key_exists")) {
return null;
}
/* array_key_exists is valid only with null-alternatives */
final PsiElement alternative = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getTrueVariant() : expression.getFalseVariant());
final PsiElement value = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getFalseVariant() : expression.getTrueVariant());
if (!(value instanceof ArrayAccessExpression) || !PhpLanguageUtil.isNull(alternative)) {
return null;
}
/* verify condition and variant structure */
final PsiElement[] params = call.getParameters();
final ArrayAccessExpression array = (ArrayAccessExpression) value;
final PsiElement container = array.getValue();
final PsiElement index = null == array.getIndex() ? null : array.getIndex().getValue();
if (null == params[0] || null == params[1] || null == container || null == index) {
return null;
}
if (!OpenapiEquivalenceUtil.areEqual(params[1], container) || !OpenapiEquivalenceUtil.areEqual(params[0], index)) {
return null;
}
return value.getText() + " ?? " + alternative.getText();
}
use of com.jetbrains.php.lang.psi.elements.ArrayAccessExpression 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();
}
};
}
Aggregations