#38682 [SC-Medium] AugAssign evaluation order causing OOB write within the object
Was this helpful?
Was this helpful?
Submitted on Jan 10th 2025 at 01:15:10 UTC by @anatomist for
Report ID: #38682
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/vyperlang/vyper
Impacts:
(Compiler) Incorrect bytecode generation leading to incorrect behavior
(Compiler) Unexpected behavior
AugAssign (e.g. +=
, -=
, ...) statements does not consider the side effect caused by rhs, allowing out-of-bounds index write within the array.
Vyper parse AugAssign
statements by first cache the target location to avoid double evaluation.
However, in the case when target is an access to a DynArray
and the right value modify the array, the cached target
will evaluate first, following the modifications like DynArray.pop()
, and eventually the STORE
operation could store the computed output in an index that falls outside the array’s current length bounds.
The direct impact is out-of-bounds index access within the array. But wrong IR code emission could also lead to various consequences.
https://github.com/vyperlang/vyper/blob/a29b49d422f6979be2b9c6c80aa583a60b1ccb7f/vyper/codegen/stmt.py#L291
This is alike high severity issue where it discusses similar issues for Assign
. However, it is not appropriate to apply the same mitigations in parse_Assign
to parse_AugAssign
, since the evaluation order of Assign
is rhs -> lhs
, while evaluation of AugAssign
should be dereference lhs -> rhs -> assign to lhs
, so assigning rhs
to a temporary variable will actually change the evaluation order. We currently don't have a simple patch in mind, aside from reimplementing the entire AugAssign
. Notably, care must be taken to not double evaluate lhs
when fixing the bug.