It used to be that we didn't raise a SyntaxError if there is an await but it is optimized away, and the code would work fine.
Now, however, the symtable sets ste_coroutine when it sees the await, but it still doesn't raise an error about the await, leading to the crash reported here.
Make it so it's still a SyntaxError to await outside of a coroutine if the await is optimized away.
The latter seems like the more intuitive behavior for users.
It's also consistent with other cases where optimized-away code leads to a compile error:
% python -O
Python 3.12.1 (main, Apr 22 2024, 00:22:15) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
... assert (x := 3)
... global x
...
File "<stdin>", line 3
SyntaxError: name 'x' is assigned to before global declaration
So I'll send a PR to make python -O -c 'assert await 1' a SyntaxError.
I realized there's a few more similar cases (essentially, every place we call compiler_error in compile.c while inside an expression):
% python -c 'assert (yield)'
File "<string>", line 1
SyntaxError: 'yield' outside function
% python -O -c 'assert (yield)'
% python -O -c 'assert (__debug__ := True)'
% python -c 'assert (__debug__ := True)'
File "<string>", line 1
SyntaxError: cannot assign to __debug__
% python -O -c 'assert (__debug__ := True)'
% python -c 'assert [x async for x in ()]'
File "<string>", line 1
SyntaxError: asynchronous comprehension outside of an asynchronous function
% python -O -c 'assert [x async for x in ()]'
The latter also crashes on current main:
% ./python.exe -O -c 'assert [x async for x in ()]'
Assertion failed: (IS_TOP_LEVEL_AWAIT(c) || _PyST_IsFunctionLike(ste)), function compute_code_flags, file compile.c, line 7482.
zsh: abort ./python.exe -O -c 'assert [x async for x in ()]'
The linked PR makes symtable.c detect incorrect await and async comprehensions, fixing this issue.
I didn't bother detecting other compiler errors (e.g., invalid yields) because they don't cause similar crashes. I wouldn't be surprised though if there's a crash lurking somewhere with e.g. assert (yield) being optimized away, so maybe if you point your fuzzer in that direction it will find something :)
Activity
alex commented on Jul 12, 2024
cc: @iritkatriel -- it looks like you've got a few commits in this file in that range, though I don't see one that's obviously relevant.
JelleZijlstra commented on Jul 12, 2024
Feels related to #121297.
sobolevn commented on Jul 12, 2024
I will add both asyncio and interpreter-core, because both are related.
JelleZijlstra commented on Jul 12, 2024
Irit is on vacation, I'll look into this over the next few days.
JelleZijlstra commented on Jul 13, 2024
The problem is arguably this:
It used to be that we didn't raise a SyntaxError if there is an await but it is optimized away, and the code would work fine.
Now, however, the symtable sets ste_coroutine when it sees the await, but it still doesn't raise an error about the await, leading to the crash reported here.
I can see two solutions:
The latter seems like the more intuitive behavior for users.
It's also consistent with other cases where optimized-away code leads to a compile error:
So I'll send a PR to make python -O -c 'assert await 1' a SyntaxError.
alex commented on Jul 13, 2024
Always doing a syntax error, even if the assert is optimized out, feels like the right behavior to me.
JelleZijlstra commented on Jul 13, 2024
I realized there's a few more similar cases (essentially, every place we call compiler_error in compile.c while inside an expression):
The latter also crashes on current main:
JelleZijlstra commented on Jul 13, 2024
The linked PR makes symtable.c detect incorrect await and async comprehensions, fixing this issue.
I didn't bother detecting other compiler errors (e.g., invalid yields) because they don't cause similar crashes. I wouldn't be surprised though if there's a crash lurking somewhere with e.g. assert (yield) being optimized away, so maybe if you point your fuzzer in that direction it will find something :)
gvanrossum commented on Jul 13, 2024
Of course! It must have been an oversight that we didn't do this from the start.
I'm removing the topic-asyncio label -- just because it mentions await doesn't make it an asyncio issue.
gh-121637: Syntax error for optimized-away incorrect await (#121656)
JelleZijlstra commented on Jul 22, 2024
Thanks for the report! This will now be a SyntaxError.