|
55 | 55 | import com.sun.tools.javac.code.Symbol;
|
56 | 56 | import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
57 | 57 | import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
58 |
| -import com.sun.tools.javac.code.Symbol.VarSymbol; |
59 | 58 | import com.sun.tools.javac.code.Type;
|
60 | 59 | import com.sun.tools.javac.code.Type.ClassType;
|
| 60 | +import com.sun.tools.javac.tree.JCTree.JCNewClass; |
61 | 61 |
|
62 | 62 | import java.util.ArrayList;
|
63 | 63 | import java.util.Arrays;
|
|
67 | 67 | import java.util.Optional;
|
68 | 68 | import java.util.Set;
|
69 | 69 | import java.util.concurrent.atomic.AtomicReference;
|
70 |
| -import java.util.function.Predicate; |
71 | 70 | import java.util.regex.Pattern;
|
72 | 71 |
|
73 | 72 | import javax.lang.model.element.Name;
|
@@ -125,6 +124,12 @@ public final class RequiresPermissionChecker extends BugChecker
|
125 | 124 | instanceMethod()
|
126 | 125 | .onDescendantOf("android.content.Context")
|
127 | 126 | .withNameMatching(Pattern.compile("^send(Ordered|Sticky)?Broadcast.*$")));
|
| 127 | + private static final Matcher<ExpressionTree> SEND_BROADCAST_AS_USER = |
| 128 | + methodInvocation( |
| 129 | + instanceMethod() |
| 130 | + .onDescendantOf("android.content.Context") |
| 131 | + .withNameMatching( |
| 132 | + Pattern.compile("^send(Ordered|Sticky)?Broadcast.*AsUser.*$"))); |
128 | 133 | private static final Matcher<ExpressionTree> SEND_PENDING_INTENT = methodInvocation(
|
129 | 134 | instanceMethod()
|
130 | 135 | .onDescendantOf("android.app.PendingIntent")
|
@@ -306,18 +311,6 @@ public void addConstValue(Tree tree) {
|
306 | 311 | }
|
307 | 312 | }
|
308 | 313 |
|
309 |
| - private static ExpressionTree findArgumentByParameterName(MethodInvocationTree tree, |
310 |
| - Predicate<String> paramName) { |
311 |
| - final MethodSymbol sym = ASTHelpers.getSymbol(tree); |
312 |
| - final List<VarSymbol> params = sym.getParameters(); |
313 |
| - for (int i = 0; i < params.size(); i++) { |
314 |
| - if (paramName.test(params.get(i).name.toString())) { |
315 |
| - return tree.getArguments().get(i); |
316 |
| - } |
317 |
| - } |
318 |
| - return null; |
319 |
| - } |
320 |
| - |
321 | 314 | private static Name resolveName(ExpressionTree tree) {
|
322 | 315 | if (tree instanceof IdentifierTree) {
|
323 | 316 | return ((IdentifierTree) tree).getName();
|
@@ -345,76 +338,85 @@ private static ParsedRequiresPermission parseIntentAction(MethodInvocationTree t
|
345 | 338 |
|
346 | 339 | private static ParsedRequiresPermission parseBroadcastSourceRequiresPermission(
|
347 | 340 | MethodInvocationTree methodTree, VisitorState state) {
|
348 |
| - final ExpressionTree arg = findArgumentByParameterName(methodTree, |
349 |
| - (name) -> name.toLowerCase().contains("intent")); |
350 |
| - if (arg instanceof IdentifierTree) { |
351 |
| - final Name argName = ((IdentifierTree) arg).getName(); |
352 |
| - final MethodTree method = state.findEnclosing(MethodTree.class); |
353 |
| - final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>(); |
354 |
| - method.accept(new TreeScanner<Void, Void>() { |
355 |
| - private ParsedRequiresPermission last; |
356 |
| - |
357 |
| - @Override |
358 |
| - public Void visitMethodInvocation(MethodInvocationTree tree, Void param) { |
359 |
| - if (Objects.equal(methodTree, tree)) { |
360 |
| - res.set(last); |
361 |
| - } else { |
362 |
| - final Name name = resolveName(tree.getMethodSelect()); |
363 |
| - if (Objects.equal(argName, name) |
364 |
| - && INTENT_SET_ACTION.matches(tree, state)) { |
365 |
| - last = parseIntentAction(tree); |
| 341 | + if (methodTree.getArguments().size() < 1) { |
| 342 | + return null; |
| 343 | + } |
| 344 | + final ExpressionTree arg = methodTree.getArguments().get(0); |
| 345 | + if (!(arg instanceof IdentifierTree)) { |
| 346 | + return null; |
| 347 | + } |
| 348 | + final Name argName = ((IdentifierTree) arg).getName(); |
| 349 | + final MethodTree method = state.findEnclosing(MethodTree.class); |
| 350 | + final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>(); |
| 351 | + method.accept(new TreeScanner<Void, Void>() { |
| 352 | + private ParsedRequiresPermission mLast; |
| 353 | + |
| 354 | + @Override |
| 355 | + public Void visitMethodInvocation(MethodInvocationTree tree, Void param) { |
| 356 | + if (Objects.equal(methodTree, tree)) { |
| 357 | + res.set(mLast); |
| 358 | + } else { |
| 359 | + final Name name = resolveName(tree.getMethodSelect()); |
| 360 | + if (Objects.equal(argName, name) && INTENT_SET_ACTION.matches(tree, state)) { |
| 361 | + mLast = parseIntentAction(tree); |
| 362 | + } else if (name == null && tree.getMethodSelect() instanceof MemberSelectTree) { |
| 363 | + ExpressionTree innerTree = |
| 364 | + ((MemberSelectTree) tree.getMethodSelect()).getExpression(); |
| 365 | + if (innerTree instanceof JCNewClass) { |
| 366 | + mLast = parseIntentAction((NewClassTree) innerTree); |
366 | 367 | }
|
367 | 368 | }
|
368 |
| - return super.visitMethodInvocation(tree, param); |
369 | 369 | }
|
| 370 | + return super.visitMethodInvocation(tree, param); |
| 371 | + } |
370 | 372 |
|
371 |
| - @Override |
372 |
| - public Void visitAssignment(AssignmentTree tree, Void param) { |
373 |
| - final Name name = resolveName(tree.getVariable()); |
374 |
| - final Tree init = tree.getExpression(); |
375 |
| - if (Objects.equal(argName, name) |
376 |
| - && init instanceof NewClassTree) { |
377 |
| - last = parseIntentAction((NewClassTree) init); |
378 |
| - } |
379 |
| - return super.visitAssignment(tree, param); |
| 373 | + @Override |
| 374 | + public Void visitAssignment(AssignmentTree tree, Void param) { |
| 375 | + final Name name = resolveName(tree.getVariable()); |
| 376 | + final Tree init = tree.getExpression(); |
| 377 | + if (Objects.equal(argName, name) && init instanceof NewClassTree) { |
| 378 | + mLast = parseIntentAction((NewClassTree) init); |
380 | 379 | }
|
| 380 | + return super.visitAssignment(tree, param); |
| 381 | + } |
381 | 382 |
|
382 |
| - @Override |
383 |
| - public Void visitVariable(VariableTree tree, Void param) { |
384 |
| - final Name name = tree.getName(); |
385 |
| - final ExpressionTree init = tree.getInitializer(); |
386 |
| - if (Objects.equal(argName, name) |
387 |
| - && init instanceof NewClassTree) { |
388 |
| - last = parseIntentAction((NewClassTree) init); |
389 |
| - } |
390 |
| - return super.visitVariable(tree, param); |
| 383 | + @Override |
| 384 | + public Void visitVariable(VariableTree tree, Void param) { |
| 385 | + final Name name = tree.getName(); |
| 386 | + final ExpressionTree init = tree.getInitializer(); |
| 387 | + if (Objects.equal(argName, name) && init instanceof NewClassTree) { |
| 388 | + mLast = parseIntentAction((NewClassTree) init); |
391 | 389 | }
|
392 |
| - }, null); |
393 |
| - return res.get(); |
394 |
| - } |
395 |
| - return null; |
| 390 | + return super.visitVariable(tree, param); |
| 391 | + } |
| 392 | + }, null); |
| 393 | + return res.get(); |
396 | 394 | }
|
397 | 395 |
|
398 | 396 | private static ParsedRequiresPermission parseBroadcastTargetRequiresPermission(
|
399 | 397 | MethodInvocationTree tree, VisitorState state) {
|
400 |
| - final ExpressionTree arg = findArgumentByParameterName(tree, |
401 |
| - (name) -> name.toLowerCase().contains("permission")); |
402 | 398 | final ParsedRequiresPermission res = new ParsedRequiresPermission();
|
403 |
| - if (arg != null) { |
404 |
| - arg.accept(new TreeScanner<Void, Void>() { |
405 |
| - @Override |
406 |
| - public Void visitIdentifier(IdentifierTree tree, Void param) { |
407 |
| - res.addConstValue(tree); |
408 |
| - return super.visitIdentifier(tree, param); |
409 |
| - } |
410 |
| - |
411 |
| - @Override |
412 |
| - public Void visitMemberSelect(MemberSelectTree tree, Void param) { |
413 |
| - res.addConstValue(tree); |
414 |
| - return super.visitMemberSelect(tree, param); |
415 |
| - } |
416 |
| - }, null); |
| 399 | + int permission_position = 1; |
| 400 | + if (SEND_BROADCAST_AS_USER.matches(tree, state)) { |
| 401 | + permission_position = 2; |
417 | 402 | }
|
| 403 | + if (tree.getArguments().size() < permission_position + 1) { |
| 404 | + return res; |
| 405 | + } |
| 406 | + final ExpressionTree arg = tree.getArguments().get(permission_position); |
| 407 | + arg.accept(new TreeScanner<Void, Void>() { |
| 408 | + @Override |
| 409 | + public Void visitIdentifier(IdentifierTree tree, Void param) { |
| 410 | + res.addConstValue(tree); |
| 411 | + return super.visitIdentifier(tree, param); |
| 412 | + } |
| 413 | + |
| 414 | + @Override |
| 415 | + public Void visitMemberSelect(MemberSelectTree tree, Void param) { |
| 416 | + res.addConstValue(tree); |
| 417 | + return super.visitMemberSelect(tree, param); |
| 418 | + } |
| 419 | + }, null); |
418 | 420 | return res;
|
419 | 421 | }
|
420 | 422 |
|
|
0 commit comments