mirror of
https://github.com/github/codeql.git
synced 2025-12-16 08:43:11 +01:00
Python: Get rid of some get...Object methods
This frees `Class.qll`, `Exprs.qll`, and `Function.qll` from the clutches of points-to. For the somewhat complicated setup with `getLiteralObject` (an abstract method), I opted for a slightly ugly but workable solution of just defining a predicate on `ImmutableLiteral` that inlines each predicate body, special-cased to the specific instance to which it applies.
This commit is contained in:
@@ -221,3 +221,66 @@ class ModuleWithPointsTo extends Module {
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Function` that provides points-to related methods.
|
||||
*/
|
||||
class FunctionWithPointsTo extends Function {
|
||||
/** Gets the FunctionObject corresponding to this function */
|
||||
FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() }
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Class` that provides points-to related methods.
|
||||
*/
|
||||
class ClassWithPointsTo extends Class {
|
||||
/** Gets the ClassObject corresponding to this class */
|
||||
ClassObject getClassObject() { result.getOrigin() = this.getParent() }
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
Object getLiteralObject(ImmutableLiteral l) {
|
||||
l instanceof IntegerLiteral and
|
||||
(
|
||||
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, l.(Num).getN())
|
||||
)
|
||||
or
|
||||
l instanceof FloatLiteral and
|
||||
py_cobjecttypes(result, theFloatType()) and
|
||||
py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
l instanceof ImaginaryLiteral and
|
||||
py_cobjecttypes(result, theComplexType()) and
|
||||
py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
l instanceof NegativeIntegerLiteral and
|
||||
(
|
||||
(py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and
|
||||
py_cobjectnames(result, "-" + l.(UnaryExpr).getOperand().(IntegerLiteral).getN())
|
||||
)
|
||||
or
|
||||
l instanceof Bytes and
|
||||
py_cobjecttypes(result, theBytesType()) and
|
||||
py_cobjectnames(result, l.(Bytes).quotedString())
|
||||
or
|
||||
l instanceof Unicode and
|
||||
py_cobjecttypes(result, theUnicodeType()) and
|
||||
py_cobjectnames(result, l.(Unicode).quotedString())
|
||||
or
|
||||
l instanceof True and
|
||||
name_consts(l, "True") and
|
||||
result = theTrueObject()
|
||||
or
|
||||
l instanceof False and
|
||||
name_consts(l, "False") and
|
||||
result = theFalseObject()
|
||||
or
|
||||
l instanceof None and
|
||||
name_consts(l, "None") and
|
||||
result = theNoneObject()
|
||||
}
|
||||
|
||||
@@ -141,9 +141,6 @@ class Class extends Class_, Scope, AstNode {
|
||||
/** Gets the metaclass expression */
|
||||
Expr getMetaClass() { result = this.getParent().getMetaClass() }
|
||||
|
||||
/** Gets the ClassObject corresponding to this class */
|
||||
ClassObject getClassObject() { result.getOrigin() = this.getParent() }
|
||||
|
||||
/** Gets the nth base of this class definition. */
|
||||
Expr getBase(int index) { result = this.getParent().getBase(index) }
|
||||
|
||||
|
||||
@@ -240,17 +240,12 @@ class Bytes extends StringLiteral {
|
||||
/* syntax: b"hello" */
|
||||
Bytes() { not this.isUnicode() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theBytesType()) and
|
||||
py_cobjectnames(result, this.quotedString())
|
||||
}
|
||||
|
||||
/**
|
||||
* The extractor puts quotes into the name of each string (to prevent "0" clashing with 0).
|
||||
* The following predicate help us match up a string/byte literals in the source
|
||||
* which the equivalent object.
|
||||
*/
|
||||
private string quotedString() {
|
||||
string quotedString() {
|
||||
exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'")
|
||||
}
|
||||
}
|
||||
@@ -266,8 +261,6 @@ class Ellipsis extends Ellipsis_ {
|
||||
* Consists of string (both unicode and byte) literals and numeric literals.
|
||||
*/
|
||||
abstract class ImmutableLiteral extends Expr {
|
||||
abstract Object getLiteralObject();
|
||||
|
||||
abstract boolean booleanValue();
|
||||
}
|
||||
|
||||
@@ -292,12 +285,6 @@ class IntegerLiteral extends Num {
|
||||
|
||||
override string toString() { result = "IntegerLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN())
|
||||
or
|
||||
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0 and result = false
|
||||
or
|
||||
@@ -317,10 +304,6 @@ class FloatLiteral extends Num {
|
||||
|
||||
override string toString() { result = "FloatLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0.0 and result = false
|
||||
or
|
||||
@@ -343,10 +326,6 @@ class ImaginaryLiteral extends Num {
|
||||
|
||||
override string toString() { result = "ImaginaryLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0.0 and result = false
|
||||
or
|
||||
@@ -365,11 +344,6 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
|
||||
|
||||
override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
(py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and
|
||||
py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (integer) value of this constant. Will not return a result if the value does not fit into
|
||||
* a 32 bit signed value
|
||||
@@ -385,11 +359,6 @@ class Unicode extends StringLiteral {
|
||||
/* syntax: "hello" */
|
||||
Unicode() { this.isUnicode() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theUnicodeType()) and
|
||||
py_cobjectnames(result, this.quotedString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the quoted representation fo this string.
|
||||
*
|
||||
@@ -593,12 +562,10 @@ class StringLiteral extends Str_, ImmutableLiteral {
|
||||
this.getText() != "" and result = true
|
||||
}
|
||||
|
||||
override Object getLiteralObject() { none() }
|
||||
|
||||
override string toString() { result = "StringLiteral" }
|
||||
}
|
||||
|
||||
private predicate name_consts(Name_ n, string id) {
|
||||
predicate name_consts(Name_ n, string id) {
|
||||
exists(Variable v | py_variables(v, n) and id = v.getId() |
|
||||
id = "True" or id = "False" or id = "None"
|
||||
)
|
||||
@@ -627,8 +594,6 @@ class True extends BooleanLiteral {
|
||||
/* syntax: True */
|
||||
True() { name_consts(this, "True") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() }
|
||||
|
||||
override boolean booleanValue() { result = true }
|
||||
}
|
||||
|
||||
@@ -637,8 +602,6 @@ class False extends BooleanLiteral {
|
||||
/* syntax: False */
|
||||
False() { name_consts(this, "False") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() }
|
||||
|
||||
override boolean booleanValue() { result = false }
|
||||
}
|
||||
|
||||
@@ -647,8 +610,6 @@ class None extends NameConstant {
|
||||
/* syntax: None */
|
||||
None() { name_consts(this, "None") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() }
|
||||
|
||||
override boolean booleanValue() { result = false }
|
||||
}
|
||||
|
||||
|
||||
@@ -87,9 +87,6 @@ class Function extends Function_, Scope, AstNode {
|
||||
/** Gets the metrics for this function */
|
||||
FunctionMetrics getMetrics() { result = this }
|
||||
|
||||
/** Gets the FunctionObject corresponding to this function */
|
||||
FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() }
|
||||
|
||||
/**
|
||||
* Whether this function is a procedure, that is, it has no explicit return statement and always returns None.
|
||||
* Note that generator and async functions are not procedures as they return generators and coroutines respectively.
|
||||
|
||||
@@ -89,7 +89,7 @@ class ClassObject extends Object {
|
||||
}
|
||||
|
||||
/** Gets the scope associated with this class, if it is not a builtin class */
|
||||
Class getPyClass() { result.getClassObject() = this }
|
||||
ClassWithPointsTo getPyClass() { result.getClassObject() = this }
|
||||
|
||||
/** Returns an attribute declared on this class (not on a super-class) */
|
||||
Object declaredAttribute(string name) {
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from NumericObject n
|
||||
where
|
||||
exists(IntegerLiteral i | i.getLiteralObject() = n |
|
||||
exists(IntegerLiteral i | getLiteralObject(i) = n |
|
||||
i.getEnclosingModule().getFile().getShortName() = "test.py"
|
||||
)
|
||||
select n.toString(), n.repr()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Test that there are no literals that do not have a corresponding object. */
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
string repr(Expr e) {
|
||||
result = e.(Num).getN() or
|
||||
@@ -8,5 +9,5 @@ string repr(Expr e) {
|
||||
}
|
||||
|
||||
from ImmutableLiteral l
|
||||
where not exists(l.getLiteralObject())
|
||||
where not exists(getLiteralObject(l))
|
||||
select l.getLocation().getStartLine(), repr(l)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Test that there are no literals that do not have a corresponding object. */
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
string repr(Expr e) {
|
||||
result = e.(Num).getN() or
|
||||
@@ -8,5 +9,5 @@ string repr(Expr e) {
|
||||
}
|
||||
|
||||
from ImmutableLiteral l
|
||||
where not exists(l.getLiteralObject())
|
||||
where not exists(getLiteralObject(l))
|
||||
select l.getLocation().getStartLine(), repr(l)
|
||||
|
||||
Reference in New Issue
Block a user