@Override public void visitCall(UastAndroidContext context, UCallExpression node) { UFunction resolved = node.resolve(context); if (resolved == null || !UastUtils.getContainingClassOrEmpty(resolved).isSubclassOf(PACKAGE_MANAGER_CLASS)) { return; } List<UExpression> argumentList = node.getValueArguments(); // Ignore if the method doesn't fit our description. if (argumentList.size() == 2) { UType firstParameterType = argumentList.get(0).getExpressionType(); if (firstParameterType != null && firstParameterType.matchesFqName(JavaParser.TYPE_STRING)) { maybeReportIssue(calculateValue(context, argumentList.get(1)), context, node); } } }
private static void maybeReportIssue( int flagValue, UastAndroidContext context, UCallExpression node) { if ((flagValue & GET_SIGNATURES_FLAG) != 0) { context.report( ISSUE, node, context.getLocation(node.getValueArguments().get(1)), "Reading app signatures from getPackageInfo: The app signatures " + "could be exploited if not validated properly; " + "see issue explanation for details."); } }
private static void ensureAtLeast( @NonNull JavaContext context, @NonNull UCallExpression node, int parameter, long min) { UExpression argument = node.getValueArguments().get(parameter); long value = getLongValue(context, argument); if (value < min) { String message = String.format( "Value will be forced up to %1$d as of Android 5.1; " + "don't rely on this to be exact", min); context.report(ISSUE, argument, context.getUastLocation(argument), message); } }
@Nullable private static String getLhs(@NonNull UCallExpression call) { UElement parent = call.getParent(); if (UastBinaryExpressionWithTypeUtils.isTypeCast(parent)) { assert parent != null; parent = parent.getParent(); } if (parent instanceof UVariable) { UVariable vde = (UVariable) parent; return vde.getName(); } else if (parent instanceof UBinaryExpression) { UBinaryExpression be = (UBinaryExpression) parent; UExpression left = be.getLeftOperand(); if (left instanceof USimpleReferenceExpression || left instanceof UQualifiedExpression) { return be.getLeftOperand().toString(); } else if (left instanceof UArrayAccessExpression) { UArrayAccessExpression aa = (UArrayAccessExpression) left; return aa.getReceiver().toString(); } } return null; }
@Override public void visitCall(UastAndroidContext context, UCallExpression node) { String lhs = getLhs(node); if (lhs == null) { return; } UFunction method = UastUtils.getContainingFunction(node); if (method == null) { return; } else if (method != mLastMethod) { mIds = Maps.newHashMap(); mLhs = Maps.newHashMap(); mCallOperands = Maps.newHashMap(); mLastMethod = method; } UElement parent = node.getParent(); String callOperand = ""; if (parent instanceof UQualifiedExpression) { callOperand = ((UQualifiedExpression) parent).getReceiver().renderString(); } UExpression first = node.getValueArguments().get(0); if (first instanceof UQualifiedExpression) { UQualifiedExpression select = (UQualifiedExpression) first; String id = select.getSelector().renderString(); UExpression operand = select.getReceiver(); if (operand instanceof UQualifiedExpression) { UQualifiedExpression type = (UQualifiedExpression) operand; if (type.getSelector().renderString().equals(RESOURCE_CLZ_ID)) { if (mIds.containsKey(id)) { if (lhs.equals(mLhs.get(id))) { return; } if (!callOperand.equals(mCallOperands.get(id))) { return; } UCallExpression earlierCall = mIds.get(id); if (!isReachableFrom(method, earlierCall, node)) { return; } Location location = context.getLocation(node); Location secondary = context.getLocation(earlierCall); if (location != null && secondary != null) { secondary.setMessage("First usage here"); location.setSecondary(secondary); context.report( ISSUE, node, location, String.format( "The id `%1$s` has already been looked up in this method; possible " + "cut & paste error?", first.toString())); } } else { mIds.put(id, node); mLhs.put(id, lhs); mCallOperands.put(id, callOperand); } } } } }