From b881001b5b63c319cbac48acad4e643efa6f802f Mon Sep 17 00:00:00 2001 From: Ashwini Oruganti Date: Mon, 8 Mar 2021 16:53:49 -0800 Subject: [PATCH] Errorprone check for unattributed noteOp calls Bug: 182216007 Test: atest error_prone_android_framework_test:com.google.errorprone.bugpatterns.android.UnattributedNoteOpCallCheckerTest Change-Id: I338177ed4c10869725ba0d39c487a1ea923cd564 --- .../UnattributedNoteOpCallChecker.java | 62 +++++++++++++++++++ .../UnattributedNoteOpCallCheckerTest.java | 57 +++++++++++++++++ .../tests/res/android/app/AppOpsManager.java | 42 +++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java create mode 100644 errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java create mode 100644 errorprone/tests/res/android/app/AppOpsManager.java diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java new file mode 100644 index 0000000000000..d39978f54ebc8 --- /dev/null +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallChecker.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.bugpatterns.android; + +import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; +import static com.google.errorprone.matchers.Matchers.instanceMethod; +import static com.google.errorprone.matchers.Matchers.methodInvocation; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; + +@AutoService(BugChecker.class) +@BugPattern( + name = "AndroidFrameworkUnattributedNoteOpCall", + summary = "Verifies that a noteOp() call is attributed", + severity = WARNING) +public final class UnattributedNoteOpCallChecker extends BugChecker + implements MethodInvocationTreeMatcher { + + private static final Matcher UNATTRIBUTED_NOTEOP_CALL_1 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteOp(int,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEOP_CALL_2 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteOp(java.lang.String,int,java.lang.String)")); + private static final Matcher UNATTRIBUTED_NOTEOP_CALL_3 = methodInvocation( + instanceMethod().onExactClass("android.app.AppOpsManager") + .withSignature("noteOp(int)")); + + @Override + public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { + if (UNATTRIBUTED_NOTEOP_CALL_1.matches(tree, state) + || UNATTRIBUTED_NOTEOP_CALL_2.matches(tree, state) + || UNATTRIBUTED_NOTEOP_CALL_3.matches(tree, state)) { + return buildDescription(tree) + .setMessage("Unattributed noteOp call! Please use noteOp(int, String, String, String) or noteOp(int, CallerIdentity)") + .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 new file mode 100644 index 0000000000000..4a559c205ca6f --- /dev/null +++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/UnattributedNoteOpCallCheckerTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.bugpatterns.android; + +import com.google.errorprone.CompilationTestHelper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class UnattributedNoteOpCallCheckerTest { + private CompilationTestHelper mCompilationHelper; + + @Before + public void setUp() { + mCompilationHelper = CompilationTestHelper.newInstance( + UnattributedNoteOpCallChecker.class, getClass()); + } + + @Test + public void testNoteOp() { + mCompilationHelper + .addSourceFile("/android/app/AppOpsManager.java") + .addSourceLines("Example.java", + "import android.app.AppOpsManager;", + "public class Example {", + " void example() {", + " AppOpsManager mAppOps = new AppOpsManager();", + " mAppOps.noteOp(\"foo\", 0, \"bar\", \"baz\", \"qux\");", + " mAppOps.noteOp(0, 0, \"bar\", \"baz\", \"qux\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteOp(1, 2, \"foo\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteOp(\"foo\", 1, \"bar\");", + " // BUG: Diagnostic contains:", + " mAppOps.noteOp(1);", + " }", + "}") + .doTest(); + } +} diff --git a/errorprone/tests/res/android/app/AppOpsManager.java b/errorprone/tests/res/android/app/AppOpsManager.java new file mode 100644 index 0000000000000..cccdfd8eb9336 --- /dev/null +++ b/errorprone/tests/res/android/app/AppOpsManager.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +public class AppOpsManager { + + public int noteOp(String op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int noteOp(int op) { + throw new UnsupportedOperationException(); + } + + public int noteOp(int op, int uid, String packageName) { + throw new UnsupportedOperationException(); + } + + public int noteOp(String op, int uid, String packageName, + String attributionTag, String message) { + throw new UnsupportedOperationException(); + } + + public int noteOp(int op, int uid, String packageName, + String attributionTag, String message) { + throw new UnsupportedOperationException(); + } +}