Skip to content

fix[codegen]: fix removal of side effects in concat #4644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

charles-cooper
Copy link
Member

@charles-cooper charles-cooper commented May 15, 2025

concat would remove side effects for zero-length arguments. fix by removing the fastpath.

as the test case shows, this pattern is not common in user-code.

fix for GHSA-qhr6-mgqr-mchm

What I did

How I did it

How to verify it

Commit message

concat would remove side effects for zero-length arguments. fix by
removing the fastpath.

as the test case shows, this pattern is not common in user-code.

this commit also reverts the optimization introduced in a06f7df76fc07,
and replaces it with a tag on the `IRnode`, since otherwise the
`~empty` intrinsic can show up in the IR at the time we lower to
assembly (which is an error).

Description for the changelog

Cute Animal Picture

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

concat would remove side effects for zero-length arguments. fix by
removing the fastpath.

as the test case shows, this pattern is not common in user-code.
Copy link

codecov bot commented May 15, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.53%. Comparing base (a06f7df) to head (9bf9723).
Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4644   +/-   ##
=======================================
  Coverage   92.53%   92.53%           
=======================================
  Files         129      129           
  Lines       18604    18605    +1     
  Branches     3228     3227    -1     
=======================================
+ Hits        17215    17216    +1     
  Misses        943      943           
  Partials      446      446           

☔ 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.


@external
def test() -> Bytes[256]:
a: Bytes[256] = concat(b"" if self.sideeffect() else b"", b"aaaa")
Copy link
Collaborator

Choose a reason for hiding this comment

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

just for completness noting that in this case we will hit this fast-path in copy_bytes

return IRnode.from_list(["seq"], annotation=annotation)

@cyberthirst
Copy link
Collaborator

this fix should be sufficient as now we will hit the following line for all the arguments:

ret.append(b1.resolve(b2.resolve(do_copy)))

and thus if the argument will be complex (and potentially have side-effects) it will get evaluated

@cyberthirst
Copy link
Collaborator

charles-cooper#85 shows a poc for side-effect elimination in case the concat node is Bytes[0]

…t-zero-length

add concat side-effect elimination test
@@ -557,10 +557,6 @@ def build_IR(self, expr, context):
dst_data = add_ofst(bytes_data_ptr(dst), ofst)

if isinstance(arg.typ, _BytestringT):
# Ignore empty strings
if arg.typ.maxlen == 0:
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think this will have to be rewritten to smth like if arg.is_empty_intrinsic because of: https://github.com/vyperlang/vyper/pull/4649/files#diff-452732981c7a1a928e9f249c7b14c723695de3d6635568ccc8899b6cab2fc54bR151

.. otherwise bytes_data_ptr(arg) would fail i think

charles-cooper added a commit to charles-cooper/vyper that referenced this pull request May 19, 2025
@charles-cooper charles-cooper marked this pull request as ready for review May 19, 2025 10:31
@charles-cooper charles-cooper marked this pull request as draft May 19, 2025 10:31
charles-cooper added a commit that referenced this pull request May 19, 2025
per title. as in the referenced pull requests and security advisories,
it is difficult, but not impossible, to construct an empty bytestring
which has side effects. in this commit, don't fastpath out the side
effects for zero-length bytestrings

references:
- #4644
- GHSA-qhr6-mgqr-mchm
- #4645
- GHSA-3vcg-j39x-cwfm

---------

Co-authored-by: cyberthirst <[email protected]>
@cyberthirst cyberthirst marked this pull request as ready for review May 19, 2025 17:03
@@ -369,6 +373,8 @@ def is_empty_intrinsic(self):
return True
if self.value == "seq":
return len(self.args) == 1 and self.args[0].is_empty_intrinsic
if self.is_source_literal and isinstance(self.typ, _BytestringT) and self.typ.maxlen == 0:
Copy link
Collaborator

Choose a reason for hiding this comment

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

please add a comment why this counts as the empty intrinsic

["seq"] + seq + [placeholder],
typ=btype,
location=MEMORY,
annotation=f"Create {btype}: {bytez}",
)
ret.is_source_literal = True
Copy link
Collaborator

Choose a reason for hiding this comment

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

i would probably rename this to is_source_bytes_literal because other literals don't have this flag turned on. so that we don't use this in some future analysis with the wrong assumptions

@charles-cooper charles-cooper merged commit e463acd into vyperlang:master May 21, 2025
162 checks passed
@charles-cooper charles-cooper deleted the fix/concat-zero-length branch May 21, 2025 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants