diff options
author | Tian Gao <gaogaotiantian@hotmail.com> | 2023-05-31 20:51:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-31 20:51:46 (GMT) |
commit | d944d873b2d7a627c20246762e931f9d4fcf8fe7 (patch) | |
tree | 308cdc00c7a065c65b52bae3ead9946ef2f3b185 | |
parent | ed86e14b1672f32f0a31d72070e93d361ee0e2b4 (diff) | |
download | cpython-d944d873b2d7a627c20246762e931f9d4fcf8fe7.zip cpython-d944d873b2d7a627c20246762e931f9d4fcf8fe7.tar.gz cpython-d944d873b2d7a627c20246762e931f9d4fcf8fe7.tar.bz2 |
gh-103464: Add checks for arguments of pdb commands (GH-103465)
-rwxr-xr-x | Lib/pdb.py | 64 | ||||
-rw-r--r-- | Lib/test/test_pdb.py | 36 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst | 1 |
3 files changed, 90 insertions, 11 deletions
@@ -644,7 +644,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): try: bnum = int(arg) except: - self.error("Usage: commands [bnum]\n ...\n end") + self._print_invalid_arg(arg) return try: self.get_bpbynumber(bnum) @@ -941,14 +941,22 @@ class Pdb(bdb.Bdb, cmd.Cmd): condition evaluates to true. """ args = arg.split() - try: - count = int(args[1].strip()) - except: + if not args: + self.error('Breakpoint number expected') + return + if len(args) == 1: count = 0 + elif len(args) == 2: + try: + count = int(args[1]) + except ValueError: + self._print_invalid_arg(arg) + return + else: + self._print_invalid_arg(arg) + return try: bp = self.get_bpbynumber(args[0].strip()) - except IndexError: - self.error('Breakpoint number expected') except ValueError as err: self.error(err) else: @@ -1025,6 +1033,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): An arrow indicates the "current frame", which determines the context of most commands. 'bt' is an alias for this command. """ + if arg: + self._print_invalid_arg(arg) + return self.print_stack_trace() do_w = do_where do_bt = do_where @@ -1112,6 +1123,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): (either in a function that is called or in the current function). """ + if arg: + self._print_invalid_arg(arg) + return self.set_step() return 1 do_s = do_step @@ -1122,6 +1136,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Continue execution until the next line in the current function is reached or it returns. """ + if arg: + self._print_invalid_arg(arg) + return self.set_next(self.curframe) return 1 do_n = do_next @@ -1153,6 +1170,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Continue execution until the current function returns. """ + if arg: + self._print_invalid_arg(arg) + return self.set_return(self.curframe) return 1 do_r = do_return @@ -1162,6 +1182,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Continue execution, only stop when a breakpoint is encountered. """ + if arg: + self._print_invalid_arg(arg) + return if not self.nosigint: try: Pdb._previous_sigint_handler = \ @@ -1256,6 +1279,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Print the argument list of the current function. """ + if arg: + self._print_invalid_arg(arg) + return co = self.curframe.f_code dict = self.curframe_locals n = co.co_argcount + co.co_kwonlyargcount @@ -1274,6 +1300,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Print the return value for the last return of a function. """ + if arg: + self._print_invalid_arg(arg) + return if '__return__' in self.curframe_locals: self.message(repr(self.curframe_locals['__return__'])) else: @@ -1390,6 +1419,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): List the whole source code for the current function or frame. """ + if arg: + self._print_invalid_arg(arg) + return filename = self.curframe.f_code.co_filename breaklist = self.get_file_breaks(filename) try: @@ -1570,7 +1602,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): Delete the specified alias. """ args = arg.split() - if len(args) == 0: return + if len(args) == 0: + self._print_invalid_arg(arg) + return if args[0] in self.aliases: del self.aliases[args[0]] @@ -1723,7 +1757,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): lineno = max(1, lineno) return lines, lineno - def _help_message_from_doc(self, doc): + def _help_message_from_doc(self, doc, usage_only=False): lines = [line.strip() for line in doc.rstrip().splitlines()] if not lines: return "No help message found." @@ -1739,10 +1773,24 @@ class Pdb(bdb.Bdb, cmd.Cmd): elif i < usage_end: prefix = " " else: + if usage_only: + break prefix = "" formatted.append(indent + prefix + line) return "\n".join(formatted) + def _print_invalid_arg(self, arg): + """Return the usage string for a function.""" + + self.error(f"Invalid argument: {arg}") + + # Yes it's a bit hacky. Get the caller name, get the method based on + # that name, and get the docstring from that method. + # This should NOT fail if the caller is a method of this class. + doc = inspect.getdoc(getattr(self, sys._getframe(1).f_code.co_name)) + if doc is not None: + self.message(self._help_message_from_doc(doc, usage_only=True)) + # Collect all command help into docstring, if not run with -OO if __doc__ is not None: diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 83c7cdf..277400e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -334,9 +334,11 @@ def test_pdb_breakpoint_commands(): (Pdb) commands 10 *** cannot set commands: Breakpoint number 10 out of range (Pdb) commands a - *** Usage: commands [bnum] - ... - end + *** Invalid argument: a + Usage: (Pdb) commands [bpnumber] + (com) ... + (com) end + (Pdb) (Pdb) commands 4 *** cannot set commands: Breakpoint 4 already deleted (Pdb) break 6, undefined @@ -908,6 +910,34 @@ def test_pdb_skip_modules(): (Pdb) continue """ +def test_pdb_invalid_arg(): + """This tests pdb commands that have invalid arguments + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... pass + + >>> with PdbTestInput([ + ... 'a = 3', + ... 'll 4', + ... 'step 1', + ... 'continue' + ... ]): + ... test_function() + > <doctest test.test_pdb.test_pdb_invalid_arg[0]>(3)test_function() + -> pass + (Pdb) a = 3 + *** Invalid argument: = 3 + Usage: a(rgs) + (Pdb) ll 4 + *** Invalid argument: 4 + Usage: ll | longlist + (Pdb) step 1 + *** Invalid argument: 1 + Usage: s(tep) + (Pdb) continue + """ + # Module for testing skipping of module that makes a callback mod = types.ModuleType('module_to_skip') diff --git a/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst b/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst new file mode 100644 index 0000000..6afaeb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-12-03-03-27.gh-issue-103464.Oa_8IW.rst @@ -0,0 +1 @@ +Provide helpful usage messages when parsing incorrect :mod:`pdb` commands. |