Skip to content

Commit 63f24df

Browse files
committed
Python: Add some more utility predicates and classes to the new 'Value' API.
1 parent 5496fa4 commit 63f24df

File tree

4 files changed

+76
-2
lines changed

4 files changed

+76
-2
lines changed

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,17 @@ module Value {
218218
result.(UnicodeObjectInternal).strValue() = text
219219
}
220220

221+
/** Gets a `Value` for the string `text`. May be a bytes or unicode string for Python 2.
222+
* There will be no `Value` for most strings, unless it is explicitly
223+
* declared in the source program.
224+
*/
225+
Value forString(string text) {
226+
result.(UnicodeObjectInternal).strValue() = text
227+
or
228+
major_version() = 2 and
229+
result.(BytesObjectInternal).strValue() = text
230+
}
231+
221232
/** Gets the `Value` for the bool constant `b`. */
222233
Value forBool(boolean b) {
223234
b = true and result = TTrue()
@@ -389,20 +400,54 @@ class ClassValue extends Value {
389400

390401
}
391402

392-
class PythonFunctionValue extends CallableValue {
403+
404+
/** Class representing functions in the Python program, both Python and built-in.
405+
* Note that this does not include other callables such as bound-methods.
406+
*/
407+
abstract class FunctionValue extends CallableValue {
408+
409+
abstract string getQualifiedName();
410+
411+
}
412+
413+
class PythonFunctionValue extends FunctionValue {
393414

394415
PythonFunctionValue() {
395416
this instanceof PythonFunctionObjectInternal
396417
}
397418

419+
override string getQualifiedName() {
420+
result = this.(PythonFunctionObjectInternal).getScope().getQualifiedName()
421+
}
422+
398423
}
399424

400-
class BuiltinFunctionValue extends CallableValue {
425+
class BuiltinFunctionValue extends FunctionValue {
401426

402427
BuiltinFunctionValue() {
403428
this instanceof BuiltinFunctionObjectInternal
404429
}
405430

431+
override string getQualifiedName() {
432+
result = this.(BuiltinFunctionObjectInternal).getName()
433+
}
434+
435+
}
436+
437+
class BuiltinMethodValue extends FunctionValue {
438+
439+
BuiltinMethodValue() {
440+
this instanceof BuiltinMethodObjectInternal
441+
}
442+
443+
override string getQualifiedName() {
444+
exists(Builtin cls |
445+
cls.isClass() and
446+
cls.getMember(_) = this.(BuiltinMethodObjectInternal).getBuiltin() and
447+
result = cls.getName() + "." + this.getName()
448+
)
449+
}
450+
406451
}
407452

408453
class SequenceValue extends Value {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| file://:0:0:0:0 | Builtin-function exit | exit |
2+
| file://:0:0:0:0 | Builtin-function len | len |
3+
| file://:0:0:0:0 | builtin method append | list.append |
4+
| test.py:8:1:8:10 | Function foo | foo |
5+
| test.py:13:5:13:19 | Function C.meth | C.meth |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
import python
3+
4+
from FunctionValue v, string name
5+
where name = v.getQualifiedName() and
6+
(
7+
v = Value::named("len")
8+
or
9+
v instanceof PythonFunctionValue
10+
or
11+
v = Value::named("sys.exit")
12+
or
13+
v = Value::named("list").(ClassValue).lookup("append")
14+
)
15+
16+
select v, name

python/ql/test/library-tests/PointsTo/api/test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@
44
b"d"
55
1000
66
1004
7+
8+
def foo():
9+
pass
10+
11+
class C(object):
12+
13+
def meth(self):
14+
pass

0 commit comments

Comments
 (0)