java:S2095 misses unclosed resources after trivial helper-method calls

Product: SonarQube Community (self-hosted)
sonar-java version: sonar-java 8.28.0.43176 on SonarQube Community Build 26.4.0.121862
Java source level: 21 (javac 21, source/target 17)

Rule

java:S2095 — Resources should be closed

Description

S2095 stops reporting an unclosed InputStream once it is passed to a helper method, even though the helper neither closes nor takes ownership of the resource. The stream still leaks, but the analyzer appears to treat any method call as potential resource management.

Reproducer

// BEFORE — S2095 correctly reported on `new FileInputStream(path)`
package demo.before;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamLeak {
    public static void process(String path) throws IOException {
        InputStream in = new FileInputStream(path);
        int firstByte = in.read();
        System.out.println("First byte: " + firstByte);
    }
}
// AFTER — S2095 no longer reported, but the stream is still leaked
package demo.after;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamLeak {
    public static void process(String path) throws IOException {
        InputStream in = new FileInputStream(path);
        int firstByte = readFirstByte(in);      // helper does not close `in`
        System.out.println("First byte: " + firstByte);
    }

    private static int readFirstByte(InputStream in) throws IOException {
        return in.read();
    }
}

Hello @Emilyaxe,

Thank you for the detailed report.

What you describe here is the expected behaviour for this rule. Whenever a resource is passed as argument to a method that is not explicitly known to keep the resource it consumes open, the rule conservatively avoids reporting an issue.
In your example, it is obvious that the method being called on the resource does not close its argument. However, in the more general case, if the implementation of the method is unknown, we cannot definitively say if the resource will be closed or not.

I hope this answers any questions you might have. If not, don’t hesitate to reply here.

Best regards,
Aurélien

Thank you for your reply and the detailed explanation. I will avoid constructing test cases in this manner, i.e., extracting the code into a separate function for testing.

Best regards.