Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create config options from choices #2090

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 21 additions & 21 deletions pwndbg/commands/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ def clear_screen(out=sys.stdout) -> None:
"context-sections",
"regs disasm code ghidra stack backtrace expressions threads heap-tracker",
"which context sections are displayed (controls order)",
choices=[
"regs",
"disasm",
"code",
"ghidra",
"stack",
"backtrace",
"expressions",
"threads",
"heap-tracker",
"''",
'""',
"none",
"empty",
"-",
"",
],
)
config_max_threads_display = pwndbg.gdblib.config.add_param(
"context-max-threads",
Expand All @@ -97,20 +114,12 @@ def clear_screen(out=sys.stdout) -> None:


@pwndbg.gdblib.config.trigger(config_context_sections)
def validate_context_sections() -> None:
valid_values = [
context.__name__.replace("context_", "") for context in context_sections.values()
]

def allow_empty_context_sections() -> None:
# If someone tries to set an empty string, we let to do that informing about possible values
# (so that it is possible to have no context at all)
if not config_context_sections.value or config_context_sections.value.lower() in (
"''",
'""',
"none",
"empty",
"-",
):
special_values = ["''", '""', "none", "empty", "-", ""]
valid_values = [e for e in config_context_sections.choices if e not in special_values]
if not config_context_sections.value or config_context_sections.value.lower() in special_values:
config_context_sections.value = ""
print(
message.warn(
Expand All @@ -119,15 +128,6 @@ def validate_context_sections() -> None:
)
return

for section in config_context_sections.split():
if section not in valid_values:
print(
message.warn(f"Invalid section: {section}, valid values: {', '.join(valid_values)}")
)
print(message.warn("(setting none of them like '' will make sections not appear)"))
config_context_sections.revert_default()
return


class StdOutput:
"""A context manager wrapper to give stdout"""
Expand Down
5 changes: 5 additions & 0 deletions pwndbg/gdblib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ def __get_set_string_gdb_gte_9(self) -> str:
self.param.value = self.value

for trigger in config.triggers[self.param.name]:
# validate param value before trigger
if not config.validate_choices(self.param.name, self.param.value):
self.param.revert_default()
return f"Invalid value '{self.param.value}' for parameter '{self.param.name}'. Valid choices are: {', '.join(self.param.choices)}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this if need to be in the trigger loop? The condition do not use trigger at all and here we will be re-validating things on each trigger. Is that needed?


trigger()

# No need to print anything if this is set before we get to a prompt,
Expand Down
12 changes: 12 additions & 0 deletions pwndbg/lib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(
param_class: int | None = None,
enum_sequence: Sequence[str] | None = None,
scope: str = "config",
choices: Sequence[str] | None = None,
) -> None:
# Note: `set_show_doc` should be a noun phrase, e.g. "the value of the foo"
# The `set_doc` will be "Set the value of the foo."
Expand All @@ -54,6 +55,7 @@ def __init__(
self.param_class = param_class or PARAM_CLASSES[type(default)]
self.enum_sequence = enum_sequence
self.scope = scope
self.choices = choices

@property
def is_changed(self) -> bool:
Expand Down Expand Up @@ -146,6 +148,7 @@ def add_param(
param_class: int | None = None,
enum_sequence: Sequence[str] | None = None,
scope: str = "config",
choices: Sequence[str] | None = None,
) -> Parameter:
# Dictionary keys are going to have underscores, so we can't allow them here
assert "_" not in name
Expand All @@ -158,6 +161,7 @@ def add_param(
param_class=param_class,
enum_sequence=enum_sequence,
scope=scope,
choices=choices,
)
return self.add_param_obj(p)

Expand All @@ -170,6 +174,14 @@ def add_param_obj(self, p: Parameter) -> Parameter:
self.params[attr_name] = p
return p

def validate_choices(self, name: str, value: Any) -> bool:
name_with_underscores = name.replace("-", "_")
p = self.params[name_with_underscores]
if p.choices is not None:
for v in value.split():
return v in p.choices
return True

def trigger(self, *params: Parameter) -> Callable[[Callable[..., T]], Callable[..., T]]:
names = [p.name for p in params]

Expand Down