This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: readline 8.1 enables the bracketed paste mode by default
Type: behavior Stage: resolved
Components: Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: asmeurer, dtrodrigues, fxcoudert, gregory.p.smith, hroncok, miss-islington, petr.viktorin, twouters, vstinner
Priority: normal Keywords: patch

Created on 2021-01-03 20:52 by dtrodrigues, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 24108 merged dtrodrigues, 2021-01-05 05:06
PR 24545 merged miss-islington, 2021-02-15 23:28
PR 24546 merged miss-islington, 2021-02-15 23:28
Messages (19)
msg384297 - (view) Author: Dustin Rodrigues (dtrodrigues) * Date: 2021-01-03 20:52
Readline 8.1 enables bracketed paste by default. Package managers like Homebrew for macOS and distributions like Arch Linux which use the latest version of readline (released December 2020) now have new behavior when pasting multiline strings into the python REPL. Disabling bracketed paste on 8.1 reverts to the expected behavior, and enabling bracketed paste on 8.0 also reproduces the behavior. Further information in https://github.com/Homebrew/homebrew-core/issues/68193

Example with bracketed paste on:
$ cat in
1+2
3+4
5+6

$ pbcopy < in
$ /usr/local/Cellar/python\@3.9/3.9.1_3/bin/python3
Python 3.9.1 (default, Dec 28 2020, 11:22:14) 
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+2
3+4
5+6

  File "<stdin>", line 1
    1+2
3+4
5+6


       ^
SyntaxError: multiple statements found while compiling a single statement
>>> 



Example with it off:
$ /usr/local/bin/python3
Python 3.9.1 (v3.9.1:1e5d33e9b9, Dec  7 2020, 12:10:52) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+2
3
>>> 3+4
7
>>> 5+6
11
>>>
msg384330 - (view) Author: FX Coudert (fxcoudert) * Date: 2021-01-04 15:34
This bug is present in all versions since the 3.6 branch at least, but was only triggered when users' readline settings explicitly enabled bracketed-paste. Previous reports: https://bugs.python.org/issue32019 and https://bugs.python.org/issue39820 Longer discussion (on a more extensive feature request) at https://bugs.python.org/issue38747

The new factor is that readline 8.1 now enables bracketed-paste by default. So the broken behaviour is seen for Python built with the latest readline, with no specific setting.

Python should probably in the long term be improved to handle bracketed-paste, which will make a nicer user experience. But in the short term, it should communication with readline to disable bracketed-paste at runtime, and restore the previous behaviour.
msg385245 - (view) Author: Dustin Rodrigues (dtrodrigues) * Date: 2021-01-19 03:42
The linked PR disables bracketed paste regardless of if the user has it as a configuration option or if Python was configured with a version of readline which defaults to on for bracketed paste. Is this a viable approach?
msg385855 - (view) Author: Dustin Rodrigues (dtrodrigues) * Date: 2021-01-28 12:55
Bumping this issue because it's a bug affecting all users who build or use a Python built with the current version of readline, to include all macOS HomeBrew and Arch Linux users who use the python from the respective package managers.
msg386929 - (view) Author: Miro Hrončok (hroncok) * Date: 2021-02-13 21:08
This also affects Fedora 34+
msg386981 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 08:15
> Readline 8.1 enables bracketed paste by default.

Can you try to find why it changed the default? Why should Python change the default readline default behavior?
msg386982 - (view) Author: Miro Hrončok (hroncok) * Date: 2021-02-15 08:21
https://lists.gnu.org/archive/html/bug-readline/2020-11/msg00010.html
https://lists.gnu.org/archive/html/bug-bash/2020-10/msg00048.html
https://lists.gnu.org/archive/html/bug-bash/2020-10/msg00087.html
msg386987 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 09:29
I didn't know "bracketed paste mode". It seems like a protocol between a terminal and the user to add markers before/after a pasted text.
https://cirw.in/blog/bracketed-paste

"""
In summary:

1. Enable bracketed paste: printf "\e[?2004h"
2. Wait for paste to start: you’ll see \e[200~ on STDIN.
3. Wait for paste to stop: you’ll see \e[201~ on STDIN.
4. Disable bracketed paste: printf "\e[?2004l"
"""

I understand that this mode prevents to run arbitrary command when pasting blindly an untrusted command copied from a webpage, like this example:
https://thejh.net/misc/website-terminal-copy-paste

