From e2ede4717cdf9fa06805c065481aee65564ffa35 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 5 Nov 2026 09:45:02 -0500 Subject: [PATCH] Python: treat await expressions as side-effecting Prevent ineffectual-statement false positives when awaiting a task or coroutine without assigning its returned value. Add regression cases for both forms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f0800d30-e4f9-463c-a0d8-660fe1aceaf1 --- .../change-notes/2026-11-05-await-side-effects.md | 4 ++++ python/ql/lib/semmle/python/Exprs.qll | 2 ++ .../Statements/no_effect/await_task.py | 15 +++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 python/ql/lib/change-notes/2026-11-05-await-side-effects.md create mode 100644 python/ql/test/query-tests/Statements/no_effect/await_task.py diff --git a/python/ql/lib/change-notes/2026-11-05-await-side-effects.md b/python/ql/lib/change-notes/2026-11-05-await-side-effects.md new file mode 100644 index 000000000000..9f84762e711d --- /dev/null +++ b/python/ql/lib/change-notes/2026-11-05-await-side-effects.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Await expressions are now treated as having side effects. This prevents false positives from the "Statement has no effect" query (`py/ineffectual-statement`) when an awaited task or coroutine's result is discarded. diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index 937c9e5ffd79..1d4b545909ae 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -623,6 +623,8 @@ class None extends NameConstant { class Await extends Await_ { /* syntax: await Expr */ override Expr getASubExpression() { result = this.getValue() } + + override predicate hasSideEffects() { any() } } /** A formatted string literal expression, such as `f'hello {world!s}'` */ diff --git a/python/ql/test/query-tests/Statements/no_effect/await_task.py b/python/ql/test/query-tests/Statements/no_effect/await_task.py new file mode 100644 index 000000000000..6d464c954666 --- /dev/null +++ b/python/ql/test/query-tests/Statements/no_effect/await_task.py @@ -0,0 +1,15 @@ +import asyncio + + +async def returns_value(): + return 42 + + +async def await_task_result(): + task = asyncio.create_task(returns_value()) + await task + + +async def await_coroutine_result(): + coroutine = returns_value() + await coroutine