Skip to content

fix[codegen]: cache result of iter eval#4488

Merged
charles-cooper merged 4 commits intovyperlang:masterfrom
charles-cooper:fix/list-iter
Feb 22, 2025
Merged

fix[codegen]: cache result of iter eval#4488
charles-cooper merged 4 commits intovyperlang:masterfrom
charles-cooper:fix/list-iter

Conversation

@charles-cooper
Copy link
Copy Markdown
Member

@charles-cooper charles-cooper commented Feb 21, 2025

What I did

fix for GHSA-h33q-mhmp-8p67 by always evaluating complex expressions before entry into the loop body. this is also a perf fix, since it moves the repeated evaluation into a one-time evaluation.

How I did it

How to verify it

Commit message

prior to this commit, multiple evaluation of a single expression is
possible in the iterator target of a for loop. while the iterator
expression cannot produce multiple writes, it can _consume_ side
effects produced in the loop body (e.g. read a storage variable
updated in the loop body) and thus lead to unexpected program
behavior. specifically, reads in iterators which contain an `IfExp`
(e.g. `for s: uint256 in ([read(), read()] if True else []))` would
issue one evaluation of the list `[read(), read()]` per loop iteration,
thus interleaving reads with writes in the loop body.

this commit fixes the issue by using `cache_when_complex` to enforce
evaluation of the iterator before entering the loop body.

this is incidentally also a performance fix, since it moves the
repeated evaluation into a one-time evaluation.

references:
- https://github.com/vyperlang/vyper/security/advisories/GHSA-h33q-mhmp-8p67

Description for the changelog

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@charles-cooper charles-cooper added this to the v0.4.1 milestone Feb 21, 2025
@charles-cooper charles-cooper added the release - must release blocker label Feb 21, 2025
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.06%. Comparing base (ba66226) to head (fbdcf85).
Report is 94 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4488   +/-   ##
=======================================
  Coverage   92.06%   92.06%           
=======================================
  Files         120      120           
  Lines       17329    17330    +1     
  Branches     2932     2932           
=======================================
+ Hits        15954    15955    +1     
  Misses        957      957           
  Partials      418      418           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Collaborator

@cyberthirst cyberthirst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's please link the PR to the advisory before merging

@cyberthirst
Copy link
Copy Markdown
Collaborator

should we update the docs for how the evaluation of the iter behaves?

@charles-cooper
Copy link
Copy Markdown
Member Author

should we update the docs for how the evaluation of the iter behaves?

i don't think so, i think this is the expected behavior. we have the advisory for the old behavior.

@charles-cooper
Copy link
Copy Markdown
Member Author

let's please link the PR to the advisory before merging

i think it's already linked?

@charles-cooper charles-cooper enabled auto-merge (squash) February 22, 2025 18:17
@charles-cooper charles-cooper merged commit 1ce583b into vyperlang:master Feb 22, 2025
159 checks passed
lemenkov pushed a commit to fedora-ethereum/vyper that referenced this pull request Feb 27, 2025
prior to this commit, multiple evaluation of a single expression is
possible in the iterator target of a for loop. while the iterator
expression cannot produce multiple writes, it can _consume_ side
effects produced in the loop body (e.g. read a storage variable
updated in the loop body) and thus lead to unexpected program
behavior. specifically, reads in iterators which contain an `IfExp`
(e.g. `for s: uint256 in ([read(), read()] if True else []))` would
issue one evaluation of the list `[read(), read()]` per loop iteration,
thus interleaving reads with writes in the loop body.

this commit fixes the issue by using `cache_when_complex` to enforce
evaluation of the iterator before entering the loop body.

this is incidentally also a performance fix, since it moves the
repeated evaluation into a one-time evaluation.

references:
- GHSA-h33q-mhmp-8p67
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release - must release blocker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants