From dba9f4e946d0647bd045d5c0a927cc606bdc0b28 Mon Sep 17 00:00:00 2001 From: grub-basket Date: Sun, 19 Jul 2026 13:56:22 -0700 Subject: [PATCH] Guard git status parser against infinite loop on unknown entry parseGitStatus advanced 'pos' only from a successful pattern match. On an unrecognized status ident it hit 'continue' without advancing, re-reading the same character forever and spamming warnings. A malformed record could also make pattern.match() return None, crashing on match.end(). Handle both cases by resyncing to the next NUL-terminated entry (or ending the loop if none remains). --- gitfourchette/gitdriver/parsers.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/gitfourchette/gitdriver/parsers.py b/gitfourchette/gitdriver/parsers.py index 26ba9e7e..8d9264d2 100644 --- a/gitfourchette/gitdriver/parsers.py +++ b/gitfourchette/gitdriver/parsers.py @@ -79,13 +79,19 @@ def parseGitStatus(stdout: str, workdir: str): while pos < limit: ident = stdout[pos] - try: - pattern = _gitStatusPatterns[ident] - except KeyError: - logging.warning(f"unknown git status ident '{ident}'") + pattern = _gitStatusPatterns.get(ident) + match = pattern.match(stdout, pos) if pattern is not None else None + + if match is None: + # Unknown ident or malformed record. Skip to the next NUL-terminated + # entry rather than re-reading the same character forever. + logging.warning(f"skipping unparseable git status entry (ident '{ident}')") + nul = stdout.find("\x00", pos) + if nul < 0: + break + pos = nul + 1 continue - match = pattern.match(stdout, pos) pos = match.end() staged, unstaged = _parseStatusLine(ident, *match.groups())