Repository: pwndbg/pwndbg

Issue:
heap_config should give an example format for GLIBC version
The UX for the glibc version setting is not great.

1. The `heap_config` should give user an example format of GLIBC version we do expect. Currently it only shows this:
```
pwndbg> heap_config
Name                             Value (Def)  Documentation
-----------------------------------------------------------
glibc                            ''           GLIBC version for heuristics
...
```

2. When one sets the `glibc` parameter, we should have a setter that will validate it against the expected version format. Currently it does not:
```
pwndbg> set glibc as
Set GLIBC version for heuristics to 'as'.
```




Discussion:
Note: the glibc parameter is defined in here:
https://github.com/pwndbg/pwndbg/blob/e37591b25d923b1933b7092cacafa51a210d5f5e/pwndbg/glibc.py#L32-L34
Huh actually we do validate the glibc version that was set but only very late on when the heap commands are executed:

```
pwndbg> set glibc asdf
Set GLIBC version for heuristics to 'asdf'.
pwndbg> heap
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.

For more info invoke `set exception-verbose on` and rerun the command
or debug it by yourself with `set exception-debugger on`
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.

For more info invoke `set exception-verbose on` and rerun the command
or debug it by yourself with `set exception-debugger on`
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.

For more info invoke `set exception-verbose on` and rerun the command
or debug it by yourself with `set exception-debugger on`
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.

For more info invoke `set exception-verbose on` and rerun the command
or debug it by yourself with `set exception-debugger on`
Top chunk | PREV_INUSE
Addr: 0x555555776910
Size: 0x206f1

pwndbg> set exception-verbose on
Set whether to print a full stacktrace for exceptions raised in Pwndbg commands to 'on'.
pwndbg> heap
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.

Traceback (most recent call last):
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 184, in __call__
    return self.function(*args, **kwargs)
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 320, in _OnlyWhenRunning
    return function(*a, **kw)
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 406, in _OnlyWithResolvedHeapSyms
    return _try2run_heap_command(function, a, kw)
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 388, in _try2run_heap_command
    raise err
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 363, in _try2run_heap_command
    return function(*a, **kw)
  File "/home/dc/pwndbg/pwndbg/commands/__init__.py", line 345, in _OnlyWhenHeapIsInitialized
    return function(*a, **kw)
  File "/home/dc/pwndbg/pwndbg/commands/heap.py", line 401, in malloc_chunk
    allocator.fastbins(arena.address),
  File "/home/dc/pwndbg/pwndbg/heap/ptmalloc.py", line 1097, in fastbins
    safe_lnk = pwndbg.glibc.check_safe_linking()
  File "/home/dc/pwndbg/pwndbg/glibc.py", line 179, in _OnlyWhenGlibcLoaded
    if get_version() is not None:
  File "/home/dc/pwndbg/pwndbg/gdblib/proc.py", line 151, in wrapper
    return func(*a, **kw)
  File "/home/dc/pwndbg/pwndbg/glibc.py", line 46, in get_version
    % glibc_version.value
ValueError: Invalid GLIBC version: `asdf`, you should provide something like: 2.31 or 2.34

If that is an issue, you can report it on https://github.com/pwndbg/pwndbg/issues
(Please don't forget to search if it hasn't been reported before)
To generate the report and open a browser, you may run `bugreport --run-browser`
PS: Pull requests are welcome
malloc_chunk: An unknown error occurred when running this command.
You can try `set resolve-heap-via-heuristic force` and re-run this command.
```

We should move that validation to when the parameter is actually being set. This can be done with some triggers or sth for parameters.

Resolving patch:
diff --git a/pwndbg/glibc.py b/pwndbg/glibc.py
--- a/pwndbg/glibc.py
+++ b/pwndbg/glibc.py
@@ -21,6 +21,7 @@
 import pwndbg.heap
 import pwndbg.lib.cache
 import pwndbg.search
+from pwndbg.color import message
 
 safe_lnk = pwndbg.gdblib.config.add_param(
     "safe-linking",
@@ -30,21 +31,28 @@
 )
 
 glibc_version = pwndbg.gdblib.config.add_param(
-    "glibc", "", "GLIBC version for heuristics", scope="heap"
+    "glibc", "", "GLIBC version for heap heuristics resolution (e.g. 2.31)", scope="heap"
 )
 
 
+@pwndbg.gdblib.config.trigger(glibc_version)
+def set_glibc_version() -> None:
+    ret = re.search(r"(\d+)\.(\d+)", glibc_version.value)
+    if ret:
+        glibc_version.value = tuple(map(int, ret.groups()))
+        return
+
+    print(
+        message.warn(
+            f"Invalid GLIBC version: `{glibc_version.value}`, you should provide something like: 2.31 or 2.34"
+        )
+    )
+    glibc_version.revert_default()
+
+
 @pwndbg.gdblib.proc.OnlyWhenRunning
 def get_version() -> Optional[Tuple[int, ...]]:
-    if glibc_version.value:
-        ret = re.search(r"(\d+)\.(\d+)", glibc_version.value)
-        if ret:
-            return tuple(int(_) for _ in ret.groups())
-        else:
-            raise ValueError(
-                f"Invalid GLIBC version: `{glibc_version.value}`, you should provide something like: 2.31 or 2.34"
-            )
-    return _get_version()
+    return glibc_version or _get_version()
 
 
 @pwndbg.gdblib.proc.OnlyWhenRunning


Test patch: