Skip to content

Commit 3669efb

Browse files
authored
[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 <[email protected]> Co-authored-by: Bénédikt Tran <[email protected]> (cherry picked from commit 8ef7735)
1 parent d8b3a83 commit 3669efb

File tree

5 files changed

+31
-8
lines changed

5 files changed

+31
-8
lines changed

Lib/_colorize.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,29 @@ def get_colors(
7777

7878

7979
def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
80+
81+
def _safe_getenv(k: str, fallback: str | None = None) -> str | None:
82+
"""Exception-safe environment retrieval. See gh-128636."""
83+
try:
84+
return os.environ.get(k, fallback)
85+
except Exception:
86+
return fallback
87+
8088
if file is None:
8189
file = sys.stdout
8290

8391
if not sys.flags.ignore_environment:
84-
if os.environ.get("PYTHON_COLORS") == "0":
92+
if _safe_getenv("PYTHON_COLORS") == "0":
8593
return False
86-
if os.environ.get("PYTHON_COLORS") == "1":
94+
if _safe_getenv("PYTHON_COLORS") == "1":
8795
return True
88-
if os.environ.get("NO_COLOR"):
96+
if _safe_getenv("NO_COLOR"):
8997
return False
9098
if not COLORIZE:
9199
return False
92-
if os.environ.get("FORCE_COLOR"):
100+
if _safe_getenv("FORCE_COLOR"):
93101
return True
94-
if os.environ.get("TERM") == "dumb":
102+
if _safe_getenv("TERM") == "dumb":
95103
return False
96104

97105
if not hasattr(file, "fileno"):

Lib/_pyrepl/unix_console.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def __init__(
154154
self.input_buffer_pos = 0
155155
curses.setupterm(term or None, self.output_fd)
156156
self.term = term
157+
self.is_apple_terminal = (
158+
platform.system() == "Darwin"
159+
and os.getenv("TERM_PROGRAM") == "Apple_Terminal"
160+
)
157161

158162
@overload
159163
def _my_getstr(cap: str, optional: Literal[False] = False) -> bytes: ...
@@ -348,7 +352,7 @@ def prepare(self):
348352
tcsetattr(self.input_fd, termios.TCSADRAIN, raw)
349353

350354
# In macOS terminal we need to deactivate line wrap via ANSI escape code
351-
if platform.system() == "Darwin" and os.getenv("TERM_PROGRAM") == "Apple_Terminal":
355+
if self.is_apple_terminal:
352356
os.write(self.output_fd, b"\033[?7l")
353357

354358
self.screen = []
@@ -379,7 +383,7 @@ def restore(self):
379383
self.flushoutput()
380384
tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
381385

382-
if platform.system() == "Darwin" and os.getenv("TERM_PROGRAM") == "Apple_Terminal":
386+
if self.is_apple_terminal:
383387
os.write(self.output_fd, b"\033[?7h")
384388

385389
if hasattr(self, "old_sigwinch"):

Lib/test/support/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2754,7 +2754,7 @@ def no_color():
27542754
from .os_helper import EnvironmentVarGuard
27552755

27562756
with (
2757-
swap_attr(_colorize, "can_colorize", lambda file=None: False),
2757+
swap_attr(_colorize, "can_colorize", lambda *, file=None: False),
27582758
EnvironmentVarGuard() as env,
27592759
):
27602760
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")

Lib/test/test_pyrepl/test_unix_console.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,12 @@ def test_getheightwidth_with_invalid_environ(self, _os_write):
327327
self.assertIsInstance(console.getheightwidth(), tuple)
328328
os.environ = []
329329
self.assertIsInstance(console.getheightwidth(), tuple)
330+
331+
@unittest.skipUnless(sys.platform == "darwin", "requires macOS")
332+
def test_restore_with_invalid_environ_on_macos(self, _os_write):
333+
# gh-128636 for macOS
334+
console = UnixConsole(term="xterm")
335+
with os_helper.EnvironmentVarGuard():
336+
os.environ = []
337+
console.prepare() # needed to call restore()
338+
console.restore() # this should succeed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash in PyREPL when os.environ is overwritten with an invalid value for
2+
mac

0 commit comments

Comments
 (0)