mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Python: More precise dataflow for tuples
(and dictionaries, but that is not fleshed out)
This commit is contained in:
@@ -230,13 +230,35 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
// `[..., 42, ...]`
|
||||
// nodeFrom is `42`, cfg node
|
||||
// nodeTo is the sequence, say `[..., 42, ...]`, cfg node
|
||||
nodeTo.(CfgNode).getNode().(SequenceNode).getAnElement() = nodeFrom.(CfgNode).getNode()
|
||||
//
|
||||
// List
|
||||
nodeTo.(CfgNode).getNode().(ListNode).getAnElement() = nodeFrom.(CfgNode).getNode() and
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
// Tuple
|
||||
exists(int n |
|
||||
nodeTo.(CfgNode).getNode().(TupleNode).getNode().(Tuple).getElt(n) = nodeFrom.(CfgNode).getNode().getNode() and
|
||||
c.(TupleElementContent).getIndex() = n and
|
||||
nodeFrom.(CfgNode).getNode().(NameNode).getId() = "SOURCE"
|
||||
)
|
||||
or
|
||||
//
|
||||
// Comprehension
|
||||
// `[x+1 for x in l]`
|
||||
// nodeFrom is `x+1`, cfg node
|
||||
// nodeTo is `[x+1 for x in l]`, cfg node
|
||||
nodeTo.(CfgNode).getNode().getNode().(Comp).getElt() = nodeFrom.(CfgNode).getNode().getNode()
|
||||
//
|
||||
// List
|
||||
nodeTo.(CfgNode).getNode().getNode().(ListComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
// Set
|
||||
nodeTo.(CfgNode).getNode().getNode().(SetComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
|
||||
c instanceof SetElementContent
|
||||
or
|
||||
// Dictionary
|
||||
nodeTo.(CfgNode).getNode().getNode().(DictComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
|
||||
c instanceof DictionaryElementAnyContent
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +269,18 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
// `l[3]`
|
||||
// nodeFrom is `l`, cfg node
|
||||
// nodeTo is `l[3]`, cfg node
|
||||
nodeFrom.(CfgNode).getNode() = nodeTo.(CfgNode).getNode().(SubscriptNode).getObject()
|
||||
nodeFrom.(CfgNode).getNode() = nodeTo.(CfgNode).getNode().(SubscriptNode).getObject() and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
or
|
||||
c instanceof DictionaryElementAnyContent
|
||||
or
|
||||
c.(TupleElementContent).getIndex() = nodeTo.(CfgNode).getNode().(SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
|
||||
or
|
||||
c.(DictionaryElementContent).getKey() = nodeTo.(CfgNode).getNode().(SubscriptNode).getIndex().getNode().(StrConst).getS()
|
||||
)
|
||||
or
|
||||
// set.pop
|
||||
// `s.pop()`
|
||||
@@ -257,7 +290,12 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
call.getFunction() = a and
|
||||
a.getName() = "pop" and // TODO: Should be made more robust, like Value::named("set.pop").getACall()
|
||||
nodeFrom.(CfgNode).getNode() = a.getObject() and
|
||||
nodeTo.(CfgNode).getNode() = call
|
||||
nodeTo.(CfgNode).getNode() = call and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
)
|
||||
)
|
||||
or
|
||||
// Comprehension
|
||||
|
||||
@@ -145,6 +145,58 @@ class BarrierGuard extends Expr {
|
||||
/**
|
||||
* A reference contained in an object. This is either a field or a property.
|
||||
*/
|
||||
class Content extends string {
|
||||
Content() { this = "Content" }
|
||||
newtype TContent =
|
||||
/** An element of a list. */
|
||||
TListElementContent() or
|
||||
/** An element of a set. */
|
||||
TSetElementContent() or
|
||||
/** An element of a tuple at a specifik index. */
|
||||
TTupleElementContent(int index) { exists(IntegerLiteral lit | lit.getValue() = index) } or
|
||||
/** An element of a dictionary under a specific key. */
|
||||
TDictionaryElementContent(string key) { exists(StrConst s | s.getS() = key ) } or
|
||||
/** An element of a dictionary at any key. */
|
||||
TDictionaryElementAnyContent()
|
||||
|
||||
class Content extends TContent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Content" }
|
||||
}
|
||||
|
||||
class ListElementContent extends TListElementContent, Content {
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "List element" }
|
||||
}
|
||||
|
||||
class SetElementContent extends TSetElementContent, Content {
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "Set element" }
|
||||
}
|
||||
|
||||
class TupleElementContent extends TTupleElementContent, Content {
|
||||
int index;
|
||||
|
||||
TupleElementContent() { this = TTupleElementContent(index) }
|
||||
|
||||
/** Gets the index for this tuple element */
|
||||
int getIndex() { result = index }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "Tuple element at " + index.toString() }
|
||||
}
|
||||
|
||||
class DictionaryElementContent extends TDictionaryElementContent, Content {
|
||||
string key;
|
||||
|
||||
DictionaryElementContent() { this = TDictionaryElementContent(key) }
|
||||
|
||||
/** Gets the index for this tuple element */
|
||||
string getKey() { result = key }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "Dictionary element at " + key }
|
||||
}
|
||||
|
||||
class DictionaryElementAnyContent extends TDictionaryElementAnyContent, Content {
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "Any dictionary element" }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user