mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Python: Autoformat
This commit is contained in:
@@ -170,227 +170,227 @@
|
||||
private import python
|
||||
private import DataFlowPublic
|
||||
|
||||
/**
|
||||
* The target of a `for`, e.g. `x` in `for x in list` or in `[42 for x in list]`.
|
||||
* This class also records the source, which in both above cases is `list`.
|
||||
* This class abstracts away the differing representations of comprehensions and
|
||||
* for statements.
|
||||
*/
|
||||
class ForTarget extends ControlFlowNode {
|
||||
Expr source;
|
||||
/**
|
||||
* The target of a `for`, e.g. `x` in `for x in list` or in `[42 for x in list]`.
|
||||
* This class also records the source, which in both above cases is `list`.
|
||||
* This class abstracts away the differing representations of comprehensions and
|
||||
* for statements.
|
||||
*/
|
||||
class ForTarget extends ControlFlowNode {
|
||||
Expr source;
|
||||
|
||||
ForTarget() {
|
||||
exists(For for |
|
||||
source = for.getIter() and
|
||||
this.getNode() = for.getTarget() and
|
||||
not for = any(Comp comp).getNthInnerLoop(0)
|
||||
)
|
||||
or
|
||||
exists(Comp comp |
|
||||
source = comp.getIterable() and
|
||||
this.getNode() = comp.getNthInnerLoop(0).getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
Expr getSource() { result = source }
|
||||
}
|
||||
|
||||
/** The LHS of an assignment, it also records the assigned value. */
|
||||
class AssignmentTarget extends ControlFlowNode {
|
||||
Expr value;
|
||||
|
||||
AssignmentTarget() {
|
||||
exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue())
|
||||
}
|
||||
|
||||
Expr getValue() { result = value }
|
||||
}
|
||||
|
||||
/** A direct (or top-level) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentDirectTarget extends ControlFlowNode {
|
||||
Expr value;
|
||||
|
||||
UnpackingAssignmentDirectTarget() {
|
||||
this instanceof SequenceNode and
|
||||
(
|
||||
value = this.(AssignmentTarget).getValue()
|
||||
or
|
||||
value = this.(ForTarget).getSource()
|
||||
)
|
||||
}
|
||||
|
||||
Expr getValue() { result = value }
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentTarget extends ControlFlowNode {
|
||||
UnpackingAssignmentTarget() {
|
||||
this instanceof UnpackingAssignmentDirectTarget
|
||||
or
|
||||
this = any(UnpackingAssignmentSequenceTarget parent).getAnElement()
|
||||
}
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
||||
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof SequenceNode {
|
||||
ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
||||
|
||||
ControlFlowNode getAnElement() { result = this.getElement(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1a
|
||||
* Data flows from `iterable` to `TIterableSequence(sequence)`
|
||||
*/
|
||||
predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(AssignmentTarget target |
|
||||
nodeFrom.asExpr() = target.getValue() and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
ForTarget() {
|
||||
exists(For for |
|
||||
source = for.getIter() and
|
||||
this.getNode() = for.getTarget() and
|
||||
not for = any(Comp comp).getNthInnerLoop(0)
|
||||
)
|
||||
or
|
||||
exists(Comp comp |
|
||||
source = comp.getIterable() and
|
||||
this.getNode() = comp.getNthInnerLoop(0).getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1b
|
||||
* Data is read from `iterable` to `TIterableSequence(sequence)`
|
||||
*/
|
||||
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ForTarget target |
|
||||
nodeFrom.asExpr() = target.getSource() and
|
||||
target instanceof SequenceNode and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
) and
|
||||
Expr getSource() { result = source }
|
||||
}
|
||||
|
||||
/** The LHS of an assignment, it also records the assigned value. */
|
||||
class AssignmentTarget extends ControlFlowNode {
|
||||
Expr value;
|
||||
|
||||
AssignmentTarget() {
|
||||
exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue())
|
||||
}
|
||||
|
||||
Expr getValue() { result = value }
|
||||
}
|
||||
|
||||
/** A direct (or top-level) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentDirectTarget extends ControlFlowNode {
|
||||
Expr value;
|
||||
|
||||
UnpackingAssignmentDirectTarget() {
|
||||
this instanceof SequenceNode and
|
||||
(
|
||||
value = this.(AssignmentTarget).getValue()
|
||||
or
|
||||
value = this.(ForTarget).getSource()
|
||||
)
|
||||
}
|
||||
|
||||
Expr getValue() { result = value }
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment. */
|
||||
class UnpackingAssignmentTarget extends ControlFlowNode {
|
||||
UnpackingAssignmentTarget() {
|
||||
this instanceof UnpackingAssignmentDirectTarget
|
||||
or
|
||||
this = any(UnpackingAssignmentSequenceTarget parent).getAnElement()
|
||||
}
|
||||
}
|
||||
|
||||
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
||||
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof SequenceNode {
|
||||
ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
||||
|
||||
ControlFlowNode getAnElement() { result = this.getElement(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1a
|
||||
* Data flows from `iterable` to `TIterableSequence(sequence)`
|
||||
*/
|
||||
predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(AssignmentTarget target |
|
||||
nodeFrom.asExpr() = target.getValue() and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1b
|
||||
* Data is read from `iterable` to `TIterableSequence(sequence)`
|
||||
*/
|
||||
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ForTarget target |
|
||||
nodeFrom.asExpr() = target.getSource() and
|
||||
target instanceof SequenceNode and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
) and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
* Data flows from `TIterableSequence(sequence)` to `sequence`
|
||||
*/
|
||||
predicate iterableUnpackingTupleFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo.asCfgNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
* Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`.
|
||||
* As `sequence` is modeled as a tuple, we will not read tuple content as that would allow
|
||||
* crosstalk.
|
||||
*/
|
||||
predicate iterableUnpackingConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo = TIterableElementNode(target) and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
// TODO: dict content in iterable unpacking not handled
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
* Data flows from `TIterableSequence(sequence)` to `sequence`
|
||||
*/
|
||||
predicate iterableUnpackingTupleFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo.asCfgNode() = target
|
||||
/**
|
||||
* Step 4
|
||||
* Data flows from `TIterableElement(sequence)` to `sequence`.
|
||||
* Content type is `TupleElementContent` with indices taken from the syntax.
|
||||
* For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2.
|
||||
*/
|
||||
predicate iterableUnpackingConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableElementNode(target) and
|
||||
nodeTo.asCfgNode() = target and
|
||||
exists(int index | exists(target.getElement(index)) |
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
* Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`.
|
||||
* As `sequence` is modeled as a tuple, we will not read tuple content as that would allow
|
||||
* crosstalk.
|
||||
*/
|
||||
predicate iterableUnpackingConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo = TIterableElementNode(target) and
|
||||
(
|
||||
c instanceof ListElementContent
|
||||
or
|
||||
c instanceof SetElementContent
|
||||
// TODO: dict content in iterable unpacking not handled
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4
|
||||
* Data flows from `TIterableElement(sequence)` to `sequence`.
|
||||
* Content type is `TupleElementContent` with indices taken from the syntax.
|
||||
* For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2.
|
||||
*/
|
||||
predicate iterableUnpackingConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableElementNode(target) and
|
||||
nodeTo.asCfgNode() = target and
|
||||
exists(int index | exists(target.getElement(index)) |
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 5
|
||||
* For a sequence node inside an iterable unpacking, data flows from the sequence to its elements. There are
|
||||
* three cases for what `toNode` should be:
|
||||
* a) If the element is a plain variable, `toNode` is the corresponding essa node.
|
||||
*
|
||||
* b) If the element is itself a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`.
|
||||
*
|
||||
* c) If the element is a starred variable, with control-flow node `v`, `toNode` is `TIterableElement(v)`.
|
||||
*/
|
||||
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex
|
||||
|
|
||||
target.getElement(starIndex) instanceof StarredNode
|
||||
or
|
||||
not exists(target.getAnElement().(StarredNode)) and
|
||||
starIndex = -1
|
||||
|
|
||||
nodeFrom.asCfgNode() = target and
|
||||
element = target.getElement(index) and
|
||||
(
|
||||
if starIndex = -1 or index < starIndex
|
||||
then c.(TupleElementContent).getIndex() = index
|
||||
else
|
||||
// This could get big if big tuples exist
|
||||
if index = starIndex
|
||||
then c.(TupleElementContent).getIndex() >= index
|
||||
else c.(TupleElementContent).getIndex() >= index - 1
|
||||
) and
|
||||
(
|
||||
if element instanceof SequenceNode
|
||||
/**
|
||||
* Step 5
|
||||
* For a sequence node inside an iterable unpacking, data flows from the sequence to its elements. There are
|
||||
* three cases for what `toNode` should be:
|
||||
* a) If the element is a plain variable, `toNode` is the corresponding essa node.
|
||||
*
|
||||
* b) If the element is itself a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`.
|
||||
*
|
||||
* c) If the element is a starred variable, with control-flow node `v`, `toNode` is `TIterableElement(v)`.
|
||||
*/
|
||||
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex
|
||||
|
|
||||
target.getElement(starIndex) instanceof StarredNode
|
||||
or
|
||||
not exists(target.getAnElement().(StarredNode)) and
|
||||
starIndex = -1
|
||||
|
|
||||
nodeFrom.asCfgNode() = target and
|
||||
element = target.getElement(index) and
|
||||
(
|
||||
if starIndex = -1 or index < starIndex
|
||||
then c.(TupleElementContent).getIndex() = index
|
||||
else
|
||||
// This could get big if big tuples exist
|
||||
if index = starIndex
|
||||
then c.(TupleElementContent).getIndex() >= index
|
||||
else c.(TupleElementContent).getIndex() >= index - 1
|
||||
) and
|
||||
(
|
||||
if element instanceof SequenceNode
|
||||
then
|
||||
// Step 5b
|
||||
nodeTo = TIterableSequenceNode(element)
|
||||
else
|
||||
if element instanceof StarredNode
|
||||
then
|
||||
// Step 5b
|
||||
nodeTo = TIterableSequenceNode(element)
|
||||
// Step 5c
|
||||
nodeTo = TIterableElementNode(element)
|
||||
else
|
||||
if element instanceof StarredNode
|
||||
then
|
||||
// Step 5c
|
||||
nodeTo = TIterableElementNode(element)
|
||||
else
|
||||
// Step 5a
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element
|
||||
)
|
||||
// Step 5a
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 6
|
||||
* Data flows from `TIterableElement(v)` to the essa variable for `v`, with
|
||||
* content type `ListElementContent`.
|
||||
*/
|
||||
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ControlFlowNode starred | starred.getNode() instanceof Starred |
|
||||
nodeFrom = TIterableElementNode(starred) and
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = starred and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Step 6
|
||||
* Data flows from `TIterableElement(v)` to the essa variable for `v`, with
|
||||
* content type `ListElementContent`.
|
||||
*/
|
||||
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ControlFlowNode starred | starred.getNode() instanceof Starred |
|
||||
nodeFrom = TIterableElementNode(starred) and
|
||||
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = starred and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
|
||||
/** All read steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
iterableUnpackingForReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingElementReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingConvertingReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
/** All read steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
iterableUnpackingForReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingElementReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingConvertingReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** All store steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
iterableUnpackingStarredElementStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingConvertingStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
/** All store steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
iterableUnpackingStarredElementStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingConvertingStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** All flow steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
iterableUnpackingAssignmentFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
/** All flow steps associated with unpacking assignment. */
|
||||
predicate iterableUnpackingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
iterableUnpackingAssignmentFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
@@ -54,260 +54,258 @@
|
||||
private import python
|
||||
private import DataFlowPublic
|
||||
|
||||
/**
|
||||
* Holds when there is flow from the subject `nodeFrom` to the (top-level) pattern `nodeTo` of a `match` statement.
|
||||
*
|
||||
* The subject of a match flows to each top-level pattern
|
||||
* (a pattern directly under a `case` statement).
|
||||
*
|
||||
* We could consider a model closer to use-use-flow, where the subject
|
||||
* only flows to the first top-level pattern and from there to the
|
||||
* following ones.
|
||||
*/
|
||||
predicate matchSubjectFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchStmt match, Expr subject, Pattern target |
|
||||
subject = match.getSubject() and
|
||||
target = match.getCase(_).(Case).getPattern()
|
||||
|
|
||||
nodeFrom.asExpr() = subject and
|
||||
nodeTo.asCfgNode().getNode() = target
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Holds when there is flow from the subject `nodeFrom` to the (top-level) pattern `nodeTo` of a `match` statement.
|
||||
*
|
||||
* The subject of a match flows to each top-level pattern
|
||||
* (a pattern directly under a `case` statement).
|
||||
*
|
||||
* We could consider a model closer to use-use-flow, where the subject
|
||||
* only flows to the first top-level pattern and from there to the
|
||||
* following ones.
|
||||
*/
|
||||
predicate matchSubjectFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchStmt match, Expr subject, Pattern target |
|
||||
subject = match.getSubject() and
|
||||
target = match.getCase(_).(Case).getPattern()
|
||||
|
|
||||
nodeFrom.asExpr() = subject and
|
||||
nodeTo.asCfgNode().getNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* as pattern: subject flows to alias as well as to the interior pattern
|
||||
* syntax (toplevel): `case pattern as alias:`
|
||||
*/
|
||||
predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchAsPattern subject, Name alias | alias = subject.getAlias() |
|
||||
// We make the subject flow to the interior pattern via the alias.
|
||||
// That way, information can propagate from the interior pattern to the alias.
|
||||
//
|
||||
// the subject flows to the interior pattern
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = subject.getPattern()
|
||||
/**
|
||||
* as pattern: subject flows to alias as well as to the interior pattern
|
||||
* syntax (toplevel): `case pattern as alias:`
|
||||
*/
|
||||
predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchAsPattern subject, Name alias | alias = subject.getAlias() |
|
||||
// We make the subject flow to the interior pattern via the alias.
|
||||
// That way, information can propagate from the interior pattern to the alias.
|
||||
//
|
||||
// the subject flows to the interior pattern
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = subject.getPattern()
|
||||
or
|
||||
// the interior pattern flows to the alias
|
||||
nodeFrom.asCfgNode().getNode() = subject.getPattern() and
|
||||
nodeTo.asVar().getDefinition().(PatternAliasDefinition).getDefiningNode().getNode() = alias
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* or pattern: subject flows to each alternative
|
||||
* syntax (toplevel): `case alt1 | alt2:`
|
||||
*/
|
||||
predicate matchOrFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchOrPattern subject, Pattern pattern | pattern = subject.getAPattern() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* literal pattern: flow from the literal to the pattern, to add information
|
||||
* syntax (toplevel): `case literal:`
|
||||
*/
|
||||
predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchLiteralPattern pattern, Expr literal | literal = pattern.getLiteral() |
|
||||
nodeFrom.asExpr() = literal and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* capture pattern: subject flows to the variable
|
||||
* syntax (toplevel): `case var:`
|
||||
*/
|
||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
||||
nodeFrom.asCfgNode().getNode() = capture and
|
||||
nodeTo.asVar().getDefinition().(PatternCaptureDefinition).getDefiningNode().getNode() = var
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* value pattern: flow from the value to the pattern, to add information
|
||||
* syntax (toplevel): `case Dotted.value:`
|
||||
*/
|
||||
predicate matchValueFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchValuePattern pattern, Expr value | value = pattern.getValue() |
|
||||
nodeFrom.asExpr() = value and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* sequence pattern: each element reads from subject at the associated index
|
||||
* syntax (toplevel): `case [a, b]:`
|
||||
*/
|
||||
predicate matchSequenceReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, Pattern element |
|
||||
element = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = element and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
or
|
||||
// the interior pattern flows to the alias
|
||||
nodeFrom.asCfgNode().getNode() = subject.getPattern() and
|
||||
nodeTo.asVar().getDefinition().(PatternAliasDefinition).getDefiningNode().getNode() = alias
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* or pattern: subject flows to each alternative
|
||||
* syntax (toplevel): `case alt1 | alt2:`
|
||||
*/
|
||||
predicate matchOrFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchOrPattern subject, Pattern pattern | pattern = subject.getAPattern() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* literal pattern: flow from the literal to the pattern, to add information
|
||||
* syntax (toplevel): `case literal:`
|
||||
*/
|
||||
predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchLiteralPattern pattern, Expr literal | literal = pattern.getLiteral() |
|
||||
nodeFrom.asExpr() = literal and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* capture pattern: subject flows to the variable
|
||||
* syntax (toplevel): `case var:`
|
||||
*/
|
||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
||||
nodeFrom.asCfgNode().getNode() = capture and
|
||||
nodeTo.asVar().getDefinition().(PatternCaptureDefinition).getDefiningNode().getNode() = var
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* value pattern: flow from the value to the pattern, to add information
|
||||
* syntax (toplevel): `case Dotted.value:`
|
||||
*/
|
||||
predicate matchValueFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchValuePattern pattern, Expr value | value = pattern.getValue() |
|
||||
nodeFrom.asExpr() = value and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* sequence pattern: each element reads from subject at the associated index
|
||||
* syntax (toplevel): `case [a, b]:`
|
||||
*/
|
||||
predicate matchSequenceReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, Pattern element |
|
||||
element = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = element and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
or
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the read step.
|
||||
*/
|
||||
predicate matchStarReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, MatchStarPattern star |
|
||||
star = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo = TStarPatternElementNode(star) and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() >= index
|
||||
or
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the store step.
|
||||
*/
|
||||
predicate matchStarStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchStarPattern star |
|
||||
nodeFrom = TStarPatternElementNode(star) and
|
||||
nodeTo.asCfgNode().getNode() = star.getTarget() and
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* mapping pattern: each value reads from subject at the associated key
|
||||
* syntax (toplevel): `case {"color": c, "height": x}:`
|
||||
*/
|
||||
predicate matchMappingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
Pattern value
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
value = keyValue.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the read step.
|
||||
*/
|
||||
predicate matchStarReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, MatchStarPattern star |
|
||||
star = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo = TStarPatternElementNode(star) and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() >= index
|
||||
or
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* double star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case {**var}:`
|
||||
*
|
||||
* Dictionary content flows to the double star, but all mentioned keys in the
|
||||
* mapping pattern should be cleared.
|
||||
*/
|
||||
predicate matchMappingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchMappingPattern subject, MatchDoubleStarPattern dstar |
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = dstar.getTarget()
|
||||
)
|
||||
}
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the store step.
|
||||
*/
|
||||
predicate matchStarStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchStarPattern star |
|
||||
nodeFrom = TStarPatternElementNode(star) and
|
||||
nodeTo.asCfgNode().getNode() = star.getTarget() and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bindings that are mentioned in a mapping pattern will not be available
|
||||
* to a double star pattern in the same mapping pattern.
|
||||
*/
|
||||
predicate matchMappingClearStep(Node n, Content c) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
MatchDoubleStarPattern dstar
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
n.asCfgNode().getNode() = dstar.getTarget() and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
/**
|
||||
* mapping pattern: each value reads from subject at the associated key
|
||||
* syntax (toplevel): `case {"color": c, "height": x}:`
|
||||
*/
|
||||
predicate matchMappingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
Pattern value
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
value = keyValue.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* class pattern: all keywords read the appropriate attribute from the subject
|
||||
* syntax (toplevel): `case ClassName(attr = val):`
|
||||
*/
|
||||
predicate matchClassReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchClassPattern subject, MatchKeywordPattern keyword, Name attr, Pattern value |
|
||||
keyword = subject.getKeyword(_) and
|
||||
attr = keyword.getAttribute() and
|
||||
value = keyword.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(AttributeContent).getAttribute() = attr.getId()
|
||||
)
|
||||
}
|
||||
/**
|
||||
* double star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case {**var}:`
|
||||
*
|
||||
* Dictionary content flows to the double star, but all mentioned keys in the
|
||||
* mapping pattern should be cleared.
|
||||
*/
|
||||
predicate matchMappingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchMappingPattern subject, MatchDoubleStarPattern dstar | dstar = subject.getAMapping() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = dstar.getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/** All flow steps associated with match. */
|
||||
predicate matchFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
matchSubjectFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchAsFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchOrFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchLiteralFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchCaptureFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchValueFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchMappingFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
/**
|
||||
* Bindings that are mentioned in a mapping pattern will not be available
|
||||
* to a double star pattern in the same mapping pattern.
|
||||
*/
|
||||
predicate matchMappingClearStep(Node n, Content c) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
MatchDoubleStarPattern dstar
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
n.asCfgNode().getNode() = dstar.getTarget() and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
|
||||
/** All read steps associated with match. */
|
||||
predicate matchReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchClassReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchSequenceReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchMappingReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStarReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
/**
|
||||
* class pattern: all keywords read the appropriate attribute from the subject
|
||||
* syntax (toplevel): `case ClassName(attr = val):`
|
||||
*/
|
||||
predicate matchClassReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchClassPattern subject, MatchKeywordPattern keyword, Name attr, Pattern value |
|
||||
keyword = subject.getKeyword(_) and
|
||||
attr = keyword.getAttribute() and
|
||||
value = keyword.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(AttributeContent).getAttribute() = attr.getId()
|
||||
)
|
||||
}
|
||||
|
||||
/** All store steps associated with match. */
|
||||
predicate matchStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchStarStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
/** All flow steps associated with match. */
|
||||
predicate matchFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
matchSubjectFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchAsFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchOrFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchLiteralFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchCaptureFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchValueFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchMappingFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* All clear steps associated with match
|
||||
*/
|
||||
predicate matchClearStep(Node n, Content c) { matchMappingClearStep(n, c) }
|
||||
/** All read steps associated with match. */
|
||||
predicate matchReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchClassReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchSequenceReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchMappingReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStarReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** All store steps associated with match. */
|
||||
predicate matchStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchStarStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* All clear steps associated with match
|
||||
*/
|
||||
predicate matchClearStep(Node n, Content c) { matchMappingClearStep(n, c) }
|
||||
|
||||
Reference in New Issue
Block a user