FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Reject non-str reads in the tokenizer instead of looping forever by afonsojanu · Pull Request #1553 · dateutil/dateutil · GitHub

Reject non-str reads in the tokenizer instead of looping forever - #1553

Open
afonsojanu wants to merge 1 commit into
dateutil:masterfrom
afonsojanu:fix/timelex-reject-non-str-instream-read-1428
Open

afonsojanu wants to merge 1 commit into
dateutil:masterfrom
afonsojanu:fix/timelex-reject-non-str-instream-read-1428

Conversation

Copy link
Copy Markdown

Fixes #1428.

If something that isn't a string or a real character stream reaches parse(), _timelex.__init__ only checks for a read attribute before accepting it. That passes for anything that auto-vivifies attributes, like a MagicMock, which is exactly how this got reported: a test suite accidentally passed a mock object into parse() instead of a real value.

Once that happens, get_token() calls self.instream.read(1) in a loop waiting for a falsy value to signal EOF. A MagicMock is never falsy and never returns a real empty string, so the loop never terminates, and it keeps allocating memory the whole time until the process runs out and the test suite just hangs with no useful error, which is what made this so hard to track down originally.

_timelex now checks that read() actually returned a str on every call, and raises a clear TypeError the moment it doesn't, instead of looping.

Added a regression test that reproduces the exact scenario from the issue (a MagicMock reaching parse()), verified against both the fixed and unfixed code with a bounded subprocess timeout, since the whole point of the bug is that it doesn't fail cleanly without the fix.

_timelex.__init__ only checked for a `read` attribute on the input
stream, which passes for anything that auto-vivifies attributes, like
a MagicMock. If one of those reaches parse() (typically by accident,
e.g. a mocking mistake in a caller's own test suite), get_token() never
sees a real empty string to signal EOF and keeps calling read(1)
forever, allocating memory the whole time until the process runs out.

_timelex now checks that read() actually returned a str each time it's
called, and raises a clear TypeError the first time it doesn't, rather
than looping.

Fixes dateutil#1428
afonsojanu force-pushed the fix/timelex-reject-non-str-instream-read-1428 branch from 2ea79d9 to 19bd55f Compare August 30, 2026 14:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

If a mock object reaches parse() during a unit test, unbounded memory allocation occurs

1 participant


Back | FazBrowse Home | New Git URL