ethereum / fe

Emerging smart contract language for the Ethereum blockchain.
https://fe-lang.org
Other
1.61k stars 185 forks source link

Compiling the compilers/tests/fixtures/demos/uniswap.fe file can crash with /solidity/libyul/backends/evm/EVMObjectCompiler.cpp(66): Throw in function void solidity::yul::EVMObjectCompiler::run(solidity::yul::Object &, bool) #319

Closed agroce closed 3 years ago

agroce commented 3 years ago

Compiling the compilers/tests/fixtures/demos/uniswap.fe file can crash! But if you add --overwrite it doesn't do so.

user@e63eb6d843c9:~/fe$ RUST_BACKTRACE=1 target/debug/fe compiler/tests/fixtures/demos/uniswap.fe 
thread 'main' panicked at 'Yul compilation failed: {"errors":[{"component":"general","formattedMessage":"Internal exception in StandardCompiler::compile: /solidity/libyul/backends/evm/EVMObjectCompiler.cpp(66): Throw in function void solidity::yul::EVMObjectCompiler::run(solidity::yul::Object &, bool)\nDynamic exception type: boost::exception_detail::clone_impl<solidity::yul::StackTooDeepError>\nstd::exception::what: Variable $amount1_out is 1 slot(s) too deep inside the stack.\n[solidity::util::tag_comment*] = Variable $amount1_out is 1 slot(s) too deep inside the stack.\n","message":"Internal exception in StandardCompiler::compile: /solidity/libyul/backends/evm/EVMObjectCompiler.cpp(66): Throw in function void solidity::yul::EVMObjectCompiler::run(solidity::yul::Object &, bool)\nDynamic exception type: boost::exception_detail::clone_impl<solidity::yul::StackTooDeepError>\nstd::exception::what: Variable $amount1_out is 1 slot(s) too deep inside the stack.\n[solidity::util::tag_comment*] = Variable $amount1_out is 1 slot(s) too deep inside the stack.\n","severity":"error","type":"InternalCompilerError"}]}', compiler/src/lib.rs:48:27
stack backtrace:
   0: rust_begin_unwind
             at /rustc/9c09c1f7cfcf9de0522bcd1cfda32b552195c464/library/std/src/panicking.rs:493:5
   1: std::panicking::begin_panic_fmt
             at /rustc/9c09c1f7cfcf9de0522bcd1cfda32b552195c464/library/std/src/panicking.rs:435:5
   2: fe_compiler::compile
   3: fe::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Aborted

but note:

user@e63eb6d843c9:~/fe$ target/debug/fe compiler/tests/fixtures/demos/uniswap.fe --overwrite
Compiled compiler/tests/fixtures/demos/uniswap.fe. Outputs in `output`

On latest github master, built with

[profile.dev]
debug = true
panic = "abort"

for fuzzing. Found this one when preparing new corpus for starting a new fuzzer run, I crawl the directories for the .fe files. This is the first version this has happened on, so something's changed (maybe on solc's end?)

agroce commented 3 years ago

Seems to be the only test that this happens for. I'm going to just pull it from the corpus and start up a fuzzer, for now, but something odd going on here. Also, when afl refused to start up, it was running with --overwrite, so there seem to be some circumstances under which this can happen with --overwrite since the afl command line is:

 cargo afl fuzz -i corpus/ -o fuzz_fe -f code.fe -d -t 80000 -m 80 -- target/debug/fe code.fe --overwrite
g-r-a-n-t commented 3 years ago

Good catch! This is somewhat embarrassing..

This is happening because the Yul optimizer will sort out most StackTooDeepErrors that would otherwise crash the Solidity compiler. So, what does overwrite have to do with optimization? Looks like I made a copy paste error when adding the optimize flag:

https://github.com/ethereum/fe/blob/7b9ef12c30e03e7c301ba9e77e9973e356a8e680/src/main.rs#L78-L79

agroce commented 3 years ago

heh!

agroce commented 3 years ago

hmm, wait, without --optimize there's no optimization going on? I should definitely be fuzzing with optimization

agroce commented 3 years ago

ah right, just the solc Yul optimizer, so we may get "fuzzing" of solc rather than Fe here, and most Fe bugs will be caught without it being on. hmm. Still think I'll crank up with it on, no reason not to do so. also, I guess since I do --overwrite, I get --optimize for free right now :)

agroce commented 3 years ago

of course this gets exposed only when not --optimize, hrm

g-r-a-n-t commented 3 years ago

The downside with running the optimizer is of course time. Maybe this isn't a big deal?

Let me look into this a bit more. I suspect StackTooDeepError is being thrown at a later stage that we don't need to care about.

agroce commented 3 years ago

The downside with running the optimizer is of course time. Maybe this isn't a big deal?

well, throughput is king in fuzzing. OTOH I imagine we only pay the price when we actually make it to the Yul optimizer, which is probably vanishingly few inputs, so I think it is not a real cost here

agroce commented 3 years ago

ok, I don't imagine; we clearly only pay when it makes it all the way to Yul codegen, which probably basically never happens in fuzzing runs, which is why we need millions to find stuff