Skip to content

Commit

Permalink
Let GefSetting write hooks see value
Browse files Browse the repository at this point in the history
  • Loading branch information
Grazfather committed Aug 26, 2023
1 parent c5f5df8 commit d8e0cb2
Showing 1 changed file with 37 additions and 36 deletions.
73 changes: 37 additions & 36 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -9491,9 +9491,11 @@ def __init__(self) -> None:
gef.config["gef.readline_compat"] = GefSetting(False, bool, "Workaround for readline SOH/ETX issue (SEGV)")
gef.config["gef.debug"] = GefSetting(False, bool, "Enable debug mode for gef")
gef.config["gef.autosave_breakpoints_file"] = GefSetting("", str, "Automatically save and restore breakpoints")
gef.config["gef.extra_plugins_dir"] = GefSetting("", str, "Autoload additional GEF commands from external directory", hooks={"on_write": self.load_extra_plugins})
plugins_dir = GefSetting("", str, "Autoload additional GEF commands from external directory", hooks={"on_write": GefSetting.no_spaces})
plugins_dir.add_hook("on_write", lambda _: self.load_extra_plugins)
gef.config["gef.extra_plugins_dir"] = plugins_dir
gef.config["gef.disable_color"] = GefSetting(False, bool, "Disable all colors in GEF")
gef.config["gef.tempdir"] = GefSetting(GEF_TEMP_DIR, str, "Directory to use for temporary/cache content")
gef.config["gef.tempdir"] = GefSetting(GEF_TEMP_DIR, str, "Directory to use for temporary/cache content", hooks={"on_write": GefSetting.no_spaces})
gef.config["gef.show_deprecation_warnings"] = GefSetting(True, bool, "Toggle the display of the `deprecated` warnings")
gef.config["gef.buffer"] = GefSetting(True, bool, "Internally buffer command output until completion")
gef.config["gef.bruteforce_main_arena"] = GefSetting(False, bool, "Allow bruteforcing main_arena symbol if everything else fails")
Expand Down Expand Up @@ -9812,12 +9814,15 @@ def set_setting(self, argv: Tuple[str, Any]) -> None:
_newval = True if new_value.upper() in ("TRUE", "T", "1") else False
else:
_newval = new_value

gef.config[key] = _newval
except Exception as e:
err(f"'{key}' expects type '{_type.__name__}', got {type(new_value).__name__}: reason {str(e)}")
return

try:
gef.config[key] = _newval
except Exception as e:
err(f"Cannot set '{key}': {e}")

reset_all_caches()
return

Expand Down Expand Up @@ -10607,30 +10612,34 @@ def malloc_align_address(self, address: int) -> int:

class GefSetting:
"""Basic class for storing gef settings as objects"""
READ_ACCESS = 0
WRITE_ACCESS = 1

def __init__(self, value: Any, cls: Optional[type] = None, description: Optional[str] = None, hooks: Optional[Dict[str, Callable]] = None) -> None:
self.value = value
self.type = cls or type(value)
self.description = description or ""
self.hooks: Tuple[List[Callable], List[Callable]] = ([], [])
if hooks:
for access, func in hooks.items():
if access == "on_read":
idx = GefSetting.READ_ACCESS
elif access == "on_write":
idx = GefSetting.WRITE_ACCESS
else:
raise ValueError
if not callable(func):
raise ValueError(f"hook is not callable")
self.hooks[idx].append(func)
self.hooks: Dict[str, List[Callable]] = collections.defaultdict(list)
if not hooks:
hooks = {}

for access, func in hooks.items():
self.add_hook(access, func)
return

def __str__(self) -> str:
return f"Setting(type={self.type.__name__}, value='{self.value}', desc='{self.description[:10]}...', "\
f"read_hooks={len(self.hooks[GefSetting.READ_ACCESS])}, write_hooks={len(self.hooks[GefSetting.READ_ACCESS])})"
return f"Setting(type={self.type.__name__}, value='{self.value}', desc='{self.description[:10]}...', " \
f"read_hooks={len(self.hooks['on_read'])}, write_hooks={len(self.hooks['on_write'])})"

def add_hook(self, access, func):
if access != "on_read" and access != "on_write":
raise ValueError("invalid access type")
if not callable(func):
raise ValueError(f"hook is not callable")
self.hooks[access].append(func)

@staticmethod
def no_spaces(value):
if " " in value:
raise ValueError("setting cannot contain spaces")


class GefSettingsManager(dict):
Expand All @@ -10656,32 +10665,24 @@ def __setitem__(self, name: str, value: Any) -> None:
if not value.type: raise Exception("Invalid type")
if not value.description: raise Exception("Invalid description")
setting = value
value = setting.value
super().__setitem__(name, setting)
self.__invoke_write_hooks(setting)
self.__invoke_write_hooks(setting, value)
return

def __delitem__(self, name: str) -> None:
super().__delitem__(name)
return
return super().__delitem__(name)

def raw_entry(self, name: str) -> GefSetting:
return super().__getitem__(name)

def __invoke_read_hooks(self, setting: GefSetting) -> None:
self.__invoke_hooks(is_write=False, setting=setting)
return

def __invoke_write_hooks(self, setting: GefSetting) -> None:
self.__invoke_hooks(is_write=True, setting=setting)
return
for callback in setting.hooks["on_read"]:
callback()

def __invoke_hooks(self, is_write: bool, setting: GefSetting) -> None:
if not setting.hooks:
return
idx = int(is_write)
if setting.hooks[idx]:
for callback in setting.hooks[idx]:
callback()
def __invoke_write_hooks(self, setting: GefSetting, value: Any) -> None:
for callback in setting.hooks["on_write"]:
callback(value)
return


Expand Down

0 comments on commit d8e0cb2

Please sign in to comment.