summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/pdb.rst2
-rwxr-xr-xLib/pdb.py33
-rw-r--r--Lib/test/test_pdb.py22
-rw-r--r--Misc/NEWS.d/next/Library/2023-11-04-01-20-23.gh-issue-111719.fUiKBD.rst1
4 files changed, 51 insertions, 7 deletions
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index 002eeef..bbc6aac 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -580,7 +580,7 @@ can be overridden by the local file.
Create an alias called *name* that executes *command*. The *command* must
*not* be enclosed in quotes. Replaceable parameters can be indicated by
- ``%1``, ``%2``, and so on, while ``%*`` is replaced by all the parameters.
+ ``%1``, ``%2``, ... and ``%9``, while ``%*`` is replaced by all the parameters.
If *command* is omitted, the current alias for *name* is shown. If no
arguments are given, all aliases are listed.
diff --git a/Lib/pdb.py b/Lib/pdb.py
index dbb7f55..a4b02e0 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -597,11 +597,20 @@ class Pdb(bdb.Bdb, cmd.Cmd):
args = line.split()
while args[0] in self.aliases:
line = self.aliases[args[0]]
- ii = 1
- for tmpArg in args[1:]:
- line = line.replace("%" + str(ii),
- tmpArg)
- ii += 1
+ for idx in range(1, 10):
+ if f'%{idx}' in line:
+ if idx >= len(args):
+ self.error(f"Not enough arguments for alias '{args[0]}'")
+ # This is a no-op
+ return "!"
+ line = line.replace(f'%{idx}', args[idx])
+ elif '%*' not in line:
+ if idx < len(args):
+ self.error(f"Too many arguments for alias '{args[0]}'")
+ # This is a no-op
+ return "!"
+ break
+
line = line.replace("%*", ' '.join(args[1:]))
args = line.split()
# split into ';;' separated commands
@@ -616,6 +625,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
# Replace all the convenience variables
line = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'__pdb_convenience_variables["\1"]', line)
+
return line
def onecmd(self, line):
@@ -1797,7 +1807,18 @@ class Pdb(bdb.Bdb, cmd.Cmd):
else:
self.error(f"Unknown alias '{args[0]}'")
else:
- self.aliases[args[0]] = ' '.join(args[1:])
+ # Do a validation check to make sure no replaceable parameters
+ # are skipped if %* is not used.
+ alias = ' '.join(args[1:])
+ if '%*' not in alias:
+ consecutive = True
+ for idx in range(1, 10):
+ if f'%{idx}' not in alias:
+ consecutive = False
+ if f'%{idx}' in alias and not consecutive:
+ self.error("Replaceable parameters must be consecutive")
+ return
+ self.aliases[args[0]] = alias
def do_unalias(self, arg):
"""unalias name
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index ff9e7c2..5508f7b 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -671,6 +671,14 @@ def test_pdb_alias_command():
... 'pi o',
... 's',
... 'ps',
+ ... 'alias myp p %2',
+ ... 'alias myp',
+ ... 'alias myp p %1',
+ ... 'myp',
+ ... 'myp 1',
+ ... 'myp 1 2',
+ ... 'alias repeat_second_arg p "%* %2"',
+ ... 'repeat_second_arg 1 2 3',
... 'continue',
... ]):
... test_function()
@@ -692,6 +700,20 @@ def test_pdb_alias_command():
(Pdb) ps
self.attr1 = 10
self.attr2 = str
+ (Pdb) alias myp p %2
+ *** Replaceable parameters must be consecutive
+ (Pdb) alias myp
+ *** Unknown alias 'myp'
+ (Pdb) alias myp p %1
+ (Pdb) myp
+ *** Not enough arguments for alias 'myp'
+ (Pdb) myp 1
+ 1
+ (Pdb) myp 1 2
+ *** Too many arguments for alias 'myp'
+ (Pdb) alias repeat_second_arg p "%* %2"
+ (Pdb) repeat_second_arg 1 2 3
+ '1 2 3 2'
(Pdb) continue
"""
diff --git a/Misc/NEWS.d/next/Library/2023-11-04-01-20-23.gh-issue-111719.fUiKBD.rst b/Misc/NEWS.d/next/Library/2023-11-04-01-20-23.gh-issue-111719.fUiKBD.rst
new file mode 100644
index 0000000..1d3b948
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-11-04-01-20-23.gh-issue-111719.fUiKBD.rst
@@ -0,0 +1 @@
+Add extra argument validation for ``alias`` command in :mod:`pdb`