It can be enabled explicitly by adding "set enable-bracketed-paste" on to your ~/.inputrc configuration file.
msg386988 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 09:46
On my Fedora 33 (readline-8.0-5.fc33.x86_64), I enabled the bracketed paste mode by adding "set enable-bracketed-paste" on to my ~/.inputrc config file.

When I test https://thejh.net/misc/website-terminal-copy-paste : the evil command is no long executed.

If I copy/paste "1+1" and "2+2" commands (two lines pasted at once) manually in the Python REPL, they are no longer executed immediately, Python waits for me pressing ENTER to execute, *as expected*:

----
$ ./python 
Python 3.10.0a5+ (heads/master:fcbe0cb04d, Feb 15 2021, 10:30:10) 
[GCC 10.2.1 20201125 (Red Hat 10.2.1-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+1
2+2
----

But using "./python -i < commands", each line is executed immediately and Python exits after displaying the results:

---
$ cat commands 
1+1
2+2

$ ./python -i < commands
Python 3.10.0a5+ (heads/master:fcbe0cb04d, Feb 15 2021, 10:30:10) 
>>> 2
>>> 4
>>> 
---

If I disable again bracketed mode (ex: remove ~/.inputrc file in my case), when I copy/paste manually the two commands at once, they are executed again, as expected:
---
$ ./python
>>> 1+1
2
>>> 2+2
4
---

The bracketed paste mode can be enabled explicitly in Python with this patch to simulate readline 8.1 default behavior:

diff --git a/Modules/readline.c b/Modules/readline.c
index c900e07954..ce8662c000 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -217,6 +217,7 @@ readline_read_init_file_impl(PyObject *module, PyObject *filename_obj)
         errno = rl_read_init_file(NULL);
     if (errno)
         return PyErr_SetFromErrno(PyExc_OSError);
+    rl_variable_bind ("enable-bracketed-paste", "on");
     Py_RETURN_NONE;
 }
 


All of these behavior look consistent, correct and expected.

Note: When I redirect Python output into a file, I cannot see "\e[?2004h" (likely because stdout is not a TTY if it's redirected into a file), so I'm not sure how to check if this escape sequence is injected in Python stdout or not.
msg386989 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 09:46
Oh, I forgot to mention that I ran my tests in Gnome Terminal 3.38.1-2.fc33.
msg386993 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 10:03
Related issue: test_pdb_interaction_doctest test of pytest fails on Fedora Rawhide because of a "\x1b[?2004h" string:
* https://github.com/pytest-dev/pytest/issues/8256
* https://bugzilla.redhat.com/show_bug.cgi?id=1892612

It fails with readline 8.1 which enables bracketed mode by default, but it fails with any readline version if ~/.inputrc contains "set enable-bracketed-paste on".
msg386994 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 10:07
https://lists.gnu.org/archive/html/bug-readline/2020-11/msg00010.html
says that bracketed mode is turned off if the terminal type is "dumb".

Setting TERM env var to dumb gives me a surprising behavior when I paste "1+1\n2+2" in Python REPL:
---
$ TERM=dumb python3
Python 3.9.1 (default, Jan 20 2021, 00:00:00) 
>>> ^J1+1^J2+2^J
---

If I press ENTER, I get:
---
>>> ^J1+1^J2+2^J
  File "<stdin>", line 1
    
1+1
2+2

    ^
SyntaxError: multiple statements found while compiling a single statement
>>> 
---

Note: if I redirect Python output into a file ("python3 > output"), I get a different behavior since stdout is no longer a TTY.
msg386995 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 10:17
There are different things:

* Bracketed paste mode prevents to execute malicious command copied from evil internet web pages
* Python REPL is not really convenient in the bracked paste mode: bpo-39820
* Users are not used to the bracketed mode which gives a surprising behavior in Python REPL
* Copy/paste in a shell running in a graphical terminal is fine in bracketed mode, since users running a shell are used to modify a command before running and to run manually a command by pressing ENTER
* The bracketed paste mode causes test failures in applications (like pytest test suite) which doesn't support it.
* It is not easy/convenient to opt-out for the bracketed paste mode.

For all these reasons, it sounds reasonable to disable the readline bracketed paste mode by default in Python, even if it's enabled explicitly in ~/.inputrc.

If an user opts in for the bracketed paste mode, it is more likely to prevent running malicious commands in a shell, rather than not executing immediately commands executed in Python.

Once the bpo-39820 will be fixed, we can reconsider to leave the bracketed paste mode default unchanged (no longer disable it explicitly).
msg387061 - (view) Author: Aaron Meurer (asmeurer) Date: 2021-02-15 21:15
Instead of enabling it by default, why not just keep it but emulate the old behavior by splitting and buffering the input lines? That way you still get some of the benefits of bracketed paste, i.e., faster pasting, but without the hard work of fixing the REPL to actually support native multiline editing + execing multiline statements (the broken "simple" design).
msg387062 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 21:16
> Instead of enabling it by default, why not just keep it but emulate the old behavior by splitting and buffering the input lines?

PR 24108 change can and should be backported to 3.8 and 3.9 branches.

REPL enhancements can only land in the master branch and should be done in bpo-39820.
msg387071 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-15 23:28
New changeset 755f3c1521b422bc2177013d289f5439975fdc4f by Dustin Rodrigues in branch 'master':
bpo-42819, readline: Disable bracketed paste (GH-24108)
https://github.com/python/cpython/commit/755f3c1521b422bc2177013d289f5439975fdc4f
msg387072 - (view) Author: miss-islington (miss-islington) Date: 2021-02-15 23:47
New changeset f9d7c12b6c7ab978cb6c61a666bc06dd3fec9b3e by Miss Islington (bot) in branch '3.8':
bpo-42819, readline: Disable bracketed paste (GH-24108)
https://github.com/python/cpython/commit/f9d7c12b6c7ab978cb6c61a666bc06dd3fec9b3e
msg387077 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-16 00:18
New changeset 85fd9f4e45ee95e2608dbc8cc6d4fe28e4d2abc4 by Miss Islington (bot) in branch '3.9':
bpo-42819, readline: Disable bracketed paste (GH-24108) (GH-24545)
https://github.com/python/cpython/commit/85fd9f4e45ee95e2608dbc8cc6d4fe28e4d2abc4
msg387078 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-02-16 00:19
Thanks Dustin for the bug report *and* the fix! I close the issue.

For people who want to support bracketed paste mode in Python, please disuss it in bpo-39820.
History
Date User Action Args
2022-04-11 14:59:39adminsetgithub: 86985
2021-02-16 00:19:11vstinnersetstatus: open -> closed
versions: + Python 3.8, Python 3.9, Python 3.10
messages: + msg387078

resolution: fixed
stage: patch review -> resolved
2021-02-16 00:18:10vstinnersetmessages: + msg387077
2021-02-15 23:47:59miss-islingtonsetmessages: + msg387072
2021-02-15 23:28:55miss-islingtonsetpull_requests: + pull_request23329
2021-02-15 23:28:47miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request23328
2021-02-15 23:28:43vstinnersetmessages: + msg387071
2021-02-15 21:16:39vstinnersetmessages: + msg387062
2021-02-15 21:15:01asmeurersetnosy: + asmeurer
messages: + msg387061
2021-02-15 10:17:49vstinnersetmessages: + msg386995
2021-02-15 10:09:56vstinnersettitle: readline 8.1 bracketed paste -> readline 8.1 enables the bracketed paste mode by default
2021-02-15 10:07:56vstinnersetmessages: + msg386994
2021-02-15 10:03:33vstinnersetmessages: + msg386993
2021-02-15 09:46:51vstinnersetmessages: + msg386989
2021-02-15 09:46:06vstinnersetmessages: + msg386988
2021-02-15 09:29:32vstinnersetmessages: + msg386987
2021-02-15 08:21:36hroncoksetmessages: + msg386982
2021-02-15 08:15:10vstinnersetnosy: + gregory.p.smith
messages: + msg386981
2021-02-13 21:08:26hroncoksetnosy: + vstinner, petr.viktorin, hroncok
messages: + msg386929
2021-01-28 14:38:12ned.deilysetnosy: + twouters
2021-01-28 12:55:28dtrodriguessetmessages: + msg385855
2021-01-19 03:42:01dtrodriguessetmessages: + msg385245
2021-01-05 05:06:20dtrodriguessetkeywords: + patch
stage: patch review
pull_requests: + pull_request22937
2021-01-04 15:34:30fxcoudertsetnosy: + fxcoudert
messages: + msg384330
2021-01-03 20:52:35dtrodriguescreate