-
Notifications
You must be signed in to change notification settings - Fork 355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spurious resource leak report when returning before a variable's definition #6317
Comments
Did some quick investigation here. Something seems to be going on where when we remove the first early return block, the resource leak store (i.e., the called methods store) holds the fact that close() is always called on r1 at the normal exit of the method. My guess is the first early return block leads to a control-flow merge just before the normal exit, such that the Where I am lost is that I don't understand why we don't report a warning even without the first early return block. For this version of the code: void method() throws IOException {
Closeable r1 = alloc();
if (r1 == null) {
return;
}
r1.close();
} Reasoning that this code is safe requires knowing that at the explicit |
Ok, upon further investigation I found the code that refines the type of Line 766 in 49d97d7
So now I think the issue is in how we handle the control-flow merge resulting from the first explicit checker-framework/framework/src/main/java/org/checkerframework/framework/flow/CFAbstractStore.java Lines 1173 to 1174 in 49d97d7
In this case, I don't think this comment captures what we want to do. The first early @smillst @mernst have you seen this issue come up before? Is there a way we can tweak the Called Methods Checker to get this desired behavior? |
@msridhar I also did a little investigating. I'm not sure if this will be useful, but here are some disorganized thoughts. My original diagnosis might not have been right. The test case is very brittle. You can also, surprisingly, silence the error by removing the second if-check: if (r1 == null) {
return;
} So I might have been wrong when I wrote "the RLC wants us to close r1 at the premature return site, before it has been defined". Instead, I now believe that there's some other explanation, and that you figured it out:
But, I have a different idea about the fix. Here's the relevant part of the CFG: The conditional block at the top of the picture corresponds to the second if-check in the original code. The error is reported when There's a piece of true information that is not shown the CFG:
But that information is lost. As you noted, Instead of making a sweeping change like
maybe a simpler fix is to write a method that can tell us what information flows along a certain edge. Such a method might obviate a lot of complex and subtle logic in Lines 2098 to 2099 in 43db447
Ideally, I think all that complex logic could be replaced with something extremely simple: var mcStore = mcAtf.getAnalysisResult().getStoreAlongEdge(currentBlock, successor);
var cmStore = analysis.getResult().getStoreAlongEdge(currentBlock, successor); |
Very interesting @Calvin-L. I'll have to digest more but your proposed solution sounds a lot simpler and cleaner than what I was thinking. |
Looking more I think this is the right idea here. The problem in this case is that when doing a consistency check for the CFG edge from a conditional block to the exit block, we use As to adding a Lines 2145 to 2148 in 43db447
But I think that will go away as part of #6221. |
FYI I have a WIP branch investigating a fix to this issue here: https://github.com/msridhar/checker-framework/tree/issue-6317 Still too hacky and not everything is working as I expect, but I think (hope?) it's on the right track. |
Given this code:
The RLC reports
The error looks spurious. Indeed, removing the early return block
silences the warning! It appears that the RLC wants us to close
r1
at the premature return site, before it has been defined.The text was updated successfully, but these errors were encountered: