Update docs, precision, and deprecate old library

This commit is contained in:
Joe Farebrother
2025-03-10 13:14:44 +00:00
parent f750e22d91
commit f8a0b1c5f9
5 changed files with 34 additions and 33 deletions

View File

@@ -1,15 +0,0 @@
f = open("filename")
... # Actions to perform on file
f.close()
# File only closed if actions are completed successfully
with open("filename") as f:
...# Actions to perform on file
# File always closed
f = open("filename")
try:
... # Actions to perform on file
finally:
f.close()
# File always closed

View File

@@ -4,32 +4,27 @@
<qhelp>
<overview>
<p> If a file is opened then it should always be closed again, even if an
exception is raised.
Failing to ensure that all files are closed may result in failure due to too
many open files.</p>
<p>When a file is opened, it should always be closed. Failure to close files could result in loss of data or resource leaks.</p>
</overview>
<recommendation>
<p>Ensure that if you open a file it is always closed on exiting the method.
Wrap the code between the <code>open()</code> and <code>close()</code>
functions in a <code>with</code> statement or use a <code>try...finally</code>
statement. Using a <code>with</code> statement is preferred as it is shorter
and more readable.</p>
<p>Ensure that opened files are always closed, including when an exception could be raised.
The best practice is to use a <code>with</code> statement to automatically clean up resources.
Otherwise, ensure that <code>.close()</code> is called in a <code>try...except</code> or <code>try...finally</code>
block to handle any possible exceptions.
</p>
</recommendation>
<example>
<p>The following code shows examples of different ways of closing a file. In the first example, the
file is closed only if the method is exited successfully. In the other examples, the file is always
closed on exiting the method.</p>
<p>In the following examples, in the case marked BAD, the file may not be closed if an exception is raised. In the cases marked GOOD, the file is always closed.</p>
<sample src="FileNotAlwaysClosed.py" />
<sample src="examples/FileNotAlwaysClosed.py" />
</example>
<references>
<li>Python Documentation: <a href="https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files">Reading and writing files</a>.</li>
<li>Python Language Reference: <a href="http://docs.python.org/reference/compound_stmts.html#the-with-statement">The with statement</a>,
<a href="http://docs.python.org/reference/compound_stmts.html#the-try-statement">The try statement</a>.</li>
<li>Python PEP 343: <a href="http://www.python.org/dev/peps/pep-0343">The "with" Statement</a>.</li>

View File

@@ -1,6 +1,6 @@
/**
* @name File is not always closed
* @description Opening a file without ensuring that it is always closed may cause resource leaks.
* @description Opening a file without ensuring that it is always closed may cause data loss or resource leaks.
* @kind problem
* @tags efficiency
* correctness
@@ -8,7 +8,7 @@
* external/cwe/cwe-772
* @problem.severity warning
* @sub-severity high
* @precision medium
* @precision high
* @id py/file-not-closed
*/
@@ -21,5 +21,5 @@ where
msg = "File is opened but is not closed."
or
fileMayNotBeClosedOnException(fo, _) and
msg = "File may not be closed if an exception is raised"
msg = "File may not be closed if an exception is raised."
select fo.getLocalSource(), msg

View File

@@ -1,4 +1,8 @@
/** Contains predicates concerning when and where files are opened and closed. */
/**
* DEPRECATED: Use FileNotAlwaysClosedQuery instead.
* Contains predicates concerning when and where files are opened and closed.
*/
deprecated module;
import python
import semmle.python.pointsto.Filters

View File

@@ -0,0 +1,17 @@
def bad():
f = open("filename", "w")
f.write("could raise exception") # BAD: This call could raise an exception, leading to the file not being closed.
f.close()
def good1():
with open("filename", "w") as f:
f.write("always closed") # GOOD: The `with` statement ensures the file is always closed.
def good2():
f = open("filename", "w")
try:
f.write("always closed")
finally:
f.close() # GOOD: The `finally` block always ensures the file is closed.