Commit graph

30327 commits

Author SHA1 Message Date
Miss Islington (bot)
b2fff0ea85
[3.13] gh-105836: Fix asyncio.run_coroutine_threadsafe leaving underlying cancelled asyncio task running (GH-141696) (#142359)
gh-105836: Fix `asyncio.run_coroutine_threadsafe` leaving underlying cancelled asyncio task running (GH-141696)
(cherry picked from commit 14715e3a64)

Co-authored-by: Kaisheng Xu <iaalmsimon@gmail.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
2025-12-09 20:15:50 +05:30
Sam Gross
85f48038aa
[3.13] gh-142342: Fix m68k assembler operand constraints for %fpcr access (gh-142343) (#142459)
On m68k, an fmove instruction accessing %fpcr may only move from
or to a data register or a memory operand. The constraint "g" also
permits the use of address registers, which is invalid. The correct
constraint is "dm". Beginning with GCC 15, the register allocator
picks an address register in the code which causes SIGILL during
runtime.
(cherry picked from commit 02c085d48b)

Co-authored-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Co-authored-by: Michael Karcher <github@mkarcher.dialup.fu-berlin.de>
2025-12-09 14:13:35 +00:00
Miss Islington (bot)
b57d69588c
[3.13] gh-68552: fix defects policy (GH-138579) (#142367)
Co-authored-by: Ivo Bellin Salarin <nilleb@users.noreply.github.com>
Co-authored-by: Martin Panter <vadmium@users.noreply.github.com>
Co-authored-by: Ivo Bellin Salarin <ivo@nilleb.com>
2025-12-09 07:39:03 +00:00
dr-carlos
d768900ca4
[3.13] gh-141732: Fix ExceptionGroup repr changing when original exception sequence is mutated (GH-141736) (#142391)
* [3.13] gh-141732: Fix `ExceptionGroup` repr changing when original exception sequence is mutated (GH-141736)
(cherry picked from commit ff2577f56e)

Co-authored-by: dr-carlos <77367421+dr-carlos@users.noreply.github.com>
2025-12-08 18:46:55 +00:00
Miss Islington (bot)
90ca216cdc
[3.13] gh-142006: Fix HeaderWriteError in email.policy.default caused by extra newline (GH-142008) (#142362)
gh-142006: Fix HeaderWriteError in email.policy.default caused by extra newline (GH-142008)

RDM: This fixes a subtle folding error that showed up when a token exactly filled a line and was followed by whitespace and a token with no folding whitespace that was longer than a line.  In this particular circumstance the whitespace after the first token got pushed on to the next line, and then stolen to go in front of the next unfoldable token...leaving a completely empty line in the line buffer.  That line got turned in to a newline, which is RFC illegal, and the newish security check caught it.  The fix is to just delete that empty line from the buffer.
(cherry picked from commit 07eff899d8)

Co-authored-by: Paresh Joshi <rahulj9223@gmail.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
2025-12-06 16:40:07 -05:00
Miss Islington (bot)
f28409cb8c
[3.13] GH-75949: Fix argparse dropping '|' in mutually exclusive groups on line wrap (GH-142312) (#142348) 2025-12-06 15:35:01 +00:00
Thomas Wouters
627894459a Python 3.13.11 2025-12-05 17:06:33 +01:00
Miss Islington (bot)
9303573c74
[3.13] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-142216) (#142296)
[3.14] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-142216)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
therefore the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 0e4f4f1a46)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
2025-12-05 15:37:09 +00:00
Miss Islington (bot)
ddcd2acd85
[3.13] gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146) (#142210)
gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146)

* Remove quadratic behavior in node ID cache clearing



* Add news fragment

---------
(cherry picked from commit 08d8e18ad8)

Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com>
2025-12-05 15:24:38 +00:00
Miss Islington (bot)
289f29b0fe
[3.13] gh-119451: Fix a potential denial of service in http.client (GH-119454) (#142139)
gh-119451: Fix a potential denial of service in http.client (GH-119454)

Reading the whole body of the HTTP response could cause OOM if
the Content-Length value is too large even if the server does not send
a large amount of data. Now the HTTP client reads large data by chunks,
therefore the amount of consumed memory is proportional to the amount
of sent data.
(cherry picked from commit 5a4c4a033a)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
2025-12-05 16:21:57 +01:00
Serhiy Storchaka
6f47a134bc
[3.13] Revert "[3.13] gh-140797: Forbid capturing groups in re.Scanner lexicon patterns (GH-140944) (GH-140983)" (GH-142231)
Revert "[3.13] gh-140797: Forbid capturing groups in re.Scanner lexicon patterns (GH-140944) (GH-140983)"

This reverts commit ee894d2abb.
2025-12-05 15:31:34 +02:00
Miss Islington (bot)
29100c8e87
[3.13] gh-142206: multiprocessing.resource_tracker: Decode messages using older protocol (GH-142215) (#142287)
[3.14] gh-142206: multiprocessing.resource_tracker: Decode messages using older protocol (GH-142215) (GH-142285)

(cherry picked from commit 4172644d78)

Difference from the original commit: the default in 3.14 is to use
the simpler original protocol (except for filenames with newlines).
(cherry picked from commit f130b06da3)

Co-authored-by: Petr Viktorin <encukou@gmail.com>
2025-12-05 12:13:05 +00:00
Sam Gross
1a75c0fb05
[3.13] gh-142218: Fix split table dictionary crash (gh-142229) (gh-142245)
This fixes a regression introduced in gh-140558. The interpreter would
crash if we inserted a non `str` key into a split table that matches an
existing key.
(cherry picked from commit 547d8daf78)
2025-12-04 07:46:24 +00:00
Thomas Wouters
4fd884356d Python 3.13.10 2025-12-02 13:49:50 +01:00
Hugo van Kemenade
a62caed6a6
[3.13] Revert "gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) (GH-142130)" (#142185)
Revert "[3.13] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) (GH-142130)"

This reverts commit 6c922bbe28.
2025-12-02 12:04:25 +00:00
Tian Gao
9d99b5b2ca
[3.13] gh-59000: Fix pdb breakpoint resolution for class methods when… (#142172)
* [3.13] gh-59000: Fix pdb breakpoint resolution for class methods when module not imported (GH-141949)
(cherry picked from commit 5e58548ebe)

Co-authored-by: LloydZ <35182391+cocolato@users.noreply.github.com>
2025-12-02 05:07:52 +00:00
Sam Gross
01393ffbe6
[3.13] gh-142048: Fix quadratically increasing GC delays (gh-142051) (#142167)
The GC for the free threaded build would get slower with each collection due
to effectively double counting objects freed by the GC.
(cherry picked from commit eb892868b3)

Co-authored-by: Kevin Wang <kevmo314@gmail.com>
2025-12-02 00:31:36 +00:00
Hugo van Kemenade
5d7cacb1db
[3.13] GH-101100: Remove some entries from `nitpick_ignore` (GH-138464) (#141827)
(cherry picked from commit 22cb9ba8f9)

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
2025-12-01 23:26:32 +01:00
Cody Maloney
ed5d71752b
[3.13] gh-141930: Use the regular IO stack to write .pyc files for a better error message on failure (GH-141931) (#142023)
* Use open() to write the bytecode
* Convert to unittest style asserts
* Tweak news, thanks @vstinner
* Tidy
* reword NEWS, avoid word "retried"
(cherry picked from commit 656a64b37f)

Co-authored-by: Stefano Rivera <stefano@rivera.za.net>
2025-12-01 23:23:07 +01:00
Miss Islington (bot)
71fa8eb823
[3.13] gh-119342: Fix a potential denial of service in plistlib (GH-119343) (GH-142144)
Reading a specially prepared small Plist file could cause OOM because file's
read(n) preallocates a bytes object for reading the specified amount of
data. Now plistlib reads large data by chunks, therefore the upper limit of
consumed memory is proportional to the size of the input file.
(cherry picked from commit 694922cf40)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
2025-12-01 15:50:28 +00:00
Miss Islington (bot)
6c922bbe28
[3.13] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) (GH-142130)
The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a1f2)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
2025-12-01 14:22:10 +00:00
Miss Islington (bot)
b34ecec682
[3.13] gh-136063: fix quadratic-complexity parsing in email.message._parseparam (GH-136072) (#140828)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
2025-11-30 14:34:22 +02:00
Prithviraj Chaudhuri
2d05a0cc2e
[3.13] gh-140042: Removing unsafe call to sqlite3_shutdown (GH-141793) (#141812) 2025-11-30 14:33:05 +02:00
Miss Islington (bot)
99b70fe4eb
[3.13] gh-74389: gh-70560: subprocess.Popen.communicate() now ignores stdin.flush error when closed (GH-142061) (#142065)
gh-74389: gh-70560: subprocess.Popen.communicate() now ignores stdin.flush error when closed (GH-142061)

gh-70560: gh-74389: subprocess.Popen.communicate() now ignores stdin.flush error when closed

with a unittest and news entry.
(cherry picked from commit 923056b2d4)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
2025-11-28 23:33:47 -08:00
Miss Islington (bot)
12471131a7
[3.13] gh-87512: Fix subprocess using timeout= on Windows blocking with a large input= (GH-142058) (#142069)
gh-87512: Fix `subprocess` using `timeout=` on Windows blocking with a large `input=` (GH-142058)

On Windows, Popen._communicate() previously wrote to stdin synchronously, which could block indefinitely if the subprocess didn't consume input= quickly and the pipe buffer filled up. The timeout= parameter was only checked when joining the reader threads, not during the stdin write.

This change moves the Windows stdin writing to a background thread (similar to how stdout/stderr are read in threads), allowing the timeout to be properly enforced. If timeout expires, TimeoutExpired is raised promptly and the writer thread continues in the background. Subsequent calls to communicate() will join the existing writer thread.

Adds test_communicate_timeout_large_input to verify that TimeoutExpired is raised promptly when communicate() is called with large input and a timeout, even when the subprocess doesn't consume stdin quickly.

This test already passed on POSIX (where select() is used) but failed on Windows where the stdin write blocks without checking the timeout.
(cherry picked from commit 5b1862bdd8)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-11-29 07:22:46 +00:00
Miss Islington (bot)
599093e2e9
[3.13] gh-141994: Warn of XXE vulnerability in documentation of SAX feature xml.sax.handler.feature_external_ges (GH-141996) (#142073)
gh-141994: Warn of XXE vulnerability in documentation of SAX feature `xml.sax.handler.feature_external_ges` (GH-141996)

Doc/library/xml.sax.handler.rst: Warn of XXE with feature_external_ges

Related to commit baa9f33897
(cherry picked from commit 440bcb9456)

Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
2025-11-29 07:14:23 +00:00
Miss Islington (bot)
2f3024f066
[3.13] gh-141473: Fix subprocess.Popen.communicate to send input to stdin upon a subsequent post-timeout call (GH-141477) (#142060)
* gh-141473: Fix subprocess.Popen.communicate to send input to stdin upon a subsequent post-timeout call (GH-141477)

* gh-141473: Fix subprocess.Popen.communicate to send input to stdin
* Docs: Clarify that `input` is one time only on `communicate()`
* NEWS entry
* Add a regression test.

---------
(cherry picked from commit 526d7a8bb4)

Co-authored-by: Artur Jamro <artur.jamro@gmail.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>

* no assertStartsWith

---------

Co-authored-by: Artur Jamro <artur.jamro@gmail.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
2025-11-29 06:53:00 +00:00
Miss Islington (bot)
704bb69bd8
[3.13] GH-134453: Fix subprocess memoryview input handling on POSIX (GH-134949) (#142063)
GH-134453: Fix subprocess memoryview input handling on POSIX (GH-134949)

Fix inconsistent subprocess.Popen.communicate() behavior between Windows
and POSIX when using memoryview objects with non-byte elements as input.

On POSIX systems, the code was incorrectly comparing bytes written against
element count instead of byte count, causing data truncation for large
inputs with non-byte element types.

Changes:
- Cast memoryview inputs to byte view when input is already a memoryview
- Fix progress tracking to use len(input_view) instead of len(self._input)
- Add comprehensive test coverage for memoryview inputs

🤖 Generated with [Claude Code](https://claude.ai/code)



* old-man-yells-at-ReST
* Update 2025-05-30-18-37-44.gh-issue-134453.kxkA-o.rst
* assertIsNone review feedback
* fix memoryview_nonbytes test to fail without our fix on main, and have a nicer error.

Thanks to Peter Bierma @ZeroIntensity for the code review.
(cherry picked from commit cc6bc4c97f)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
2025-11-29 06:49:56 +00:00
Miss Islington (bot)
b3a0101e22
[3.13] gh-98896: resource_tracker: use json&base64 to allow arbitrary shared memory names (GH-138473) (GH-142014)
(cherry picked from commit 64d6bde38f)

Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Co-authored-by: Rani Pinchuk <33353578+rani-pinchuk@users.noreply.github.com>
2025-11-28 11:57:51 +01:00
Stan Ulbrych
3bbd669abb
[3.13] gh-141004: Document PyImport_Inittab (GH-141844) (GH-142016)
(cherry picked from commit 5f35702bb6)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
2025-11-27 14:20:58 -05:00
Petr Viktorin
9756d8c637
[3.13] gh-141909: Add PyModuleDef_Slot and earlier Py_mod_* constants to stable ABI manifest (#141910) (GH-141977)
These were added to the limited API in 3.5-3.12.
Not including them in `Misc/stable_abi.toml` was a bug.

(cherry picked from commit 202fce0dbd)
2025-11-26 15:34:57 +01:00
Miss Islington (bot)
fffa6c9ab8
[3.13] gh-141004: Document PyOS_mystr(n)icmp (GH-141760) (#141948)
gh-141004: Document `PyOS_mystr(n)icmp` (GH-141760)
(cherry picked from commit f445c452ea)

Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
2025-11-25 13:51:59 +00:00
Miss Islington (bot)
8669894b1e
[3.13] gh-140911: Ensure that UserString.index() and UserString.rindex() accept UserString as argument (GH-140945) (GH-141945)
(cherry picked from commit e6174ee981)

Co-authored-by: Krishna Chaitanya <141550576+XChaitanyaX@users.noreply.github.com>
2025-11-25 13:50:30 +00:00
Sam Gross
dbb539efc3
[3.13] gh-120158: Fix inconsistent monitoring state when setting events too frequently (gh-141845) (gh-141880)
If we overflowed the global version counter (i.e., after 2*24 calls to
`_PyMonitoring_SetEvents`), we bailed out after setting global monitoring
events but before instrumenting code objects, which led to assertion errors
later on.

Also add a `time.sleep()` to `test_free_threading.test_monitoring` to avoid
overflowing the global version counter.
(cherry picked from commit e457d60daa)
2025-11-23 15:30:37 +00:00
Miss Islington (bot)
e2d320b330
[3.13] gh-98552: Revert (unneeded, already done elsewhere) "flush std streams in the multiprocessing forkserver before fork (GH-141849)" (GH-141871) (#141873)
gh-98552: Revert (unneeded, already done elsewhere) "flush std streams in the multiprocessing forkserver before fork (GH-141849)" (GH-141871)

Revert (unneeded, already done elsewhere) "gh-98552: flush std streams in the multiprocessing forkserver before fork (GH-141849)"

This reverts commit 58badb1711.
(cherry picked from commit 614a28b3da)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
2025-11-23 02:16:25 -08:00
Miss Islington (bot)
60c02ff714
[3.13] gh-98552: flush std streams in the multiprocessing forkserver before fork (GH-141849) (#141852)
gh-98552: flush std streams in the multiprocessing forkserver before fork (GH-141849)

* flush std streams in the multiprocessing forkserver before fork

* NEWS
(cherry picked from commit 58badb1711)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
2025-11-22 12:23:30 -08:00
Hugo van Kemenade
af94f62bf6
[3.13] gh-141659: Fix bad file descriptor error in subprocess on AIX (GH-141660) (#141828)
Co-authored-by: Ayappan Perumal <ayappap2@in.ibm.com>
2025-11-21 18:10:01 +00:00
Victor Stinner
a0cbdd84af
[3.13] gh-141570: can_colorize: Expect fileno() to raise OSError, as documented (#141716) (#141748)
gh-141570: can_colorize: Expect fileno() to raise OSError, as documented (#141716)

In Fedora, we've been given a slightly incomplete reproducer for a problematic
Python 3.14 color-related change in argparse that leads to an exception when
Python is used from mod_wsgi: https://bugzilla.redhat.com/2414940

mod_wsgi replaces sys.stdout with a custom object that raises OSError on .fileno():

8460dbfcd5/src/server/wsgi_logger.c (L434-L440)

This should be supported, as the documentation of fileno explicitly says:

> An OSError is raised if the IO object does not use a file descriptor.

https://docs.python.org/3.14/library/io.html#io.IOBase.fileno

The previously expected exception inherits from OSError,
so it is still expected.

Fixes https://github.com/python/cpython/issues/141570



(cherry picked from commit 96f496a949)

Co-authored-by: Miro Hrončok <miro@hroncok.cz>
Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
2025-11-19 14:28:31 +00:00
Miss Islington (bot)
c7064e7d6b
[3.13] gh-140875: Fix handling of unclosed charrefs before EOF in HTMLParser (GH-140904) (GH-141746)
(cherry picked from commit 95296a9d40)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
2025-11-19 12:17:54 +00:00
Petr Viktorin
1bca1b4da4
[3.13] gh-140691: urllib.request: Close FTP control socket if data socket can't connect (GH-140835) (GH-141657)
(cherry picked from commit f2bce51b98)

Co-authored-by: codenamenam <bluetire27@gmail.com>
2025-11-18 13:34:40 +01:00
Krishna Chaitanya
7b3312747f
[3.13] gh-141497: Make ipaddress.IP{v4,v6}Network.hosts() always returning an iterator (GH-141547) (GH-141695)
(cherry picked from commit 6b1bdf6c7a)

Co-authored-by: Krishna Chaitanya <141550576+XChaitanyaX@users.noreply.github.com>
2025-11-18 11:43:15 +02:00
Miss Islington (bot)
61a24ea572
[3.13] gh-137109: refactor warning about threads when forking (GH-141438) (GH-141614) (GH-141639)
[3.14] gh-137109: refactor warning about threads when forking (GH-141438) (GH-141614)

This splits the OS API specific functionality to get the number of threads out
from the fallback Python method and warning raising code itself.  This way the
OS APIs can be queried before we've run
`os.register_at_fork(after_in_parent=...)` registered functions which
themselves may (re)start threads that would otherwise be detected.

This is best effort.  If the OS APIs are either unavailable or fail, the
warning generating code still falls back to looking at the Python threading
state after the CPython interpreter world has been restarted and the
after_in_parent calls have been made.  The common case for most Linux and macOS
environments should work today.

This also lines up with the existing TODO refactoring, we may choose to expose
this API to get the number of OS threads in the `os` module in the future.

Note: This is a simplified backport that maintains the void return type
for warn_about_fork_with_threads() and keeps PyErr_Clear() in the warning path,
as the error handling changes from fd8f42d3d1 are not needed in 3.14.
(cherry picked from commit 0d8fb0b852)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
2025-11-16 19:26:34 -08:00
Tian Gao
7beb7e8d35
[3.13] gh-136057: Allow step and next to step over for loops (GH-136160) (#141641)
(cherry picked from commit 8be3b2f479)
2025-11-16 22:23:03 +00:00
Sergey Miryanov
cbeada9ec7
[3.13] GH-141312: Allow only integers to longrangeiter_setstate state (GH-141317) (GH-141568)
This fixes an assertion error when the new computed start is not an integer.
(cherry picked from commit 10bec7c1eb)
2025-11-15 21:14:17 +02:00
Gregory P. Smith
b693037040
[3.13] gh-140938: Raise ValueError for infinite inputs to stdev/pstdev (GH-141531) (#141584)
gh-140938: Raise ValueError for infinite inputs to stdev/pstdev (GH-141531)

Raise ValueError for infinite inputs to stdev/pstdev

---

(cherry picked from commit f0a8bc737a)

Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
2025-11-15 04:45:28 +00:00
Pablo Galindo Salgado
7e1a0dbc07
[3.13] gh-141579: Fix perf_jit backend in sys.activate_stack_trampoline() (GH-141580) (#141582) 2025-11-15 03:17:49 +00:00
Miss Islington (bot)
fb7ae3fe83
[3.13] gh-136442: Fix unittest to return exit code 5 when setUpClass raises an exception (GH-136487) (#141577)
gh-136442: Fix unittest to return exit code 5 when setUpClass raises an exception (GH-136487)
(cherry picked from commit 53d65c840e)

Co-authored-by: Takuya UESHIN <ueshin@happy-camper.st>
2025-11-15 01:23:03 +00:00
Petr Viktorin
6916bfb800
[3.13] gh-138189: Document type slots, and other constants, as part of Limited API (GH-138190) (GH-141193)
(cherry picked from commit d81e1ef0f3)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
2025-11-13 13:28:57 +01:00
Miss Islington (bot)
e5b82c433c
[3.13] gh-103847: fix cancellation safety of asyncio.create_subprocess_exec (GH-140805) (#141447)
gh-103847: fix cancellation safety of `asyncio.create_subprocess_exec` (GH-140805)
(cherry picked from commit ef474cfafb)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
2025-11-13 17:05:01 +05:30
Miss Islington (bot)
83bd8689aa
[3.13] gh-124111: Fix TCL 9 thread detection (GH-141483)
(cherry picked from commit dc0987080e)

Co-authored-by: Michael Cho <michael@michaelcho.dev>
2025-11-12 22:44:01 +00:00