Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7c23559

Browse files
committed
Python: More precise dataflow for tuples
(and dictionaries, but that is not fleshed out)
1 parent 2639e68 commit 7c23559

4 files changed

Lines changed: 139 additions & 59 deletions

File tree

python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,35 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
230230
// `[..., 42, ...]`
231231
// nodeFrom is `42`, cfg node
232232
// nodeTo is the sequence, say `[..., 42, ...]`, cfg node
233-
nodeTo.(CfgNode).getNode().(SequenceNode).getAnElement() = nodeFrom.(CfgNode).getNode()
233+
//
234+
// List
235+
nodeTo.(CfgNode).getNode().(ListNode).getAnElement() = nodeFrom.(CfgNode).getNode() and
236+
c instanceof ListElementContent
234237
or
238+
// Tuple
239+
exists(int n |
240+
nodeTo.(CfgNode).getNode().(TupleNode).getNode().(Tuple).getElt(n) = nodeFrom.(CfgNode).getNode().getNode() and
241+
c.(TupleElementContent).getIndex() = n and
242+
nodeFrom.(CfgNode).getNode().(NameNode).getId() = "SOURCE"
243+
)
244+
or
245+
//
235246
// Comprehension
236247
// `[x+1 for x in l]`
237248
// nodeFrom is `x+1`, cfg node
238249
// nodeTo is `[x+1 for x in l]`, cfg node
239-
nodeTo.(CfgNode).getNode().getNode().(Comp).getElt() = nodeFrom.(CfgNode).getNode().getNode()
250+
//
251+
// List
252+
nodeTo.(CfgNode).getNode().getNode().(ListComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
253+
c instanceof ListElementContent
254+
or
255+
// Set
256+
nodeTo.(CfgNode).getNode().getNode().(SetComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
257+
c instanceof SetElementContent
258+
or
259+
// Dictionary
260+
nodeTo.(CfgNode).getNode().getNode().(DictComp).getElt() = nodeFrom.(CfgNode).getNode().getNode() and
261+
c instanceof DictionaryElementAnyContent
240262
}
241263

242264
/**
@@ -247,7 +269,18 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
247269
// `l[3]`
248270
// nodeFrom is `l`, cfg node
249271
// nodeTo is `l[3]`, cfg node
250-
nodeFrom.(CfgNode).getNode() = nodeTo.(CfgNode).getNode().(SubscriptNode).getObject()
272+
nodeFrom.(CfgNode).getNode() = nodeTo.(CfgNode).getNode().(SubscriptNode).getObject() and
273+
(
274+
c instanceof ListElementContent
275+
or
276+
c instanceof SetElementContent
277+
or
278+
c instanceof DictionaryElementAnyContent
279+
or
280+
c.(TupleElementContent).getIndex() = nodeTo.(CfgNode).getNode().(SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
281+
or
282+
c.(DictionaryElementContent).getKey() = nodeTo.(CfgNode).getNode().(SubscriptNode).getIndex().getNode().(StrConst).getS()
283+
)
251284
or
252285
// set.pop
253286
// `s.pop()`
@@ -257,7 +290,12 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
257290
call.getFunction() = a and
258291
a.getName() = "pop" and // TODO: Should be made more robust, like Value::named("set.pop").getACall()
259292
nodeFrom.(CfgNode).getNode() = a.getObject() and
260-
nodeTo.(CfgNode).getNode() = call
293+
nodeTo.(CfgNode).getNode() = call and
294+
(
295+
c instanceof ListElementContent
296+
or
297+
c instanceof SetElementContent
298+
)
261299
)
262300
or
263301
// Comprehension

python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,58 @@ class BarrierGuard extends Expr {
145145
/**
146146
* A reference contained in an object. This is either a field or a property.
147147
*/
148-
class Content extends string {
149-
Content() { this = "Content" }
148+
newtype TContent =
149+
/** An element of a list. */
150+
TListElementContent() or
151+
/** An element of a set. */
152+
TSetElementContent() or
153+
/** An element of a tuple at a specifik index. */
154+
TTupleElementContent(int index) { exists(IntegerLiteral lit | lit.getValue() = index) } or
155+
/** An element of a dictionary under a specific key. */
156+
TDictionaryElementContent(string key) { exists(StrConst s | s.getS() = key ) } or
157+
/** An element of a dictionary at any key. */
158+
TDictionaryElementAnyContent()
159+
160+
class Content extends TContent {
161+
/** Gets a textual representation of this element. */
162+
string toString() { result = "Content" }
163+
}
164+
165+
class ListElementContent extends TListElementContent, Content {
166+
/** Gets a textual representation of this element. */
167+
override string toString() { result = "List element" }
168+
}
169+
170+
class SetElementContent extends TSetElementContent, Content {
171+
/** Gets a textual representation of this element. */
172+
override string toString() { result = "Set element" }
173+
}
174+
175+
class TupleElementContent extends TTupleElementContent, Content {
176+
int index;
177+
178+
TupleElementContent() { this = TTupleElementContent(index) }
179+
180+
/** Gets the index for this tuple element */
181+
int getIndex() { result = index }
182+
183+
/** Gets a textual representation of this element. */
184+
override string toString() { result = "Tuple element at " + index.toString() }
185+
}
186+
187+
class DictionaryElementContent extends TDictionaryElementContent, Content {
188+
string key;
189+
190+
DictionaryElementContent() { this = TDictionaryElementContent(key) }
191+
192+
/** Gets the index for this tuple element */
193+
string getKey() { result = key }
194+
195+
/** Gets a textual representation of this element. */
196+
override string toString() { result = "Dictionary element at " + key }
197+
}
198+
199+
class DictionaryElementAnyContent extends TDictionaryElementAnyContent, Content {
200+
/** Gets a textual representation of this element. */
201+
override string toString() { result = "Any dictionary element" }
150202
}

0 commit comments

Comments
 (0)