mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.13] gh-128636: Fix crash in PyREPL when os.environ is overwritten with an invalid value for macOS (GH-138089) (GH-138942)
Signed-off-by: yihong0618 <zouzou0208@gmail.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
(cherry picked from commit 8ef7735c53)
This commit is contained in:
parent
d8b3a83cf2
commit
3669efb890
5 changed files with 31 additions and 8 deletions
|
|
@ -77,21 +77,29 @@ def get_colors(
|
||||||
|
|
||||||
|
|
||||||
def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
|
def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
|
||||||
|
|
||||||
|
def _safe_getenv(k: str, fallback: str | None = None) -> str | None:
|
||||||
|
"""Exception-safe environment retrieval. See gh-128636."""
|
||||||
|
try:
|
||||||
|
return os.environ.get(k, fallback)
|
||||||
|
except Exception:
|
||||||
|
return fallback
|
||||||
|
|
||||||
if file is None:
|
if file is None:
|
||||||
file = sys.stdout
|
file = sys.stdout
|
||||||
|
|
||||||
if not sys.flags.ignore_environment:
|
if not sys.flags.ignore_environment:
|
||||||
if os.environ.get("PYTHON_COLORS") == "0":
|
if _safe_getenv("PYTHON_COLORS") == "0":
|
||||||
return False
|
return False
|
||||||
if os.environ.get("PYTHON_COLORS") == "1":
|
if _safe_getenv("PYTHON_COLORS") == "1":
|
||||||
return True
|
return True
|
||||||
if os.environ.get("NO_COLOR"):
|
if _safe_getenv("NO_COLOR"):
|
||||||
return False
|
return False
|
||||||
if not COLORIZE:
|
if not COLORIZE:
|
||||||
return False
|
return False
|
||||||
if os.environ.get("FORCE_COLOR"):
|
if _safe_getenv("FORCE_COLOR"):
|
||||||
return True
|
return True
|
||||||
if os.environ.get("TERM") == "dumb":
|
if _safe_getenv("TERM") == "dumb":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not hasattr(file, "fileno"):
|
if not hasattr(file, "fileno"):
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,10 @@ def __init__(
|
||||||
self.input_buffer_pos = 0
|
self.input_buffer_pos = 0
|
||||||
curses.setupterm(term or None, self.output_fd)
|
curses.setupterm(term or None, self.output_fd)
|
||||||
self.term = term
|
self.term = term
|
||||||
|
self.is_apple_terminal = (
|
||||||
|
platform.system() == "Darwin"
|
||||||
|
and os.getenv("TERM_PROGRAM") == "Apple_Terminal"
|
||||||
|
)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _my_getstr(cap: str, optional: Literal[False] = False) -> bytes: ...
|
def _my_getstr(cap: str, optional: Literal[False] = False) -> bytes: ...
|
||||||
|
|
@ -348,7 +352,7 @@ def prepare(self):
|
||||||
tcsetattr(self.input_fd, termios.TCSADRAIN, raw)
|
tcsetattr(self.input_fd, termios.TCSADRAIN, raw)
|
||||||
|
|
||||||
# In macOS terminal we need to deactivate line wrap via ANSI escape code
|
# In macOS terminal we need to deactivate line wrap via ANSI escape code
|
||||||
if platform.system() == "Darwin" and os.getenv("TERM_PROGRAM") == "Apple_Terminal":
|
if self.is_apple_terminal:
|
||||||
os.write(self.output_fd, b"\033[?7l")
|
os.write(self.output_fd, b"\033[?7l")
|
||||||
|
|
||||||
self.screen = []
|
self.screen = []
|
||||||
|
|
@ -379,7 +383,7 @@ def restore(self):
|
||||||
self.flushoutput()
|
self.flushoutput()
|
||||||
tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
|
tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
|
||||||
|
|
||||||
if platform.system() == "Darwin" and os.getenv("TERM_PROGRAM") == "Apple_Terminal":
|
if self.is_apple_terminal:
|
||||||
os.write(self.output_fd, b"\033[?7h")
|
os.write(self.output_fd, b"\033[?7h")
|
||||||
|
|
||||||
if hasattr(self, "old_sigwinch"):
|
if hasattr(self, "old_sigwinch"):
|
||||||
|
|
|
||||||
|
|
@ -2754,7 +2754,7 @@ def no_color():
|
||||||
from .os_helper import EnvironmentVarGuard
|
from .os_helper import EnvironmentVarGuard
|
||||||
|
|
||||||
with (
|
with (
|
||||||
swap_attr(_colorize, "can_colorize", lambda file=None: False),
|
swap_attr(_colorize, "can_colorize", lambda *, file=None: False),
|
||||||
EnvironmentVarGuard() as env,
|
EnvironmentVarGuard() as env,
|
||||||
):
|
):
|
||||||
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")
|
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")
|
||||||
|
|
|
||||||
|
|
@ -327,3 +327,12 @@ def test_getheightwidth_with_invalid_environ(self, _os_write):
|
||||||
self.assertIsInstance(console.getheightwidth(), tuple)
|
self.assertIsInstance(console.getheightwidth(), tuple)
|
||||||
os.environ = []
|
os.environ = []
|
||||||
self.assertIsInstance(console.getheightwidth(), tuple)
|
self.assertIsInstance(console.getheightwidth(), tuple)
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "darwin", "requires macOS")
|
||||||
|
def test_restore_with_invalid_environ_on_macos(self, _os_write):
|
||||||
|
# gh-128636 for macOS
|
||||||
|
console = UnixConsole(term="xterm")
|
||||||
|
with os_helper.EnvironmentVarGuard():
|
||||||
|
os.environ = []
|
||||||
|
console.prepare() # needed to call restore()
|
||||||
|
console.restore() # this should succeed
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix crash in PyREPL when os.environ is overwritten with an invalid value for
|
||||||
|
mac
|
||||||
Loading…
Add table
Add a link
Reference in a new issue