From 20417c1b06e56212e33c2c58e5a58d4323664c40 Mon Sep 17 00:00:00 2001 From: Disconnect3d Date: Fri, 21 Oct 2022 02:18:42 +0200 Subject: [PATCH] Fix parameter default values (#1307) * Fix parameter default values Before this commit the created gdb.Parameter default values were not set properly. Now, we set the object's .value field properly with the provided default value. * fix issue with set/show docstring * fix lint * fix lint * fix lint * fix parameter further... * fix flake8 lint --- pwndbg/commands/config.py | 2 +- pwndbg/gdblib/config.py | 16 ++++---- tests/gdb-tests/tests/test_command_config.py | 22 +++++++++++ .../gdb-tests/tests/test_gdblib_parameter.py | 39 +++++++++++++++++++ 4 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 tests/gdb-tests/tests/test_gdblib_parameter.py diff --git a/pwndbg/commands/config.py b/pwndbg/commands/config.py index f4b4da4e..d269abd6 100644 --- a/pwndbg/commands/config.py +++ b/pwndbg/commands/config.py @@ -39,7 +39,7 @@ def get_config_parameters(scope, filter_pattern): values = [ v for v in values - if filter_pattern in v.optname.lower() or filter_pattern in v.docstring.lower() + if filter_pattern in v.name.lower() or filter_pattern in v.docstring.lower() ] return values diff --git a/pwndbg/gdblib/config.py b/pwndbg/gdblib/config.py index 6efab430..57fd0004 100644 --- a/pwndbg/gdblib/config.py +++ b/pwndbg/gdblib/config.py @@ -37,19 +37,17 @@ PARAM_CLASSES = { # https://sourceware.org/gdb/onlinedocs/gdb/Parameters-In-Python.html class Parameter(gdb.Parameter): def __init__(self, param: pwndbg.lib.config.Parameter): - self.param = param - # `set_doc` and `show_doc` must be set before `gdb.Parameter.__init__`. # They will be used for `help set ` and `help show `, # respectively - self.set_doc = "Set " + self.param.docstring - self.show_doc = "Show " + self.param.docstring - super().__init__(self.param.name, gdb.COMMAND_SUPPORT, self._param_class()) + self.set_doc = "Set " + param.docstring + self.show_doc = "Show " + param.docstring - def _param_class(self): - for k, v in PARAM_CLASSES.items(): - if isinstance(self.param.value, k): - return v + param_class = PARAM_CLASSES[type(param.value)] + super().__init__(param.name, gdb.COMMAND_SUPPORT, param_class) + + self.param = param + self.value = param.value @property def native_value(self): diff --git a/tests/gdb-tests/tests/test_command_config.py b/tests/gdb-tests/tests/test_command_config.py index f7e99153..0682d74c 100644 --- a/tests/gdb-tests/tests/test_command_config.py +++ b/tests/gdb-tests/tests/test_command_config.py @@ -1,3 +1,5 @@ +import re + import gdb @@ -11,3 +13,23 @@ def test_config(): gdb.execute("set global-max-fast 0x80") assert "'0x80' ('0')" in gdb.execute("heap_config", to_string=True) + + +def test_config_filtering(): + out = gdb.execute("config context-code-lines", to_string=True).splitlines() + + assert re.match(r"Name\s+Value\s+\(Def\)\s+Documentation", out[0]) + assert re.match(r"-+", out[1]) + assert re.match( + r"context-code-lines\s+10\s+number of additional lines to print in the code context", out[2] + ) + assert out[3] == "You can set config variable with `set `" + assert ( + out[4] + == "You can generate configuration file using `configfile` - then put it in your .gdbinit after initializing pwndbg" + ) + + +def test_config_filtering_missing(): + out = gdb.execute("config asdasdasdasd", to_string=True) + assert out == 'No config parameter found with filter "asdasdasdasd"\n' diff --git a/tests/gdb-tests/tests/test_gdblib_parameter.py b/tests/gdb-tests/tests/test_gdblib_parameter.py new file mode 100644 index 00000000..f9572976 --- /dev/null +++ b/tests/gdb-tests/tests/test_gdblib_parameter.py @@ -0,0 +1,39 @@ +import gdb +import pytest + +import pwndbg.gdblib.config + + +@pytest.mark.parametrize( + "params", + (("int", 123, "123"), ("bool", True, "on"), ("string", "some-string-val", "some-string-val")), +) +def test_gdb_parameter_default_value_works(start_binary, params): + name_suffix, default_value, displayed_value = params + + param_name = f"test-param-{name_suffix}" + + param = pwndbg.gdblib.config.add_param(param_name, default_value, "some show string") + + # Initialize and register param in GDB as if it would be done by gdblib.config.init_params + pwndbg.gdblib.config_mod.Parameter(param) + + out = gdb.execute(f"show {param_name}", to_string=True) + assert out in ( + f"""The current value of '{param_name}' is "{displayed_value}".\n""", # GDB 12.x + f"Show some show string {displayed_value}\n", # GDB 9.x + ) + assert gdb.parameter(param_name) == default_value + + # TODO/FIXME: We need to add documentation + out = gdb.execute(f"help show {param_name}", to_string=True) + assert out == "Show some show string\nThis command is not documented.\n" + assert ( + gdb.execute(f"help set {param_name}", to_string=True) + == "Set some show string\nThis command is not documented.\n" + ) + + # TODO/FIXME: Is there a way to unregister a GDB parameter defined in Python? + # Probably no? If the fact that we register params above ever causes issues, + # then we should just not test it via gdb.* APIs and only check if the added param + # has proper/expected fields set?