-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Python: Add jump steps for global variable nested field access #20162
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
base: main
Are you sure you want to change the base?
Changes from all commits
4ab9283
104e20e
a1b1021
1c4a48e
8617ba2
11185c3
7fa224c
2a0431f
485f397
c9f495e
a2edf10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
category: minorAnalysis | ||
--- | ||
* Data flow tracking through global variables now supports nested field access patterns such as `global_var.obj.field`. This improves the precision of taint tracking analysis when data flows through complex global variable structures. |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -556,6 +556,57 @@ predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) { | |||||||||||||
nodeFrom.asCfgNode() = param.getDefault() and | ||||||||||||||
nodeTo.asCfgNode() = param.getDefiningNode() | ||||||||||||||
) | ||||||||||||||
or | ||||||||||||||
// Enhanced global variable field access tracking | ||||||||||||||
globalVariableNestedFieldJumpStep(nodeFrom, nodeTo) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* Holds if there is a jump step from `nodeFrom` to `nodeTo` through global variable field access. | ||||||||||||||
* This supports tracking nested object field access through global variables like `app.obj.foo`. | ||||||||||||||
*/ | ||||||||||||||
private predicate globalVariableNestedFieldJumpStep(Node nodeFrom, Node nodeTo) { | ||||||||||||||
exists(ModuleVariableNode globalVar, AttrWrite write, AttrRead read | | ||||||||||||||
// Match writes and reads on the same global variable attribute path | ||||||||||||||
exists(string accessPath | | ||||||||||||||
globalVariableAttrPathAtDepth(globalVar, accessPath, write.getObject(), _) and | ||||||||||||||
globalVariableAttrPathAtDepth(globalVar, accessPath, read.getObject(), _) | ||||||||||||||
) and | ||||||||||||||
write.getAttributeName() = read.getAttributeName() and | ||||||||||||||
nodeFrom = write.getValue() and | ||||||||||||||
nodeTo = read | ||||||||||||||
) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* Maximum depth for global variable nested attribute access. | ||||||||||||||
* Depth 1 = globalVar.foo, depth 2 = globalVar.foo.bar, depth 3 = globalVar.foo.bar.baz, etc. | ||||||||||||||
*/ | ||||||||||||||
private int getMaxGlobalVariableDepth() { result = 2 } | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* Holds if `node` is an attribute access path starting from global variable `globalVar` at specific `depth`. | ||||||||||||||
*/ | ||||||||||||||
private predicate globalVariableAttrPathAtDepth( | ||||||||||||||
ModuleVariableNode globalVar, string accessPath, Node node, int depth | ||||||||||||||
) { | ||||||||||||||
// Base case: Direct global variable access (depth 0) | ||||||||||||||
depth = 0 and | ||||||||||||||
// We use `globalVar` instead of `globalVar.getAWrite()` due to some weirdness with how | ||||||||||||||
// attribute writes are handled in the global scope (see `GlobalAttributeAssignmentAsAttrWrite`). | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment mentions 'some weirdness' which is too vague. Consider explaining the specific technical reason why
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||
node in [globalVar.getARead(), globalVar] and | ||||||||||||||
accessPath = "" | ||||||||||||||
or | ||||||||||||||
exists(Node obj, string attrName, string parentAccessPath, int parentDepth | | ||||||||||||||
node.(AttrRead).reads(obj, attrName) | ||||||||||||||
or | ||||||||||||||
any(AttrWrite aw).writes(obj, attrName, node) | ||||||||||||||
| | ||||||||||||||
globalVariableAttrPathAtDepth(globalVar, parentAccessPath, obj, parentDepth) and | ||||||||||||||
accessPath = parentAccessPath + "." + attrName and | ||||||||||||||
depth = parentDepth + 1 and | ||||||||||||||
depth <= getMaxGlobalVariableDepth() | ||||||||||||||
) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
//-------- | ||||||||||||||
|
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The maximum depth is hardcoded to 2. Consider making this configurable through a parameter or constant that can be easily adjusted without modifying the predicate, especially since the feature description mentions 'configurable depth limit'.
Copilot uses AI. Check for mistakes.