Skip to content

Conversation

@Nishthajain7
Copy link

Purpose / Description

Add a new Lint rule (OpenInputStreamSafeDetector) that enforces the use of openInputStreamSafe().

Fixes

Approach

Reports the UnsafeOpenInputStream issue and provides a quick-fix to replace the call with openInputStreamSafe().

How Has This Been Tested?

Added unit tests for the same

Checklist

Please, go through these checks before submitting the PR.

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@welcome
Copy link

welcome bot commented Dec 4, 2025

First PR! 🚀 We sincerely appreciate that you have taken the time to propose a change to AnkiDroid! Please have patience with us as we are all volunteers - we will get to this as soon as possible.

) {
// Check if this is ContentResolver.openInputStream()
val evaluator = context.evaluator
if (!evaluator.isMemberInClass(method, "android.content.ContentResolver")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this, can you explain it with a comment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it and lint still passed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I added it just in case someone later adds another class with an openInputStream() method in the codebase. The lint rule won't incorrectly flag it. Should I remove it to make the code more readable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh. This would be clearer if tested

Index: lint-rules/src/main/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetector.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetector.kt b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetector.kt
--- a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetector.kt	(revision 4fe93f1558f3ce22717c9dc5c72973c15ad68fec)
+++ b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetector.kt	(date 1765125080450)
@@ -50,13 +50,8 @@
         node: UCallExpression,
         method: PsiMethod,
     ) {
-        // Check if this is ContentResolver.openInputStream()
-        // The evaluator checks if this method is a member of "android.content.ContentResolver".
-        // If it's not (e.g., it's some custom class's openInputStream), we ignore it and return early.
-        val evaluator = context.evaluator
-        if (!evaluator.isMemberInClass(method, "android.content.ContentResolver")) {
-            return
-        }
+        // Only warn on ContentResolver.openInputStream()
+        if (!context.evaluator.isMemberInClass(method, "android.content.ContentResolver")) return
 
         context.report(
             issue = ISSUE,

Comment on lines +44 to +45
contentResolverStub,
uriStub,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These stubs provide fake Android classes for the test environment. Without them, the lint detector wouldn't know what ContentResolver or Uri are, and couldn't check if openInputStream() belongs to the android.content.ContentResolver class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This passes

Index: lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt b/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt
--- a/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt	(revision a7e7533b8af81829e5d940559c77442272219534)
+++ b/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt	(date 1764850400435)
@@ -9,40 +9,12 @@
 
 @RunWith(JUnit4::class)
 class OpenInputStreamSafeDetectorTest {
-    // Stub files for Android classes needed by the tests
-    private val contentResolverStub =
-        java(
-            """
-        package android.content;
-        
-        import android.net.Uri;
-        import java.io.InputStream;
-        
-        public abstract class ContentResolver {
-            public final InputStream openInputStream(Uri uri) {
-                return null;
-            }
-        }
-        """,
-        ).indented()
-
-    private val uriStub =
-        java(
-            """
-        package android.net;
-        
-        public abstract class Uri {
-        }
-        """,
-        ).indented()
 
     @Test
     fun testDirectOpenInputStreamCall() {
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 kotlin(
                     """
                     class MyClass {
@@ -62,8 +34,6 @@
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 kotlin(
                     """
                     class MyClass {
@@ -83,8 +53,6 @@
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 java(
                     """
                     public class MyClass {
@@ -104,8 +72,6 @@
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 kotlin(
                     """
                     class MyClass {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still pending

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests fail without those lines

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works fine here, how are you testing?

Screenshot 2025-12-09 at 13 47 06
Index: lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt b/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt
--- a/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt	(revision 5f313280ebc06bb23f1bc3419d6bd0577458147a)
+++ b/lint-rules/src/test/java/com/ichi2/anki/lint/rules/OpenInputStreamSafeDetectorTest.kt	(date 1765262787110)
@@ -9,40 +9,12 @@
 
 @RunWith(JUnit4::class)
 class OpenInputStreamSafeDetectorTest {
-    // Stub files for Android classes needed by the tests
-    private val contentResolverStub =
-        java(
-            """
-        package android.content;
-        
-        import android.net.Uri;
-        import java.io.InputStream;
-        
-        public abstract class ContentResolver {
-            public final InputStream openInputStream(Uri uri) {
-                return null;
-            }
-        }
-        """,
-        ).indented()
-
-    private val uriStub =
-        java(
-            """
-        package android.net;
-        
-        public abstract class Uri {
-        }
-        """,
-        ).indented()
 
     @Test
     fun testDirectOpenInputStreamCall() {
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 kotlin(
                     """
                     class MyClass {
@@ -62,8 +34,6 @@
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 kotlin(
                     """
                     class MyClass {
@@ -83,8 +53,6 @@
         lint()
             .allowMissingSdk()
             .files(
-                contentResolverStub,
-                uriStub,
                 java(
                     """
                     public class MyClass {

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Dec 4, 2025
@david-allison
Copy link
Member

CI is failing. Comments haven't been answered

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup commits need work, and the merge commit needs removing, but I can do this post-approval.

One improvement with the test, then good to go

Thanks so much!!!!

@david-allison david-allison added Needs Review Needs Author Reply Waiting for a reply from the original author and removed Needs Author Reply Waiting for a reply from the original author labels Dec 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs Author Reply Waiting for a reply from the original author Needs Review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a lint rule for openInputStreamSafe

2 participants