mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #3640 from RasmusWL/python-handle-3.8-enum-convert
Approved by tausbn
This commit is contained in:
@@ -33,12 +33,27 @@ predicate mutates_globals(ModuleValue m) {
|
||||
exists(SubscriptNode sub | sub.getObject() = globals and sub.isStore())
|
||||
)
|
||||
or
|
||||
exists(Value enum_convert, ClassValue enum_class |
|
||||
// Enum (added in 3.4) has method `_convert_` that alters globals
|
||||
// This was called `_convert` until 3.8, but that name will be removed in 3.9
|
||||
exists(ClassValue enum_class |
|
||||
enum_class.getASuperType() = Value::named("enum.Enum") and
|
||||
enum_convert = enum_class.attr("_convert") and
|
||||
exists(CallNode call | call.getScope() = m.getScope() |
|
||||
enum_convert.getACall() = call or
|
||||
call.getFunction().pointsTo(enum_convert)
|
||||
(
|
||||
// In Python < 3.8, Enum._convert can be found with points-to
|
||||
exists(Value enum_convert |
|
||||
enum_convert = enum_class.attr("_convert") and
|
||||
exists(CallNode call | call.getScope() = m.getScope() |
|
||||
enum_convert.getACall() = call or
|
||||
call.getFunction().pointsTo(enum_convert)
|
||||
)
|
||||
)
|
||||
or
|
||||
// In Python 3.8, Enum._convert_ is implemented using a metaclass, and our points-to
|
||||
// analysis doesn't handle that well enough. So we need a special case for this
|
||||
not exists(Value enum_convert | enum_convert = enum_class.attr("_convert")) and
|
||||
exists(CallNode call | call.getScope() = m.getScope() |
|
||||
call.getFunction().(AttrNode).getObject(["_convert", "_convert_"]).pointsTo() =
|
||||
enum_class
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| test.py:6:5:6:22 | Function Foo.foo | test.py:9:1:9:11 | ControlFlowNode for Attribute() |
|
||||
@@ -0,0 +1,4 @@
|
||||
import python
|
||||
|
||||
from PythonFunctionValue func
|
||||
select func, func.getACall()
|
||||
@@ -0,0 +1,25 @@
|
||||
# Simple classmethod
|
||||
|
||||
class Foo(object):
|
||||
|
||||
@classmethod
|
||||
def foo(cls, arg):
|
||||
print(cls, arg)
|
||||
|
||||
Foo.foo(42)
|
||||
|
||||
|
||||
# classmethod defined by metaclass
|
||||
|
||||
class BarMeta(type):
|
||||
|
||||
def bar(cls, arg):
|
||||
print(cls, arg)
|
||||
|
||||
class Bar(metaclass=BarMeta):
|
||||
pass
|
||||
|
||||
Bar.bar(42) # TODO: No points-to
|
||||
|
||||
# If this is solved, please update python/ql/src/Variables/UndefinedExport.ql which has a
|
||||
# work-around for this behavior
|
||||
Reference in New Issue
Block a user