Repository: pwndbg/pwndbg

Issue:
`telescope -r <num>` is broken
```
pwndbg> telescope -r 30
Traceback (most recent call last):
  File "/home/gsgx/code/pwndbg/pwndbg/commands/__init__.py", line 145, in __call__
    return self.function(*args, **kwargs)
  File "/home/gsgx/code/pwndbg/pwndbg/commands/__init__.py", line 216, in _OnlyWhenRunning
    return function(*a, **kw)
  File "/home/gsgx/code/pwndbg/pwndbg/commands/telescope.py", line 191, in telescope
    telescope.offset += i
UnboundLocalError: local variable 'i' referenced before assignment
```
`telescope -r` works fine though.


Discussion:

Resolving patch:
diff --git a/pwndbg/commands/telescope.py b/pwndbg/commands/telescope.py
--- a/pwndbg/commands/telescope.py
+++ b/pwndbg/commands/telescope.py
@@ -49,12 +49,6 @@
     ($sp by default)
     """
 )
-parser.add_argument(
-    "address", nargs="?", default=None, type=int, help="The address to telescope at."
-)
-parser.add_argument(
-    "count", nargs="?", default=telescope_lines, type=int, help="The number of lines to show."
-)
 parser.add_argument(
     "-r",
     "--reverse",
@@ -64,6 +58,14 @@
     help="Show <count> previous addresses instead of next ones",
 )
 
+parser.add_argument(
+    "address", nargs="?", default=None, type=int, help="The address to telescope at."
+)
+
+parser.add_argument(
+    "count", nargs="?", default=telescope_lines, type=int, help="The number of lines to show."
+)
+
 
 @pwndbg.commands.ArgparsedCommand(parser)
 @pwndbg.commands.OnlyWhenRunning
@@ -84,15 +86,15 @@ def telescope(address=None, count=telescope_lines, to_string=False, reverse=Fals
     delimiter = T.delimiter(offset_delimiter)
     separator = T.separator(offset_separator)
 
-    # Allow invocation of telescope -r to dump previous addresses
-    if reverse:
-        address -= (count - 1) * ptrsize
-
     # Allow invocation of "telescope 20" to dump 20 bytes at the stack pointer
     if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR and not pwndbg.gdblib.memory.peek(address):
         count = address
         address = pwndbg.gdblib.regs.sp
 
+    # Allow invocation of telescope -r to dump previous addresses
+    if reverse:
+        address -= (count - 1) * ptrsize
+
     # Allow invocation of "telescope a b" to dump all bytes from A to B
     if int(address) <= int(count):
         # adjust count if it is an address. use ceil division as count is number of
@@ -103,7 +105,6 @@ def telescope(address=None, count=telescope_lines, to_string=False, reverse=Fals
     reg_values = collections.defaultdict(lambda: [])
     for reg in pwndbg.gdblib.regs.common:
         reg_values[pwndbg.gdblib.regs[reg]].append(reg)
-    # address    = pwndbg.gdblib.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, address)
 
     start = address
     stop = address + (count * ptrsize)


Test patch:
diff --git a/tests/test_command_telescope.py b/tests/test_command_telescope.py
--- a/tests/test_command_telescope.py
+++ b/tests/test_command_telescope.py
@@ -1,5 +1,8 @@
+import re
+
 import gdb
 
+import pwndbg.gdblib
 import tests
 
 TELESCOPE_BINARY = tests.binaries.get("telescope_binary.out")
@@ -55,5 +58,27 @@ def test_command_telescope_n_records(start_binary):
 
     n = 3
     gdb.execute("entry")
-    result_str = gdb.execute("telescope $rsp {}".format(n), to_string=True)
-    assert len(result_str.strip("\n").split("\n")) == n
+    result = gdb.execute("telescope $rsp {}".format(n), to_string=True).strip().splitlines()
+    assert len(result) == n
+
+
+def test_telescope_command_with_address_as_count(start_binary):
+    start_binary(TELESCOPE_BINARY)
+
+    out = gdb.execute("telescope 2", to_string=True).splitlines()
+    rsp = pwndbg.gdblib.regs.rsp
+
+    assert len(out) == 2
+    assert out[0] == "00:0000│ rsp %#x ◂— 0x1" % rsp
+
+    expected = r"01:0008│     %#x —▸ 0x[0-9a-f]+ ◂— '%s'" % (rsp + 8, pwndbg.proc.exe)
+    assert re.search(expected, out[1])
+
+
+def test_telescope_command_with_address_as_count_and_reversed_flag(start_binary):
+    start_binary(TELESCOPE_BINARY)
+
+    out = gdb.execute("telescope -r 2", to_string=True).splitlines()
+    rsp = pwndbg.gdblib.regs.rsp
+
+    assert out == ["00:0000│     %#x ◂— 0x0" % (rsp - 8), "01:0008│ rsp %#x ◂— 0x1" % rsp]