From 850f8aa4d96544d533c45f60bb8e91859f50baf3 Mon Sep 17 00:00:00 2001 From: Ashwini Oruganti Date: Tue, 4 May 2021 16:49:12 -0700 Subject: [PATCH] Extend errorprone checks for unattributed calls Support warnings for the following methods as well: noteOpNoThrow startOp startOpNoThrow noteProxyOp noteProxyOpNoThrow finishOp Bug: 186785930 Test: atest error_prone_android_framework_test:com.google.errorprone.bugpatterns.android.UnattributedNoteOpCallCheckerTest Change-Id: I3a30f32cfb48a20b90682b28b709b086b8bb6b35 --- .../UnattributedNoteOpCallChecker.java | 91 ++++++++++++++ .../UnattributedNoteOpCallCheckerTest.java | 119 ++++++++++++++++++ .../tests/res/android/app/AppOpsManager.java | 65 ++++++++++ 3 files changed, 275 insertions(+) diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java index d39978f54ebc8..3d7b94f880ac6 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java @@ -47,6 +47,54 @@ public final class UnattributedNoteOpCallChecker extends BugChecker private static final Matcher UNATTRIBUTED_NOTEOP_CALL_3 = methodInvocation( instanceMethod().onExactClass("android.app.AppOpsManager") .withSignature("noteOp(int)")); + private static final Matcher UNATTRIBUTED_NOTEOPNOTHROW_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteOpNoThrow(int,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEOPNOTHROW_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteOpNoThrow(java.lang.String,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_STARTOP_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOp(java.lang.String,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_STARTOP_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOp(int,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_STARTOP_CALL_3 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOp(int)")); + private static final Matcher UNATTRIBUTED_STARTOP_CALL_4 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOp(int,int,java.lang.String,boolean)")); + private static final Matcher UNATTRIBUTED_STARTOPNOTHROW_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOpNoThrow(java.lang.String,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_STARTOPNOTHROW_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOpNoThrow(int,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_STARTOPNOTHROW_CALL_3 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("startOpNoThrow(int,int,java.lang.String,boolean)")); + private static final Matcher UNATTRIBUTED_NOTEPROXYOP_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteProxyOp(java.lang.String,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEPROXYOP_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteProxyOp(int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEPROXYOPNOTHROW_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteProxyOpNoThrow(java.lang.String,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEPROXYOPNOTHROW_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteProxyOpNoThrow(java.lang.String,java.lang.String,int)")); + private static final Matcher UNATTRIBUTED_FINISHOP_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("finishOp(int)")); + private static final Matcher UNATTRIBUTED_FINISHOP_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("finishOp(java.lang.String,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_FINISHOP_CALL_3 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("finishOp(int,int,java.lang.String)")); @Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { @@ -57,6 +105,49 @@ public final class UnattributedNoteOpCallChecker extends BugChecker .setMessage("Unattributed noteOp call! Please use noteOp(int, String, String, String) or noteOp(int, CallerIdentity)") .build(); } + if (UNATTRIBUTED_NOTEOPNOTHROW_CALL_1.matches(tree, state) + || UNATTRIBUTED_NOTEOPNOTHROW_CALL_2.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed noteOpNoThrow call! Please use noteOpNoThrow(String, int, String, String, String)") + .build(); + } + if (UNATTRIBUTED_STARTOP_CALL_1.matches(tree, state) + || UNATTRIBUTED_STARTOP_CALL_2.matches(tree, state) + || UNATTRIBUTED_STARTOP_CALL_3.matches(tree, state) + || UNATTRIBUTED_STARTOP_CALL_4.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed startOp call! Please use startOp(int, int, String, boolean, String, String)") + .build(); + } + if (UNATTRIBUTED_STARTOPNOTHROW_CALL_1.matches(tree, state) + || UNATTRIBUTED_STARTOPNOTHROW_CALL_2.matches(tree, state) + || UNATTRIBUTED_STARTOPNOTHROW_CALL_3.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed startOpNoThrow call!") + .build(); + } + if (UNATTRIBUTED_NOTEPROXYOP_CALL_1.matches(tree, state) + || UNATTRIBUTED_NOTEPROXYOP_CALL_2.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed noteProxyOp call!") + .build(); + } + if (UNATTRIBUTED_NOTEPROXYOPNOTHROW_CALL_1.matches(tree, state) + || UNATTRIBUTED_NOTEPROXYOPNOTHROW_CALL_2.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed noteProxyOpNoThrow call!") + .build(); + } + if (UNATTRIBUTED_FINISHOP_CALL_1.matches(tree, state) + || UNATTRIBUTED_FINISHOP_CALL_2.matches(tree, state) + || UNATTRIBUTED_FINISHOP_CALL_3.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed finishOp call!") + .build(); + } + + + return Description.NO_MATCH; } } diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java index 4a559c205ca6f..9a98c7c2d4c95 100644 --- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java +++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java @@ -54,4 +54,123 @@ public class UnattributedNoteOpCallCheckerTest { "}") .doTest(); } + + @Test + public void testNoteOpNoThrow() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.noteOpNoThrow(0, 1, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteOpNoThrow(\"foo\", 1, \"bar\");", + " }", + "}") + .doTest(); + } + + @Test + public void testStartOp() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.startOp(0, 0, \"bar\", true);", + " // BUG: Diagnostic contains:", + " mAppOps.startOp(1, 2, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.startOp(\"foo\", 1, \"bar\");", + " // BUG: Diagnostic contains:", + " mAppOps.startOp(1);", + " }", + "}") + .doTest(); + } + + @Test + public void testStartOpNoThrow() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.startOpNoThrow(0, 0, \"bar\", true);", + " // BUG: Diagnostic contains:", + " mAppOps.startOpNoThrow(1, 2, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.startOpNoThrow(\"foo\", 1, \"bar\");", + " }", + "}") + .doTest(); + } + + @Test + public void testNoteProxyOp() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.noteProxyOp(1, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteProxyOp(\"foo\", \"bar\");", + " }", + "}") + .doTest(); + } + + @Test + public void testNoteProxyOpNoThrow() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.noteProxyOpNoThrow(\"foo\", \"bar\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteProxyOpNoThrow(\"foo\", \"bar\", 1);", + " }", + "}") + .doTest(); + } + + @Test + public void testFinishOp() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " // BUG: Diagnostic contains:", + " mAppOps.finishOp(1, 2, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.finishOp(\"foo\", 1, \"bar\");", + " // BUG: Diagnostic contains:", + " mAppOps.finishOp(1);", + " }", + "}") + .doTest(); + } + + + } diff --git a/errorprone/tests/res/android/app/AppOpsManager.java b/errorprone/tests/res/android/app/AppOpsManager.java index cccdfd8eb9336..216270cb65d7d 100644 --- a/errorprone/tests/res/android/app/AppOpsManager.java +++ b/errorprone/tests/res/android/app/AppOpsManager.java @@ -39,4 +39,69 @@ public class AppOpsManager { String attributionTag, String message) { throw new UnsupportedOperationException(); } + + public int noteOpNoThrow(String op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int noteOpNoThrow(int op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int startOp(int op) { + throw new UnsupportedOperationException(); + } + + public int startOp(int op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) { + throw new UnsupportedOperationException(); + } + + public int startOp(String op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int startOpNoThrow(String op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int startOpNoThrow(int op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) { + throw new UnsupportedOperationException(); + } + + public int noteProxyOp(String op, String proxiedPackageName) { + throw new UnsupportedOperationException(); + } + + public int noteProxyOp(int op, String proxiedPackageName) { + throw new UnsupportedOperationException(); + } + + public int noteProxyOpNoThrow(String op, String proxiedPackageName) { + throw new UnsupportedOperationException(); + } + + public int noteProxyOpNoThrow(String op, String proxiedPackageName, + int proxiedUid) { + throw new UnsupportedOperationException(); + } + + public void finishOp(int op) { + throw new UnsupportedOperationException(); + } + + public void finishOp(String op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public void finishOp(int op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } }