Skip to content
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

Providing an empty string to --yul-optimizations without enabling yul optimization triggers uncaught exception #14946

Closed
danceratopz opened this issue Mar 15, 2024 · 1 comment · Fixed by #14967
Assignees
Labels

Comments

@danceratopz
Copy link
Member

Description

This is a edge case in command-line arg parsing related to assembly optimization flags: Providing the empty string or a string containing only whitespace to --yul-optimizations triggers an uncaught exception.

Environment

  • Compiler version: 0.8.23 - 0.8.26-develop.2024.3.15+commit.33e33241.mod.Linux.g++
  • Target EVM version (as per compiler settings): Default.
  • Framework/IDE (e.g. Truffle or Remix): None, triggered on the command-line
  • EVM execution environment / backend / blockchain client: None.
  • Operating system: Linux

Not present in 0.8.22, most likely due to the change in command-line parsing introduced in #14657.

Steps to Reproduce

Executing either (example Yul provided below):

solc --strict-assembly --yul-optimizations " " simple.yul

or

solc --strict-assembly --yul-optimizations "" simple.yul

Triggers the exception:

Uncaught exception:
/solidity/libyul/YulStack.cpp(179): Throw in function solidity::yul::YulStack::optimize(solidity::yul::Object&, bool)::<lambda()>
Dynamic exception type: boost::wrapexcept<solidity::yul::YulAssertion>
std::exception::what: Yul assertion failed
[solidity::util::tag_comment*] = Yul assertion failed

Contrarily:

solc --strict-assembly --yul-optimizations ":" simple.yul

outputs unoptimized bytecode, as expected:

======= simple.yul (EVM) =======

Pretty printed source:
object "object" {
    code {
        {
            sstore(0, f(1, 2))
            return(0, 32)
        }
        function f(a, b) -> c
        { c := add(a, b) }
    }
}


Binary representation:
6009600260016010565b5f5560205ff35b019056

Text representation:
    /* "simple.yul":145:152   */
  tag_2
    /* "simple.yul":150:151   */
  0x02
    /* "simple.yul":147:148   */
  0x01
    /* "simple.yul":145:152   */
  tag_1
  jump	// in
tag_2:
    /* "simple.yul":142:143   */
  0x00
    /* "simple.yul":135:153   */
  sstore
    /* "simple.yul":182:184   */
  0x20
    /* "simple.yul":179:180   */
  0x00
    /* "simple.yul":172:185   */
  return
    /* "simple.yul":35:115   */
tag_1:
    /* "simple.yul":86:95   */
  add
    /* "simple.yul":35:115   */
  swap1
  jump	// out

If the --optimize flag is added, the behavior is also as expected:

solc --strict-assembly --optimize --yul-optimizations "" simple.yul

which outputs the optimized bytecode.

Here's the contents of simple.yul used above, but this issue should be triggered regardless of input:

{
    function f(a, b) -> c {
        c := add(a, b)
    }

    sstore(0, f(1, 2))
    return(0, 32)
}
@nikola-matic
Copy link
Collaborator

Thanks for the report @danceratopz, this one is legit. Technically, we should have been more explicit as to what an empty optimizer sequence is (especially when the Yul optimizer is disabled) - i.e. ":" or just :, since this will set both the optimizer and the clean up sequence to empty.

In any case, this should fail in the CLI/standard JSON portion with a sensible error message, and not cause an ICE in the YulStack. Thankfully, it should be a trivial fix, and available in the next release.

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants