Skip to content

reject arbitrary attribute assignment on bound methods#4201

Open
knQzx wants to merge 1 commit into
facebook:mainfrom
knQzx:fix/bound-method-attr-assignment
Open

reject arbitrary attribute assignment on bound methods#4201
knQzx wants to merge 1 commit into
facebook:mainfrom
knQzx:fix/bound-method-attr-assignment

Conversation

@knQzx

@knQzx knQzx commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

a bound method is a types.MethodType, which doesn't override __setattr__/__delattr__, so assigning an arbitrary attribute to it fails at runtime. pyrefly allowed it: lookup_magic_dunder_attr1 had no BoundMethod arm, so the base fell through to the general lookup and resolved the dunder via MethodType.__getattr__ (returns Any), which made the assignment look valid

add a BoundMethod arm mirroring the ClassInstance handling: when the mutating dunder is inherited from object, report it as not-found so the set/delete is rejected. attribute reads are unchanged

closes #4163

A bound method is a types.MethodType, which does not override
__setattr__/__delattr__, so assigning an arbitrary attribute to it fails
at runtime. Pyrefly permitted it: lookup_magic_dunder_attr1 had no
BoundMethod arm, so the base fell through to the general lookup and
resolved __setattr__/__delattr__ via MethodType.__getattr__ (which
returns Any), making the assignment look valid.

Add a BoundMethod arm mirroring the ClassInstance handling: when the
mutating dunder is inherited from object, report the attribute as
not-found so the set/delete is rejected. Attribute reads are unchanged.

Closes facebook#4163
@github-actions

Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

dragonchain (https://github.com/dragonchain/dragonchain)
+ ERROR dragonchain/transaction_processor/level_5_actions_utest.py:256:9-81: Object of class `FunctionType` has no attribute `return_value` [missing-attribute]
+ ERROR dragonchain/transaction_processor/level_5_actions_utest.py:275:9-80: Object of class `FunctionType` has no attribute `side_effect` [missing-attribute]
+ ERROR dragonchain/transaction_processor/level_5_actions_utest.py:294:9-81: Object of class `FunctionType` has no attribute `return_value` [missing-attribute]
+ ERROR dragonchain/transaction_processor/level_5_actions_utest.py:312:9-81: Object of class `FunctionType` has no attribute `return_value` [missing-attribute]

@knQzx

knQzx commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

heads up on the mypy_primer diff: the 4 new errors on dragonchain are all the mock.method.return_value = ... pattern, where the object is typed as the real class instead of Mock. they're technically correct (bound methods really don't have those attrs, mypy flags them too), just noisy on mock-heavy tests. if you'd rather keep test code quiet i can look into special-casing Mock/MagicMock, lmk what you prefer)

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.

Bound method objects incorrectly allow arbitrary attribute assignment

1 participant