use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class AssertFileEqualsStrategy method apply.
public static boolean apply(@NotNull String methodName, @NotNull MethodReference reference, @NotNull ProblemsHolder holder) {
boolean result = false;
if (targetAssertions.contains(methodName)) {
final PsiElement[] assertionArguments = reference.getParameters();
if (assertionArguments.length > 1) {
/* try extracting file_get_contents arguments */
final List<PsiElement> extracts = Arrays.stream(assertionArguments).map(argument -> {
PsiElement mappingResult = null;
if (OpenapiTypesUtil.isFunctionReference(argument)) {
final FunctionReference candidate = (FunctionReference) argument;
final String functionName = candidate.getName();
if (functionName != null && functionName.equals("file_get_contents")) {
final PsiElement[] functionArguments = candidate.getParameters();
if (functionArguments.length == 1) {
mappingResult = functionArguments[0];
}
}
}
return mappingResult;
}).collect(Collectors.toList());
/* now check if reporting is needed */
if (extracts.size() > 1) {
final Function scope = ExpressionSemanticUtil.getScope(reference);
final boolean shouldReport = scope == null || !scope.getName().equals("assertFileEquals");
if (shouldReport) {
String[] suggestedArguments = null;
if (methodName.equals("assertStringEqualsFile") && extracts.get(1) != null) {
suggestedArguments = new String[assertionArguments.length];
suggestedArguments[0] = assertionArguments[0].getText();
suggestedArguments[1] = extracts.get(1).getText();
if (assertionArguments.length > 2) {
suggestedArguments[2] = assertionArguments[2].getText();
}
} else if (extracts.get(0) != null && extracts.get(1) != null) {
suggestedArguments = new String[assertionArguments.length];
suggestedArguments[0] = extracts.get(0).getText();
suggestedArguments[1] = extracts.get(1).getText();
if (assertionArguments.length > 2) {
suggestedArguments[2] = assertionArguments[2].getText();
}
}
if (suggestedArguments != null) {
final String suggestedAssertion = "assertFileEquals";
holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), suggestedAssertion), new PhpUnitAssertFixer(suggestedAssertion, suggestedArguments));
result = true;
}
}
}
extracts.clear();
}
}
return result;
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class IncorrectRandomRangeInspector 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 && functions.contains(functionName)) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 2) {
final Set<PsiElement> fromVariants = PossibleValuesDiscoveryUtil.discover(arguments[0]);
if (fromVariants.size() == 1) {
final PsiElement from = fromVariants.iterator().next();
if (OpenapiTypesUtil.isNumber(from)) {
final Set<PsiElement> toVariants = PossibleValuesDiscoveryUtil.discover(arguments[1]);
if (toVariants.size() == 1) {
final PsiElement to = toVariants.iterator().next();
if (OpenapiTypesUtil.isNumber(to)) {
boolean isTarget;
try {
isTarget = Long.parseLong(to.getText()) < Long.parseLong(from.getText());
} catch (final NumberFormatException wrongFormat) {
isTarget = false;
}
if (isTarget) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
}
}
}
toVariants.clear();
}
}
fromVariants.clear();
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class StrlenInEmptyStringCheckContextInspection 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("strlen") || functionName.equals("mb_strlen"))) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length > 0 && ExpressionSemanticUtil.getBlockScope(reference) != null) {
boolean isMatchedPattern = false;
boolean isEmptyString = false;
PsiElement target = null;
/* check explicit numbers comparisons */
final PsiElement parent = reference.getParent();
if (parent instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) parent;
final PsiElement left = binary.getLeftOperand();
final PsiElement secondOperand = OpenapiElementsUtil.getSecondOperand(binary, reference);
/* second operand should be a number */
if (OpenapiTypesUtil.isNumber(secondOperand)) {
final String number = secondOperand.getText();
/* check cases when comparing with 1 */
final IElementType operator = binary.getOperationType();
if (operator == PhpTokenTypes.opGREATER) {
isMatchedPattern = left == reference && number.equals("0");
target = binary;
isEmptyString = false;
} else if (operator == PhpTokenTypes.opLESS || operator == PhpTokenTypes.opGREATER_OR_EQUAL) {
isMatchedPattern = left == reference && number.equals("1");
target = binary;
isEmptyString = operator == PhpTokenTypes.opLESS;
}
/* check cases when checking equality to 0 */
if (!isMatchedPattern && OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator)) {
isMatchedPattern = number.equals("0");
target = binary;
isEmptyString = operator == PhpTokenTypes.opIDENTICAL || operator == PhpTokenTypes.opEQUAL;
}
}
}
/* checks NON-implicit boolean comparison patterns */
if (!isMatchedPattern && ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
isMatchedPattern = true;
target = reference;
final PsiElement operation = parent instanceof UnaryExpression ? ((UnaryExpression) parent).getOperation() : null;
if (operation != null) {
isEmptyString = OpenapiTypesUtil.is(operation, PhpTokenTypes.opNOT);
target = parent;
}
}
/* investigate possible issues */
if (isMatchedPattern) {
final boolean isRegular = ComparisonStyle.isRegular();
final String operator = (isEmptyString ? "=" : "!") + (this.canApplyIdentityOperator(arguments[0]) ? "==" : "=");
final String replacement = String.format(isRegular ? "%s %s ''" : "'' %s %s", isRegular ? arguments[0].getText() : operator, isRegular ? operator : arguments[0].getText());
holder.registerProblem(target, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new CompareToEmptyStringFix(replacement));
}
}
}
}
private boolean canApplyIdentityOperator(@NotNull PsiElement value) {
if (value instanceof PhpTypedElement) {
final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) value, holder.getProject());
if (resolved != null && resolved.size() == 1) {
return Types.strString.equals(Types.getType(resolved.getTypes().iterator().next()));
}
}
return false;
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference 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();
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class ChainedCallsStrategy method apply.
private static void apply(@NotNull MethodReference reference, @NotNull Map<MethodReference, String> nullTestedReferences, @NotNull ProblemsHolder holder) {
final PsiElement operator = OpenapiPsiSearchUtil.findResolutionOperator(reference);
if (OpenapiTypesUtil.is(operator, PhpTokenTypes.ARROW) && !OpenapiTypesUtil.isNullSafeMemberReferenceOperator(operator)) {
final PsiElement base = reference.getFirstPsiChild();
if (base instanceof FunctionReference) {
final FunctionReference baseCall = (FunctionReference) base;
final PhpType returnType = OpenapiResolveUtil.resolveType(baseCall, holder.getProject());
if (returnType != null) {
final String methodName = baseCall.getName();
for (final String resolvedType : returnType.filterUnknown().getTypes()) {
final String type = Types.getType(resolvedType);
if (type.equals(Types.strNull) || type.equals(Types.strVoid)) {
boolean isNullTested = false;
for (final Map.Entry<MethodReference, String> knownReference : nullTestedReferences.entrySet()) {
final String nullTestedMethodName = knownReference.getValue();
if (nullTestedMethodName != null && nullTestedMethodName.equals(methodName) && OpenapiEquivalenceUtil.areEqual(knownReference.getKey(), baseCall)) {
isNullTested = true;
break;
}
}
if (!isNullTested) {
holder.registerProblem(operator, MessagesPresentationUtil.prefixWithEa(message));
break;
}
}
}
}
}
/* collect null-tested references: only after main inspection! */
final PsiElement parent = reference.getParent();
if (parent instanceof BinaryExpression) {
final BinaryExpression parentExpression = (BinaryExpression) parent;
final IElementType operation = parentExpression.getOperationType();
if (OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operation)) {
final PsiElement secondOperand = OpenapiElementsUtil.getSecondOperand(parentExpression, reference);
if (PhpLanguageUtil.isNull(secondOperand)) {
nullTestedReferences.put(reference, reference.getName());
}
} else if (operation == PhpTokenTypes.kwINSTANCEOF || PhpTokenTypes.tsSHORT_CIRCUIT_AND_OPS.contains(operation)) {
nullTestedReferences.put(reference, reference.getName());
}
} else if (ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
nullTestedReferences.put(reference, reference.getName());
}
}
}
Aggregations