Skip to content

Commit fc4bb02

Browse files
authored
Merge pull request #1636 from markshannon/python-api-odds-and-ends
Python: Assorted improvements to API.
2 parents 4969298 + 44a27c3 commit fc4bb02

File tree

13 files changed

+414
-15
lines changed

13 files changed

+414
-15
lines changed

python/ql/src/semmle/python/Exprs.qll

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import python
22
private import semmle.python.pointsto.PointsTo
3+
private import semmle.python.objects.ObjectInternal
34

45
/** An expression */
56
class Expr extends Expr_, AstNode {
@@ -71,7 +72,8 @@ class Expr extends Expr_, AstNode {
7172
result = this.getASubExpression()
7273
}
7374

74-
/** Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to
75+
/** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead.
76+
* Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to
7577
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
7678
* precise, but may not provide information for a significant number of flow-nodes.
7779
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
@@ -82,13 +84,15 @@ class Expr extends Expr_, AstNode {
8284
this.refersTo(_, obj, cls, origin)
8385
}
8486

85-
/** Gets what this expression might "refer-to" in the given `context`.
87+
/** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead.
88+
* Gets what this expression might "refer-to" in the given `context`.
8689
*/
8790
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
8891
this.getAFlowNode().refersTo(context, obj, cls, origin.getAFlowNode())
8992
}
9093

91-
/** Whether this expression might "refer-to" to `value` which is from `origin`
94+
/** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead.
95+
* Holds if this expression might "refer-to" to `value` which is from `origin`
9296
* Unlike `this.refersTo(value, _, origin)`, this predicate includes results
9397
* where the class cannot be inferred.
9498
*/
@@ -97,11 +101,31 @@ class Expr extends Expr_, AstNode {
97101
this.getAFlowNode().refersTo(obj, origin.getAFlowNode())
98102
}
99103

100-
/** Equivalent to `this.refersTo(value, _)` */
104+
/** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead.
105+
* Equivalent to `this.refersTo(value, _)` */
101106
predicate refersTo(Object obj) {
102107
this.refersTo(obj, _)
103108
}
104109

110+
/** Holds if this expression might "point-to" to `value` which is from `origin`
111+
* in the given `context`.
112+
*/
113+
predicate pointsTo(Context context, Value value, AstNode origin) {
114+
this.getAFlowNode().pointsTo(context, value, origin.getAFlowNode())
115+
}
116+
117+
/** Holds if this expression might "point-to" to `value` which is from `origin`.
118+
*/
119+
predicate pointsTo(Value value, AstNode origin) {
120+
this.getAFlowNode().pointsTo(value, origin.getAFlowNode())
121+
}
122+
123+
/** Holds if this expression might "point-to" to `value`.
124+
*/
125+
predicate pointsTo(Value value) {
126+
this.pointsTo(value, _)
127+
}
128+
105129
}
106130

107131
/** An attribute expression, such as `value.attr` */
@@ -346,6 +370,11 @@ abstract class ImmutableLiteral extends Expr {
346370
abstract Object getLiteralObject();
347371

348372
abstract boolean booleanValue();
373+
374+
final Value getLiteralValue() {
375+
result.(ConstantObjectInternal).getLiteral() = this
376+
}
377+
349378
}
350379

351380
/** A numerical constant expression, such as `7` or `4.2` */
@@ -472,8 +501,10 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
472501
py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
473502
}
474503

504+
/** Gets the (integer) value of this constant. Will not return a result if the value does not fit into
505+
a 32 bit signed value */
475506
int getValue() {
476-
result = -this.getOperand().(IntegerLiteral).getValue()
507+
result = -(this.getOperand().(IntegerLiteral).getValue())
477508
}
478509

479510
}

python/ql/src/semmle/python/Flow.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ class ControlFlowNode extends @py_flow_node {
222222
this.pointsTo(_, value, _)
223223
}
224224

