crytic / echidna

Ethereum smart contract fuzzer
GNU Affero General Public License v3.0
2.65k stars 346 forks source link

[Bug-Candidate]: `Cannot decode byte '\xe4': Data.Text.Encoding: Invalid UTF-8 stream` #1241

Closed pcaversaccio closed 2 months ago

pcaversaccio commented 2 months ago

Describe the issue:

Background: See https://github.com/pcaversaccio/snekmate/pull/239

Whenever I run my echidna tests, I see the following warnings:

image

Code example to reproduce the issue:

~$ git clone https://github.com/pcaversaccio/snekmate.git
~$ git checkout feat/echidna
~$ forge install
~$ pip install git+https://github.com/vyperlang/vyper.git@master
~$ forge build --build-info
~$ echidna test/tokens/echidna/ERC20Properties.sol --contract CryticERC20ExternalHarness --config test/tokens/echidna/echidna-config.yaml --crytic-args --ignore-compile

Version:

Relevant log output:

[2024-04-23 15:44:45.45] Compiling test/tokens/echidna/ERC20Properties.sol... Done! (20.2442777s)
Analyzing contract: C:/Dev/Blockchain/snekmate/test/tokens/echidna/ERC20Properties.sol:CryticERC20ExternalHarness
[2024-04-23 15:45:09.77] Running slither on test/tokens/echidna/ERC20Properties.sol... Done! (35.8772859s)
Loaded 0 transaction sequences from echidna-corpus\reproducers
Loaded 0 transaction sequences from echidna-corpus\coverage
[2024-04-23 15:45:45.96] [Worker 0] Crashed:

Cannot decode byte '\xe4': Data.Text.Encoding: Invalid UTF-8 stream

Please report it to https://github.com/crytic/echidna/issues
[2024-04-23 15:45:45.96] [status] tests: 0/22, fuzzing: 0/10000, values: [], cov: 1560, corpus: 0
test_ERC20external_userBalanceNotHigherThanSupply(): passing
test_ERC20external_setAllowanceTwice(address,uint256): passing
test_ERC20external_burnFromUpdateAllowance(uint256): passing
test_ERC20external_transferFrom(address,uint256): passing
test_ERC20external_transferFromToZeroAddress(uint256): passing
test_ERC20external_constantSupply(): passing
test_ERC20external_setAllowance(address,uint256): passing
test_ERC20external_transferMoreThanBalance(address): passing
test_ERC20external_mintTokens(address,uint256): passing
test_ERC20external_transferToZeroAddress(): passing
test_ERC20external_transferFromMoreThanBalance(address): passing
test_ERC20external_zeroAddressBalance(): passing
test_ERC20external_transfer(address,uint256): passing
test_ERC20external_selfTransfer(uint256): passing
test_ERC20external_userBalancesLessThanTotalSupply(): passing
test_ERC20external_burnFrom(uint256): passing
test_ERC20external_transferFromZeroAmount(address): passing
test_ERC20external_burn(uint256): passing
test_ERC20external_transferZeroAmount(address): passing
test_ERC20external_spendAllowanceAfterTransfer(address,uint256): passing
test_ERC20external_selfTransferFrom(uint256): passing
AssertionFailed(..): passing

Unique instructions: 1560
Unique codehashes: 3
Corpus size: 0
Seed: 8944220378161519169

[2024-04-23 15:45:45.97] Saving test reproducers... Done! (0s)
[2024-04-23 15:45:45.97] Saving corpus... Done! (0s)
ggrieco-tob commented 2 months ago

Hey, this looks very cool. Do you know if the bug is related to hevm code or echidna?

pcaversaccio commented 2 months ago

Hey, this looks very cool. Do you know if the bug is related to hevm code or echidna?

I'm really not sure tbh - didn't have time to investigate properly.

pcaversaccio commented 2 months ago

and btw the decode error is also in the CI https://github.com/pcaversaccio/snekmate/actions/runs/8803366873/job/24161302034#step:19:21

pcaversaccio commented 2 months ago

I think I found partially the issue: Vyper adds the following signature to the init code which I use in the ffi command:

sig = b"\xa1\x65vyper\x83".hex()

See my comment here: https://github.com/vyperlang/vyper/pull/2860#issuecomment-1279717236. And \xa1 and \x83 are common decoding errors I see in that context. There might be some further method Ids that might not be decoded properly as well.

elopez commented 2 months ago

On an initial triage, it seems this happens due to Echidna calling VyperDeployer.deploy(....) with non-utf8-valid strings. The config has allContracts: true. valsArr in hevm ends up having invalid utf8 which then fails to decode. https://github.com/ethereum/hevm/blob/release/0.53.0/src/EVM.hs#L1564

Filtering the affected functions so echidna does not try to fuzz them seems to work around the issue:

filterFunctions: ["VyperDeployer.deployContract(string,string)", "VyperDeployer.deployContract(string,string,bytes)", "VyperDeployer.deployContract(string,string,bytes,string,bool)", "VyperDeployer.deployContract(string,string,string,bool)"]

This is a smaller repro of this issue:

interface Hevm {
  function ffi(string[] calldata) external returns (bytes memory);
}

contract TestFFI {
  address constant HEVM_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;

  function foo() public {
    bytes memory w = hex"c328"; // invalid utf-8

    string[] memory inputs = new string[](2);
    inputs[0] = "echo";
    inputs[1] = string(w);

    bytes memory res = Hevm(HEVM_ADDRESS).ffi(inputs);
  }
}
$ echo allowFFI: true > config.yml
$ echidna foo.sol --test-mode assertion --format text --contract TestFFI --config config.yml
[2024-04-23 18:04:34.90] Compiling foo.sol... Done! (0.775142s)
Analyzing contract: .../foo.sol:TestFFI
[2024-04-23 18:04:35.70] Running slither on foo.sol... Done! (0.81568s)
[2024-04-23 18:04:36.52] [Worker 0] Crashed:

Cannot decode byte '\xc3': Data.Text.Encoding: Invalid UTF-8 stream

Please report it to https://github.com/crytic/echidna/issues
[2024-04-23 18:04:36.52] [status] tests: 0/2, fuzzing: 0/50000, values: [], cov: 481, corpus: 0
foo(): passing
AssertionFailed(..): passing
...
pcaversaccio commented 2 months ago

@elopez confirmed, this was the issue. Thanks a lot! Fixed via https://github.com/pcaversaccio/snekmate/pull/239/commits/0d6889f3949aa89dcfdeadead5581fa395cb7d0c. Will close the issue accordingly.

ggrieco-tob commented 2 months ago

Uhm, is there something we should recommend to hevm to avoid this decoding error?

pcaversaccio commented 2 months ago

Uhm, is there something we should recommend to hevm to avoid this decoding error?

maybe raise this issue to them at least and get their thoughts on it?

ggrieco-tob commented 2 months ago

Sounds like a plan!