EventListener: pre-register event listeners in the decorator,
and use that registration in the iterator. That way, we do not invoke getattr on arbitrary methods, which could trigger unwanted code execution (for example, if a method is decorated with @property, getattr will execute its code).
This commit is contained in:
@@ -1631,21 +1631,19 @@ callback_mgr = CallbackManager()
|
|||||||
trigger_callback = callback_mgr.trigger_callback
|
trigger_callback = callback_mgr.trigger_callback
|
||||||
register_callback = callback_mgr.register_callback
|
register_callback = callback_mgr.register_callback
|
||||||
unregister_callback = callback_mgr.unregister_callback
|
unregister_callback = callback_mgr.unregister_callback
|
||||||
|
_event_listeners = defaultdict(set)
|
||||||
|
|
||||||
|
|
||||||
class EventListener:
|
class EventListener:
|
||||||
|
|
||||||
def _list_callbacks(self):
|
def _list_callbacks(self):
|
||||||
for method_name in dir(self):
|
for c in self.__class__.__mro__:
|
||||||
# Fixme: getattr executes the code of methods decorated by @property.
|
classname = c.__name__
|
||||||
# This if why we shield with startswith
|
for method_name in _event_listeners[classname]:
|
||||||
if not method_name.startswith('on_event_'):
|
method = getattr(self, method_name)
|
||||||
continue
|
assert callable(method)
|
||||||
method = getattr(self, method_name)
|
assert method_name.startswith('on_event_')
|
||||||
if not getattr(method, '_is_event_listener', False):
|
yield method_name[len('on_event_'):], method
|
||||||
continue
|
|
||||||
assert callable(method)
|
|
||||||
yield method_name[len('on_event_'):], method
|
|
||||||
|
|
||||||
def register_callbacks(self):
|
def register_callbacks(self):
|
||||||
for name, method in self._list_callbacks():
|
for name, method in self._list_callbacks():
|
||||||
@@ -1659,8 +1657,9 @@ class EventListener:
|
|||||||
|
|
||||||
|
|
||||||
def event_listener(func):
|
def event_listener(func):
|
||||||
assert func.__name__.startswith('on_event_')
|
classname, method_name = func.__qualname__.split('.')
|
||||||
func._is_event_listener = True
|
assert method_name.startswith('on_event_')
|
||||||
|
_event_listeners[classname].add(method_name)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user