pyscg-0042: Ensure Correct Operator Precedence
Failing to understand the order of precedence in expressions that read and write to the same object can lead to unintended side effects.
Python has distinct different concepts for:
| type | examples | Typical direction |
|---|---|---|
| Assignments | to store a value such as x = 1 | right-to-left. |
| Expressions | 3+4 or x*2 | left-to-right |
| Augmented assignments | a += 1 | left-to-right [Python docs 2025 - simple statements] |
Expressions such as 2 ** 3, or two to the power of three, are evaluated from right to left [python power 2025] as demonstrated in example01.py
"""Code Example"""
print(2**3**2) # prints 512
print((2**3) ** 2) # prints 64
print(2**9)
The first expression would print 64 if Python would resolve from left-to-right but prints 512 as it calculates 3**2 before using its result with 2**9.
The example02.py behaves ‘normal’ for a programmer but makes no sense as a mathematical formular.
z = 2
z *= 2 + 1
print(f"z *= 2 + 1 ={z}")
If a method changes an object’s state (has side effects) and is called multiple times within one expression, the result can be surprising and incorrect. For further info on python’s order of precedence refer to The Python Language Specification , §6.16, “Evaluation Order” [PLR 2022].
Non-Compliant Code Example
noncompliant01.py demonstrates an operator precedence logic error that can lead to a buffer overflow vulnerability. This code example is based on a real vulnerability (CVE-2026-7270) that occurred in ‘FreeBSD’s’ execve argument handling. The code fails to use parentheses to clarify the intended order of operations, causing the bounds check to pass when it should fail.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Non-Compliant Code Example"""
ARG_MAX_BYTES = 16 # small buffer
argbuf = bytearray(ARG_MAX_BYTES)
USED = 10 # 10 bytes already used
ARG = b"AAAAAAAA" # attacker-controlled, needs 8 + 1 = 9 bytes
LENGTH = len(ARG) + 1 # 9 (include NUL terminator)
REMAINING = ARG_MAX_BYTES - USED + LENGTH # Wrong: 15, expected -3
if LENGTH > REMAINING:
print("Rejected: not enough space")
else:
print(f"Bounds check passed: remaining={REMAINING}")
Example output of noncompliant01.py:
Bounds check passed: remaining=15
The bounds check incorrectly passes because the expression evaluates left-to-right as (16 - 10) + 9 = 15 instead of the intended 16 - (10 + 9) = -3. This allows the attacker-controlled data to overflow the buffer.
Compliant Solution
The compliant solution fixes the operator precedence by comparing additions instead of subtracting, making the code clear, with no precedence trap. While adding parentheses like ARG_MAX_BYTES - (USED + LENGTH) would fix the precedence issue also, restructuring to USED + LENGTH > ARG_MAX_BYTES is clearer and avoids confusing negative values.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Compliant Code Example"""
ARG_MAX_BYTES = 16
argbuf = bytearray(ARG_MAX_BYTES)
USED = 10
ARG = b"AAAAAAAA"
LENGTH = len(ARG) + 1
# Compare additions instead of subtracting: clear, and no precedence trap
if USED + LENGTH > ARG_MAX_BYTES:
print("Rejected: not enough space")
else:
print(f"Bounds check passed: remaining={ARG_MAX_BYTES - USED - LENGTH}")
Example output of compliant01.py:
Rejected: not enough space
Now the bounds check correctly rejects the operation because USED + LENGTH = 10 + 9 = 19, which exceeds ARG_MAX_BYTES = 16.
Automated Detection
| Tool | Version | Checker | Description |
|---|---|---|---|
| Bandit | 1.7.4 on Python 3.10.4 | Not Available |
Related Guidelines
| MITRE CWE | Pillar: [CWE-691: Insufficient Control Flow Management] |
| MITRE CWE | Base CWE-783: Operator Precedence Logic Error |
| SEI CERT Oracle Coding Standard for Java | EXP05-J. Do not follow a write by a subsequent write or read of the same object within an expression |
| CERT C Coding Standard | EXP30-C. Do not depend on the order of evaluation for side effects |
| SEI CERT C++ Coding Standard | EXP50-CPP. Do not depend on the order of evaluation for side effects |
Bibliography
| [Python docs 2025 - simple statements] | 7.2.1. Augmented assignment statements [online]. Available from: https://docs.python.org/3/reference/simple_stmts.html?highlight=augmented%20assignment%20operators#augmented-assignment-statement, [Accessed 19 September 2025] |
| [python power 2025] | 6. Expressions [online]. Available from: https://docs.python.org/3/reference/expressions.html#index-59, [Accessed 19 September 2025] |
| [PLR 2022] | 6.16. Evaluation order [online]. Available from: https://docs.python.org/3/reference/expressions.html#evaluation-order, [Accessed 19 September 2025] |
| [CVE-2026-7270] | FreeBSD execve argument handling buffer overflow [online]. Available from: https://nvd.nist.gov/vuln/detail/CVE-2026-7270 |