Fix FP for py/modification-of-locals

This commit is contained in:
Owen Mansel-Chan
2026-06-17 14:24:18 +01:00
parent 47c2c9e763
commit dd61dd2d74
3 changed files with 15 additions and 8 deletions

View File

@@ -13,9 +13,19 @@
import python
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.DataFlow
predicate originIsLocals(ControlFlowNode n) {
API::builtin("locals").getReturn().getAValueReachableFromSource().asCfgNode() = n
// Only consider the `locals()` dictionary within the scope that called `locals()`.
// Once the dictionary is passed to another scope (e.g. as an argument or via an
// instance attribute) it is just an ordinary mapping, and modifying it is both
// meaningful and effective. Restricting to local (intraprocedural) flow ensures we
// only report modifications in the scope where the `locals()` gotcha actually applies.
exists(DataFlow::LocalSourceNode src, DataFlow::Node use |
src = API::builtin("locals").getReturn().asSource() and
src.flowsTo(use) and
use.asCfgNode() = n
)
}
predicate modification_of_locals(ControlFlowNode f) {

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `py/modification-of-locals` query no longer flags modifications of a `locals()` dictionary that has been passed out of the scope in which `locals()` was called (for example, by passing it to another function or storing it in an instance attribute). In such cases the dictionary is used as an ordinary mapping and modifying it is meaningful, so these were false positives. The "modification has no effect" claim only applies within the scope that called `locals()`, which is now the only case reported.

View File

@@ -3,10 +3,3 @@
| test.py:101:5:101:14 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:102:9:102:14 | Subscript | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:103:5:103:13 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:206:5:206:11 | Subscript | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:207:5:207:23 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:208:5:208:15 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:209:9:209:15 | Subscript | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:210:5:210:14 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:228:9:228:24 | Subscript | Modification of the locals() dictionary will have no effect on the local variables. |
| test.py:229:9:229:35 | Attribute() | Modification of the locals() dictionary will have no effect on the local variables. |