225+
/** Gets the value that this ControlFlowNode points-to. */
226+
Value pointsTo() {
227+
this.pointsTo(_, result, _)
228+
}
229+
225230
/** Gets a value that this ControlFlowNode may points-to. */
226231
Value inferredValue() {
227232
this.pointsTo(_, result, _)

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

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ abstract class ConstantObjectInternal extends ObjectInternal {
7373

7474
override predicate useOriginAsLegacyObject() { none() }
7575

76+
/** Gets an AST literal with the same value as this object */
77+
abstract ImmutableLiteral getLiteral();
78+
7679
}
7780

7881
private abstract class BooleanObjectInternal extends ConstantObjectInternal {
7982

8083
override ObjectInternal getClass() {
81-
result = TBuiltinClassObject(Builtin::special("bool"))
84+
result = ClassValue::bool()
8285
}
8386

8487
override int length() { none() }
@@ -90,6 +93,10 @@ private abstract class BooleanObjectInternal extends ConstantObjectInternal {
9093
/* Booleans aren't iterable */
9194
override ObjectInternal getIterNext() { none() }
9295

96+
override ImmutableLiteral getLiteral() {
97+
result.(BooleanLiteral).booleanValue() = this.booleanValue()
98+
}
99+
93100
}
94101

95102
private class TrueObjectInternal extends BooleanObjectInternal, TTrue {
@@ -175,10 +182,14 @@ private class NoneObjectInternal extends ConstantObjectInternal, TNone {
175182
/* None isn't iterable */
176183
override ObjectInternal getIterNext() { none() }
177184

185+
override ImmutableLiteral getLiteral() {
186+
result instanceof None
187+
}
188+
178189
}
179190

180191

181-
private class IntObjectInternal extends ConstantObjectInternal, TInt {
192+
class IntObjectInternal extends ConstantObjectInternal, TInt {
182193

183194
override string toString() {
184195
result = "int " + this.intValue().toString()
@@ -216,9 +227,15 @@ private class IntObjectInternal extends ConstantObjectInternal, TInt {
216227
/* ints aren't iterable */
217228
override ObjectInternal getIterNext() { none() }
218229

230+
override ImmutableLiteral getLiteral() {
231+
result.(IntegerLiteral).getValue() = this.intValue()
232+
or
233+
result.(NegativeIntegerLiteral).getOperand().(IntegerLiteral).getValue() = -this.intValue()
234+
}
235+
219236
}
220237

221-
private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
238+
class FloatObjectInternal extends ConstantObjectInternal, TFloat {
222239

223240
override string toString() {
224241
if this.floatValue() = this.floatValue().floor() then (
@@ -241,7 +258,7 @@ private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
241258
result.floatValue() = this.floatValue()
242259
}
243260

244-
private float floatValue() {
261+
float floatValue() {
245262
this = TFloat(result)
246263
}
247264

@@ -264,10 +281,14 @@ private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
264281
/* floats aren't iterable */
265282
override ObjectInternal getIterNext() { none() }
266283

284+
override ImmutableLiteral getLiteral() {
285+
result.(FloatLiteral).getValue() = this.floatValue()
286+
}
287+
267288
}
268289

269290

270-
private class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
291+
class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
271292

272293
override string toString() {
273294
result = "'" + this.strValue() + "'"
@@ -310,9 +331,13 @@ private class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
310331
result = TUnknownInstance(this.getClass())
311332
}
312333

334+
override ImmutableLiteral getLiteral() {
335+
result.(Unicode).getText() = this.strValue()
336+
}
337+
313338
}
314339

315-
private class BytesObjectInternal extends ConstantObjectInternal, TBytes {
340+
class BytesObjectInternal extends ConstantObjectInternal, TBytes {
316341

317342
override string toString() {
318343
result = "'" + this.strValue() + "'"
@@ -355,6 +380,10 @@ private class BytesObjectInternal extends ConstantObjectInternal, TBytes {
355380
result = TUnknownInstance(this.getClass())
356381
}
357382

383+
override ImmutableLiteral getLiteral() {
384+
result.(Bytes).getText() = this.strValue()
385+
}
386+
358387
}
359388

360389

0 commit comments

Comments
 (0)