Skip to content

Commit 5496fa4

Browse files
committed
Python: Add a way to easily specify constant values for in new Value API.
1 parent 6b2938a commit 5496fa4

File tree

6 files changed

+87
-5
lines changed

6 files changed

+87
-5
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ abstract class ImmutableLiteral extends Expr {
370370
abstract Object getLiteralObject();
371371

372372
abstract boolean booleanValue();
373+
373374
final Value getLiteralValue() {
374375
result.(ConstantObjectInternal).getLiteral() = this
375376
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ private class NoneObjectInternal extends ConstantObjectInternal, TNone {
189189
}
190190

191191

192-
private class IntObjectInternal extends ConstantObjectInternal, TInt {
192+
class IntObjectInternal extends ConstantObjectInternal, TInt {
193193

194194
override string toString() {
195195
result = "int " + this.intValue().toString()
@@ -235,7 +235,7 @@ private class IntObjectInternal extends ConstantObjectInternal, TInt {
235235

236236
}
237237

238-
private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
238+
class FloatObjectInternal extends ConstantObjectInternal, TFloat {
239239

240240
override string toString() {
241241
if this.floatValue() = this.floatValue().floor() then (
@@ -258,7 +258,7 @@ private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
258258
result.floatValue() = this.floatValue()
259259
}
260260

261-
private float floatValue() {
261+
float floatValue() {
262262
this = TFloat(result)
263263
}
264264

@@ -288,7 +288,7 @@ private class FloatObjectInternal extends ConstantObjectInternal, TFloat {
288288
}
289289

290290

291-
private class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
291+
class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
292292

293293
override string toString() {
294294
result = "'" + this.strValue() + "'"
@@ -337,7 +337,7 @@ private class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
337337

338338
}
339339

340-
private class BytesObjectInternal extends ConstantObjectInternal, TBytes {
340+
class BytesObjectInternal extends ConstantObjectInternal, TBytes {
341341

342342
override string toString() {
343343
result = "'" + this.strValue() + "'"

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,45 @@ module Value {
191191
name = "False" and result = TFalse()
192192
}
193193

194+
/** Gets the `Value` for the integer constant `i`, if it exists.
195+
* There will be no `Value` for most integers, but the following are
196+
* guaranteed to exist:
197+
* * From zero to 511 inclusive.
198+
* * All powers of 2 (up to 2**30)
199+
* * Any integer explicitly mentioned in the source program.
200+
*/
201+
Value forInt(int i) {
202+
result.(IntObjectInternal).intValue() = i
203+
}
204+
205+
/** Gets the `Value` for the bytes constant `bytes`, if it exists.
206+
* There will be no `Value` for most byte strings, unless it is explicitly
207+
* declared in the source program.
208+
*/
209+
Value forBytes(string bytes) {
210+
result.(BytesObjectInternal).strValue() = bytes
211+
}
212+
213+
/** Gets the `Value` for the unicode constant `text`, if it exists.
214+
* There will be no `Value` for most text strings, unless it is explicitly
215+
* declared in the source program.
216+
*/
217+
Value forUnicode(string text) {
218+
result.(UnicodeObjectInternal).strValue() = text
219+
}
220+
221+
/** Gets the `Value` for the bool constant `b`. */
222+
Value forBool(boolean b) {
223+
b = true and result = TTrue()
224+
or
225+
b = false and result = TFalse()
226+
}
227+
228+
/** Gets the `Value` for `None`. */
229+
Value none_() {
230+
result = ObjectInternal::none_()
231+
}
232+
194233
}
195234

196235
/** Class representing callables in the Python program
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
| 1 | file://:0:0:0:0 | int 1 |
2+
| 2 | file://:0:0:0:0 | int 2 |
3+
| 3 | file://:0:0:0:0 | int 3 |
4+
| 4 | file://:0:0:0:0 | int 4 |
5+
| 5 | file://:0:0:0:0 | int 5 |
6+
| 6 | file://:0:0:0:0 | int 6 |
7+
| 7 | file://:0:0:0:0 | int 7 |
8+
| 8 | file://:0:0:0:0 | int 8 |
9+
| 9 | file://:0:0:0:0 | int 9 |
10+
| 10 | file://:0:0:0:0 | int 10 |
11+
| 1000 | file://:0:0:0:0 | int 1000 |
12+
| 1004 | file://:0:0:0:0 | int 1004 |
13+
| b'b' | file://:0:0:0:0 | 'b' |
14+
| b'd' | file://:0:0:0:0 | 'd' |
15+
| u'a' | file://:0:0:0:0 | 'a' |
16+
| u'c' | file://:0:0:0:0 | 'c' |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
import python
3+
4+
from string txt, Value val
5+
where
6+
exists(string s |
7+
txt = "u'" + s + "'" and val = Value::forUnicode(s)
8+
or
9+
txt = "b'" + s + "'" and val = Value::forBytes(s)
10+
|
11+
s = "a" or s = "b" or s = "c" or s = "d"
12+
)
13+
or
14+
exists(int i |
15+
txt = i.toString() and val = Value::forInt(i)
16+
|
17+
i in [1..10] or i in [1000..1010]
18+
)
19+
20+
select txt, val
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
u"a"
2+
b"b"
3+
u"c"
4+
b"d"
5+
1000
6+
1004

0 commit comments

Comments
 (0)