Skip to content

Do not crash when an error message contains format placeholders - #3203

Open
Sanjays2402 wants to merge 2 commits into
pylint-dev:mainfrom
Sanjays2402:fix/error-str-format-placeholders
Open

Do not crash when an error message contains format placeholders#3203
Sanjays2402 wants to merge 2 commits into
pylint-dev:mainfrom
Sanjays2402:fix/error-str-format-placeholders

Conversation

@Sanjays2402

Copy link
Copy Markdown
Contributor

Type of Changes

Type
🐛 Bug fix

Description

AstroidError.__str__ runs str.format on its message, and several inference errors build that message out of user code. namedtuple("{0}", "") therefore reached "ValueError: " + str(exc) with an unsatisfiable positional placeholder and raised IndexError instead of the intended UseInferenceDefault, crashing pylint.

The fallback already caught ValueError; it now also catches IndexError and KeyError, the other two exceptions str.format raises for placeholders it cannot fill. A regression test was added beside the sibling test_*_does_not_crash_inference cases in tests/brain/test_named_tuple.py (fails without the fix with the reported IndexError, passes with it).

Happy to add a ChangeLog entry if you would like one for this.

This change was prepared with AI assistance; the regression test was run locally and fails without the fix.

Closes #3199

AstroidError.__str__ calls str.format on its message, and several
inference errors build that message from user code. A typename such as
namedtuple("{0}", "") therefore reached "ValueError: " + str(exc)
with a positional placeholder and no arguments, raising IndexError
instead of the intended UseInferenceDefault.

The fallback already handled ValueError; it now also handles
IndexError and KeyError, the other two exceptions str.format
raises for unsatisfiable placeholders.

Closes pylint-dev#3199
@codspeed-hq

codspeed-hq Bot commented Aug 5, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 3 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing Sanjays2402:fix/error-str-format-placeholders (1264770) with main (8666418)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.64%. Comparing base (8666418) to head (1264770).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #3203   +/-   ##
=======================================
  Coverage   93.64%   93.64%           
=======================================
  Files          93       93           
  Lines       11567    11567           
=======================================
  Hits        10832    10832           
  Misses        735      735           
Flag Coverage Δ
linux 93.50% <100.00%> (ø)
pypy 93.64% <100.00%> (ø)
windows 93.61% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
astroid/exceptions.py 95.83% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@DanielNoord DanielNoord left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we cover the KeyError with a test as well?

@Pierre-Sassoulas Pierre-Sassoulas added this to the 4.3.1 milestone Aug 9, 2026
@Pierre-Sassoulas

Copy link
Copy Markdown
Member

Two payloads still get through:

  • namedtuple("{message.foo}", "") => AttributeError: 'str' object has no attribute 'foo'
  • namedtuple("{message:200000000}", "") => no exception at all; format succeeds and builds a 200 MB string. Peak RSS goes from 22 MB to 421 MB for a single call, so no except clause can catch this one.

#3214 covers both by also dropping message from the substitution fields, which stops the message from being able to interpolate itself (Please do it that way and credit @kali834x for it).

Also adding the changeLog entry would be welcome, plus the KeyError test Daniel asked for.

@Sanjays2402

Copy link
Copy Markdown
Contributor Author

Implemented the requested hardening in 889342c: AstroidError now excludes the message itself from format fields and falls back on LookupError/ValueError/AttributeError/TypeError, which prevents both attribute traversal and large-width self-formatting. Added the KeyError and AttributeError inference regressions plus a ChangeLog entry. The full tests/brain/test_named_tuple.py passes (26 passed); with the source fix reverted, the AttributeError regression fails during AstroidError.str, and it passes again with the fix.

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 4.3.1, 4.3.2 Aug 17, 2026
@DanielNoord

Copy link
Copy Markdown
Collaborator

Please fix CI and rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IndexError: Replacement index 0 out of range for positional args tuple

3 participants