mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Python: Port a few queries to new API.
This commit is contained in:
@@ -13,19 +13,19 @@
|
||||
|
||||
import python
|
||||
|
||||
FunctionObject defines_equality(ClassObject c, string name) {
|
||||
CallableValue defines_equality(ClassValue c, string name) {
|
||||
(name = "__eq__" or major_version() = 2 and name = "__cmp__")
|
||||
and
|
||||
result = c.declaredAttribute(name)
|
||||
}
|
||||
|
||||
FunctionObject implemented_method(ClassObject c, string name) {
|
||||
CallableValue implemented_method(ClassValue c, string name) {
|
||||
result = defines_equality(c, name)
|
||||
or
|
||||
result = c.declaredAttribute("__hash__") and name = "__hash__"
|
||||
}
|
||||
|
||||
string unimplemented_method(ClassObject c) {
|
||||
string unimplemented_method(ClassValue c) {
|
||||
not exists(defines_equality(c, _)) and
|
||||
(result = "__eq__" and major_version() = 3 or major_version() = 2 and result = "__eq__ or __cmp__")
|
||||
or
|
||||
@@ -33,14 +33,21 @@ string unimplemented_method(ClassObject c) {
|
||||
not c.declaresAttribute(result) and result = "__hash__" and major_version() = 2
|
||||
}
|
||||
|
||||
predicate violates_hash_contract(ClassObject c, string present, string missing, Object method) {
|
||||
not c.unhashable() and
|
||||
missing = unimplemented_method(c) and
|
||||
method = implemented_method(c, present) and
|
||||
not c.unknowableAttributes()
|
||||
/** Holds if this class is unhashable */
|
||||
predicate unhashable(ClassValue cls) {
|
||||
cls.lookup("__hash__") = Value::named("None")
|
||||
or
|
||||
cls.lookup("__hash__").(CallableValue).neverReturns()
|
||||
}
|
||||
|
||||
from ClassObject c, string present, string missing, FunctionObject method
|
||||
predicate violates_hash_contract(ClassValue c, string present, string missing, Value method) {
|
||||
not unhashable(c) and
|
||||
missing = unimplemented_method(c) and
|
||||
method = implemented_method(c, present) and
|
||||
not c.failedInference(_)
|
||||
}
|
||||
|
||||
from ClassValue c, string present, string missing, CallableValue method
|
||||
where violates_hash_contract(c, present, missing, method) and
|
||||
exists(c.getPyClass()) // Suppress results that aren't from source
|
||||
exists(c.getScope()) // Suppress results that aren't from source
|
||||
select method, "Class $@ implements " + present + " but does not define " + missing + ".", c, c.getName()
|
||||
|
||||
@@ -25,26 +25,26 @@ predicate total_ordering(Class cls) {
|
||||
n.getId() = "total_ordering")
|
||||
}
|
||||
|
||||
FunctionObject implemented_method(ClassObject c, string name) {
|
||||
CallableValue implemented_method(ClassValue c, string name) {
|
||||
result = c.declaredAttribute(name) and name = equals_or_ne()
|
||||
}
|
||||
|
||||
string unimplemented_method(ClassObject c) {
|
||||
string unimplemented_method(ClassValue c) {
|
||||
not c.declaresAttribute(result) and result = equals_or_ne()
|
||||
}
|
||||
|
||||
predicate violates_equality_contract(ClassObject c, string present, string missing, FunctionObject method) {
|
||||
predicate violates_equality_contract(ClassValue c, string present, string missing, CallableValue method) {
|
||||
missing = unimplemented_method(c) and
|
||||
method = implemented_method(c, present) and
|
||||
not c.unknowableAttributes() and
|
||||
not total_ordering(c.getPyClass()) and
|
||||
not c.failedInference(_) and
|
||||
not total_ordering(c.getScope()) and
|
||||
/* Python 3 automatically implements __ne__ if __eq__ is defined, but not vice-versa */
|
||||
not (major_version() = 3 and present = "__eq__" and missing = "__ne__") and
|
||||
not method.getFunction() instanceof DelegatingEqualityMethod and
|
||||
not c.lookupAttribute(missing).(FunctionObject).getFunction() instanceof DelegatingEqualityMethod
|
||||
not method.getScope() instanceof DelegatingEqualityMethod and
|
||||
not c.lookup(missing).(CallableValue).getScope() instanceof DelegatingEqualityMethod
|
||||
}
|
||||
|
||||
from ClassObject c, string present, string missing, FunctionObject method
|
||||
from ClassValue c, string present, string missing, CallableValue method
|
||||
where violates_equality_contract(c, present, missing, method)
|
||||
|
||||
select method, "Class $@ implements " + present + " but does not implement " + missing + ".", c, c.getName()
|
||||
|
||||
@@ -27,25 +27,25 @@ string ordering_name(int n) {
|
||||
result = "__ge__" and n = 4
|
||||
}
|
||||
|
||||
predicate overrides_ordering_method(ClassObject c, string name) {
|
||||
predicate overrides_ordering_method(ClassValue c, string name) {
|
||||
name = ordering_name(_) and
|
||||
(
|
||||
c.declaresAttribute(name)
|
||||
or
|
||||
exists(ClassObject sup |
|
||||
sup = c.getASuperType() and not sup = theObjectType() |
|
||||
exists(ClassValue sup |
|
||||
sup = c.getASuperType() and not sup = Value::named("object") |
|
||||
sup.declaresAttribute(name)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
string unimplemented_ordering(ClassObject c, int n) {
|
||||
not c = theObjectType() and
|
||||
string unimplemented_ordering(ClassValue c, int n) {
|
||||
not c = Value::named("object") and
|
||||
not overrides_ordering_method(c, result) and
|
||||
result = ordering_name(n)
|
||||
}
|
||||
|
||||
string unimplemented_ordering_methods(ClassObject c, int n) {
|
||||
string unimplemented_ordering_methods(ClassValue c, int n) {
|
||||
n = 0 and result = "" and exists(unimplemented_ordering(c, _))
|
||||
or
|
||||
exists(string prefix, int nm1 |
|
||||
@@ -58,14 +58,14 @@ string unimplemented_ordering_methods(ClassObject c, int n) {
|
||||
)
|
||||
}
|
||||
|
||||
Object ordering_method(ClassObject c, string name) {
|
||||
Value ordering_method(ClassValue c, string name) {
|
||||
/* If class doesn't declare a method then don't blame this class (the superclass will be blamed). */
|
||||
name = ordering_name(_) and result = c.declaredAttribute(name)
|
||||
}
|
||||
|
||||
from ClassObject c, Object ordering, string name
|
||||
where not c.unknowableAttributes() and
|
||||
not total_ordering(c.getPyClass())
|
||||
from ClassValue c, Value ordering, string name
|
||||
where not c.failedInference(_) and
|
||||
not total_ordering(c.getScope())
|
||||
and ordering = ordering_method(c, name) and
|
||||
exists(unimplemented_ordering(c, _))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user