Repository navigation
Missing validation for allowed constant values in ast.literal_eval() #141778
Copy link
Copy link
Closed as not planned
Closed as not planned
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
Maybe it's a feature, but I see something wrong here:
>>> import ast
>>> value = object()
>>> value
<object object at 0x7f7489580880>
>>> node = ast.Expression(body=ast.Constant(value))
>>> ast.fix_missing_locations(node)
Expression(body=Constant(value=<object object at 0x7f7489580880>, kind=None))
>>> ast.literal_eval(node)
<object object at 0x7f7489580880>
>>> compile(node, "<test>", "eval")
Traceback (most recent call last):
File "<python-input-6>", line 1, in <module>
compile(node, "<test>", "eval")
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: got an invalid type in Constant: objectNote, that for unary/binary ops values are checked, e.g.:
>>> node = ast.Expression(body=ast.UnaryOp(op=ast.USub(), operand=ast.Constant(value)))
>>> ast.fix_missing_locations(node)
Expression(body=UnaryOp(op=USub(), operand=Constant(value=<object object at 0x7f7489580880>, kind=None)))
>>> ast.literal_eval(node)
Traceback (most recent call last):
File "<python-input-10>", line 1, in <module>
ast.literal_eval(node)
~~~~~~~~~~~~~~~~^^^^^^
File "/usr/local/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/local/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/local/lib/python3.14/ast.py", line 74, in _convert_signed_num
operand = _convert_num(node.operand)
File "/usr/local/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/local/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Constant(value=<object object at 0x7f7489580880>, kind=None)
>>> compile(node, "<test>", "eval")
Traceback (most recent call last):
File "<python-input-11>", line 1, in <module>
compile(node, "<test>", "eval")
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: got an invalid type in Constant: object(Tested in the main branch too.)
CPython versions tested on:
CPython main branch, 3.14
Operating systems tested on:
No response
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
- StatusShow more project fieldsTodo
Activity
skirpichev commentedon Nov 20, 2025
CC @Eclips4
sergey-miryanov commentedon Nov 20, 2025
IIUC,
Constantcan't get object value according documentation:skirpichev commentedon Nov 20, 2025
I'm not sure it's relevant. The docs don't tell what happens when the value is not from the above list. Should it raise an exception? Or blow up a nuke? E.g. ast.Expr docs says:
But behold:
My argument was that the
literal_eval()has such validation, but only partially.sergey-miryanov commentedon Nov 20, 2025
Augh, I just noticed a difference in the first example -
literal_evalworks, butcompiledoesn't.Sorry.
serhiy-storchaka commentedon Nov 20, 2025
I think this is a GIGO case.
ast.literal_eval()works for string argument. It works if the string was parsed to AST byast.parse(). It does not work for arbitrary invalid AST, this is not its purpose. You can makecompile()to fail by simply setting invalid lineno --ast.literal_eval()ignores lineno.I propose to close this issue as "won't fix".
skirpichev commentedon Nov 20, 2025
Not only. But I realize, it's major case.
Nop.
(Though, literal_eval() also reject string '1j+1', this looks consistent.)
That's why I did fix_missing_locations() in my initial examples.
Then it should reject invalid input, not silently accept it. We do this for some cases. Why not do it for all?
BTW, the fix is trivial:
picnixz commentedon Nov 22, 2025
Instead of importing
type, I suggest cachingtype(None)andtype(...)as global variables.Eclips4 commentedon Nov 22, 2025
I'm actually in favor of using the new
isinstancechecks (ortype(x) in (...)). This isn't working as expected, but the real question is: Should we validate the input in theast.literal_eval? In my opinion, yes.skirpichev commentedon Nov 22, 2025
I hope someone will finish patch. Fits to "easy" camp for me.
21 remaining items
skirpichev commentedon Dec 25, 2025
Well, bad news - no one from core devs support that it's an issue :( I'll close opened pr's. Reclassified as docs issue.
Eclips4 commentedon Dec 25, 2025
@skirpichev I do think that’s an issue :) But unfortunately, it doesn’t seem like we’ve reached a consensus.
skirpichev commentedon May 26, 2026
It seems, doing so break some (wrong) assumptions of the stdlib modules as well. See the current PR.
But we have wrong documentation:
@serhiy-storchaka, @JelleZijlstra, are you suggesting to keep it as is or change? If so, how?
skirpichev commentedon Aug 18, 2026
I think we shouldn't document odd stdlib behavior. If there is no consensus on disallowing broken ast trees in all cases - lets just reject this bugreport.