Git Product home page Git Product logo

securify's Introduction

[DEPRECATED] Securify

This is version of Securify is deprecated and will be no longer supported. Please use Securify v2.0.

securify

Securify is a security scanner for Ethereum smart contracts supported by the Ethereum Foundation and ChainSecurity. The core research behind Securify was conducted at the ICE Center at ETH Zurich.

scan now

It features an extensive list of security patterns commonly found in smart contracts:

  • some forms of the DAO bug (also known as reentrancy)
  • locked ether
  • missing input validation
  • transaction ordering-dependent amount, receiver and transfer
  • unhandled exceptions
  • unrestricted ether flow

The project is meant to be an open platform welcoming contributions from all of the Ethereum Security Community. To suggest new patterns, to volunteer for testing or to contribute developing new patterns please get in touch through our Discord group.

Getting Started

Requirements

  • Soufflé: https://github.com/souffle-lang/souffle/releases (Securify should work with the latest package, please raise an issue if it does not). If you cannot install Soufflé, look at the Docker container for an alternative. Securify will crash without the souffle binary. As of writing, Soufflé is not available on Windows, so Securify should not be expected to run on Windows either.
  • Java 8
  • A solc binary is required to be able to use Solidity file as input. Securify assumes that the right version is installed for the given file. solc is available here.

Use

To build:

./gradlew jar

To run Securify on a Solidity file:

java -jar build/libs/securify.jar -fs src/test/resources/solidity/transaction-reordering.sol

To run Securify on the decompilation output provided by the pysolc.py script (which requires py-solc):

java -jar build/libs/securify.jar -co out.json

To run Securify on some EVM binary (produced e.g. by solc):

java -jar build/libs/securify.jar -fh src/test/resources/solidity/transaction-reordering.bin.hex

To see the full list of options:

java -jar build/libs/securify.jar -h

To run the tests (which use JUnit4):

./gradlew test

A Python wrapper helps to deal with solc and truffle. The requirements are in the requirements.txt file. The Dockerfile can be used as a reference to set-up your local environment to use this wrapper.

Docker

The installation should be simple enough on Debian derivatives, or any other platform supported by Soufflé.

For a quick demonstration which does not require Soufflé, you can use Docker.

Build the Docker image:

docker build . -t securify

Run Securify on a small example:

docker run securify

You can change the files analyzed by specifying a volume to mount, and every *.sol file contained will then be processed by Securify:

docker run -v $(pwd)/folder_with_solidity_files:/project securify

Adding a --truffle flag should allow Securify to run over Truffle project in which dependencies have already been installed (so run npm install before if need be). Without this flag, the project is compiled using solc. Add a -h to obtain the full list of options. In particular, if the user wants to receive compilation information from Truffle, he should add the -v flag.

If one wants to receive JSON output, the docker supports a --json flag that will suppress the pretty output and return JSON instead. Make sure to add the -q flag if no progress information should be displayed, hence resulting in pure JSON output. The indices of the lines matched are 0-based, meaning that a match to line i means that the i+1th line is matched. In particular, the first line has an index of 0.

Tests

Basic end to end tests can be run through the test.py file:

python3 test.py

The requirements can be installed using Pipenv:

pipenv install

or using pip:

pip install -r requirements.txt

These tests compare the current json output given by Securify with some past output, and report differences between the two.

Travis Integration

You can add the following .travis.yml to your project to run Securify on new commits:

services:
  - docker

before_install:
  - docker pull chainsecurity/securify

script:
- docker run -v $(pwd):/project chainsecurity/securify

This should allow Securify to run over Truffle project in which dependencies have already been installed (so run npm install before if need be).

Output

The output loosely follows the clang style. Only warnings and vulnerabilities are reported. If one wishes to also get the compliance information, please use the --json flag in the docker, or -co flag on the Java executable to get all analysis information in JSON format.

Contributing

See CONTRIBUTING.md.

Join our Discord to discuss with other users.

Known Limitations

Although Securify is regularly used to help audits at ChainSecurity, there are still bugs, including:

  • the code in the fallback function is currently not analyzed. A workaround is to name this function instead.
  • in some cases, a StackOverflowError exception is thrown, due to computeBranches being recursive. In most cases, it is enough to increase the stack size using the -Xss option of java, e.g. java -Xss1G -jar ....
  • libraries are not properly supported
  • abstract contracts (whose binary cannot be obtained via solc) are not supported

Presentations, research, and blogs about Securify

Technical details

Securify statically analyzes the EVM code of the smart contract to infer important semantic information (including control-flow and data-flow facts) about the contract. This step is fully automated using Soufflé, a scalable Datalog solver. Then, Securify checks the inferred facts to discover security violations or prove the compliance of security-relevant instructions.

The full technical details behind the Securify scanner are available in the research paper.

securify's People

Contributors

energyfusion avatar hiqua avatar mattaereal avatar matthiasegli-chainsecurity avatar ptsankov avatar ritzdorf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

securify's Issues

Decompilation errors with some contracts

Some contracts trigger decompilation errors, which prevent any analysis. The output is then empty. At least Securify should fail loudly to prevent the false sense of Securify.

In the example I have, modifying some statements a bit (e.g. by using a temporary variable to rewrite one line into two) is enough to work around the issue. Using solc with the --optimize flag also works.

Report versioning

We should add a version field to the json report, so that bugs can be traced back to the corresponding commit.

A way to do it would be to somehow insert the Git commit in the build process, so that it is then used when a report is produced.

Running docker image outputs "Error running securify." on macOS

Using a macOS Mojave. Docker is up to date.

➜ ~ docker version
Client: Docker Engine - Community
Version: 18.09.0
API version: 1.39
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:47:43 2018
OS/Arch: darwin/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.0
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:55:00 2018
OS/Arch: linux/amd64
Experimental: true

I have cloned the securify git repository, and ran docker build . -t securify successfully. I have checked that the Docker image was built, and is available.

When running docker run securify as per the project documentation, i get

Error running securify.

Running with a mounted volume yields the same output. I am confident the volume had only one contract in it, which was successfully analyzed with other engines.

Error running securify.

Docker container NullPointerException

Potentially related to #16? I am trying to build and run the Dockerfile from the current master@569893a. When I run it against the example it runs fine, but when I mount my sol files at /contracts I get this output:

[Ljava.lang.StackTraceElement;@6872f9c8
FAILURE
Exception in thread "main" java.lang.NullPointerException
	at ch.securify.analysis.Dataflow.dispose(Dataflow.java:43)
	at ch.securify.Main.checkPatterns(Main.java:397)
	at ch.securify.Main.processHexFile(Main.java:151)
	at ch.securify.Main.processSolidityFile(Main.java:108)
	at ch.securify.Main.main(Main.java:186)
Error: Exited with code 1
Step failed
Error: runner failed
Task failed

Mention errors in the json output

Steps to reproduce

  • run securify on some contract that cannot be decompiled
  • the json output will contain "results": {} with no clear indication that there was a decompilation failure

Test the absence of conflicts in the examples

In Securify, a conflict happens when both the safe and the violation behaviors of a same patterns are matched, meaning that there's an inconsistency somewhere.

We should test that, for all the examples, there is no conflict.

Unrestricted write conflicts

The tests currently have some conflicts for the "unrestricted write" pattern, e.g.:

{
  "src/test/resources/solidity/reentrancy2.sol:Ownable": {
    "results": {
      "DAO": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "DAOConstantGas": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "LockedEther": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": [
          56
        ]
      },
      "MissingInputValidation": {
        "violations": [],
        "warnings": [
          57,
          83
        ],
        "safe": [],
        "conflicts": []
      },
      "TODAmount": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "TODReceiver": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnhandledException": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnrestrictedEtherFlow": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnrestrictedWrite": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": [
          86
        ]
      }
    },
    "securifyErrors": {
      "errors": []
    }
  },
  "src/test/resources/solidity/reentrancy2.sol:SafeMath": {
    "results": {
      "DAO": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "DAOConstantGas": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "LockedEther": {
        "violations": [],
        "warnings": [
          8
        ],
        "safe": [],
        "conflicts": []
      },
      "MissingInputValidation": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "TODAmount": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "TODReceiver": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnhandledException": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnrestrictedEtherFlow": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "UnrestrictedWrite": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      }
    },
    "securifyErrors": {
      "errors": []
    }
  },
  "src/test/resources/solidity/reentrancy2.sol:Vault": {
    "results": {
      "DAO": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "DAOConstantGas": {
        "violations": [
          148
        ],
        "warnings": [
          132,
          134
        ],
        "safe": [],
        "conflicts": []
      },
      "LockedEther": {
        "violations": [],
        "warnings": [
          96
        ],
        "safe": [],
        "conflicts": []
      },
      "MissingInputValidation": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": []
      },
      "TODAmount": {
        "violations": [],
        "warnings": [
          132,
          134
        ],
        "safe": [
          148
        ],
        "conflicts": []
      },
      "TODReceiver": {
        "violations": [],
        "warnings": [
          134,
          148
        ],
        "safe": [
          132
        ],
        "conflicts": []
      },
      "UnhandledException": {
        "violations": [],
        "warnings": [
          132,
          134,
          148
        ],
        "safe": [],
        "conflicts": []
      },
      "UnrestrictedEtherFlow": {
        "violations": [],
        "warnings": [
          148
        ],
        "safe": [],
        "conflicts": [
          132,
          134
        ]
      },
      "UnrestrictedWrite": {
        "violations": [],
        "warnings": [],
        "safe": [],
        "conflicts": [
          5,
          86,
          120,
          121,
          130,
          145
        ]
      }
    },
    "securifyErrors": {
      "errors": []
    }
  }
}
pragma solidity ^0.4.21;



/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    // uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return a / b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c = a + b;
    assert(c >= a);
    return c;
  }
}


/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    emit OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

}

/**
 * @title RefundVault
 * @dev This contract is used for storing funds while a crowdsale
 * is in progress.
 */
contract Vault is Ownable {
  using SafeMath for uint256;

  mapping (address => uint256) public deposited;
  address[] fundsOwners;
  address public wallet;

  event Refunded(address beneficiary, uint256 weiAmount);
  event Deposited(address beneficiary, uint256 weiAmount);
  event Released(address beneficiary, uint256 weiAmount);
  event PartialRefund(address beneficiary, uint256 weiAmount);

  /**
   * @param _wallet Vault address
   */
  function Vault(address _wallet) public {
    require(_wallet != address(0));
    wallet = _wallet;
  }

  /**
   * @param beneficiary Investor address
   */
  function deposit(address beneficiary) onlyOwner public payable {
    deposited[beneficiary] = deposited[beneficiary].add(msg.value);
    fundsOwners.push(beneficiary);
    Deposited(beneficiary, msg.value);
  }

  /**
   * @param beneficiary Investor address
   */
  function release(address beneficiary, uint256 overflow) onlyOwner public {
    uint256 amount = deposited[beneficiary].sub(overflow);
    deposited[beneficiary] = 0;

    wallet.transfer(amount);
    if (overflow > 0) {
      beneficiary.transfer(overflow);
      PartialRefund(beneficiary, overflow);
    }
    Released(beneficiary, amount);
  }

  /**
   * @param beneficiary Investor address
   */
  function refund(address beneficiary) onlyOwner public {
    uint256 depositedValue = deposited[beneficiary];
    deposited[beneficiary] = 0;
    
    Refunded(beneficiary, depositedValue);
    beneficiary.transfer(depositedValue);
  }

  /**
   * refunds all funds on the vault to the corresponding beneficiaries
   * @param indexes list of indexes to look up for in the fundsOwner array to refund
   */
  function refundAll(uint[] indexes) onlyOwner public {
    require(indexes.length <= fundsOwners.length);
    for (uint i = 0; i < indexes.length; i++) {
      refund(fundsOwners[indexes[i]]);
    }
  }
}

Decompilation Error with --truffle

Hello,

While scanning my contract using Securify, I get the following message:


Processing contract: /project/contracts/ReputationBook.sol:ReputationBook
  Attempt to decompile the contract with methods...
  Failed to decompile methods. Attempt to decompile the contract without identifying methods...
  Decompilation failed.
Error in Securify
java.lang.NullPointerException
	at ch.securify.decompiler.DestackerFallback.findJumpCondition(DestackerFallback.java:403)
	at ch.securify.decompiler.DestackerFallback.handleStackMerging(DestackerFallback.java:356)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:205)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:201)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238)
	at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:131)
	at ch.securify.decompiler.DecompilerFallback.decompile(DecompilerFallback.java:73)
	at ch.securify.Main.decompileContract(Main.java:296)
	at ch.securify.Main.processHexFile(Main.java:160)
	at ch.securify.Main.processCompilationOutput(Main.java:129)
	at ch.securify.Main.mainFromCompilationOutput(Main.java:105)
	at ch.securify.Main.main(Main.java:241)
Error, skipping: /project/contracts/ReputationBook.sol:ReputationBook

As a result, Securify is skipping the contract that I want to scan.

Please help me address this.

OpenZeppelin ERC20: IllegalArgumentException

I'm running into an error when scanning a contract that references the OpenZeppelin ERC20 contract:

Exception in thread "main" java.lang.IllegalArgumentException: fromIndex(0) > toIndex(-1)
	at java.util.ArrayList.subListRangeCheck(ArrayList.java:1014)
	at java.util.ArrayList.subList(ArrayList.java:1004)
	at ch.securify.CompilationHelpers.bytecodeOffsetToSourceOffset(CompilationHelpers.java:59)
	at ch.securify.CompilationHelpers.getMatchedLines(CompilationHelpers.java:111)
	at ch.securify.CompilationHelpers.getMappingsFromStatusFile(CompilationHelpers.java:135)
	at ch.securify.Main.processSolidityFile(Main.java:110)
	at ch.securify.Main.main(Main.java:186)

Steps to reproduce:

  1. Download the OpenZeppelin ERC20.sol
  2. Run Securify as documented in the readme (docker run -v $(pwd)/folder_with_solidity_files:/contracts securify)

I have a feeling this could be due to the fact that ERC20.sol is an abstract contract. I am referencing the ERC20 abstract contract in another contract that accepts ERC20 token transfers.

Pattern ideas

  • two functions seem to have the same effects (bug): we've had cases where clients don't override functions properly: they will rename the function, guard it with a custom modifier thinking that it protects this functionality, but the parent function is still available. If Securify detects that the same data changes occur with two functions, a warning can be issued to ask whether this makes sense.

  • invariant is checked on the initial value instead of the final one (bug): typically, a cap is checked at the beginning, without using the sum of already bought tokens and newly bought tokens. In Securify: dependency on two storage variables (already bought tokens and cap), no dependency on input (newly bought tokens), new value of some storage variable depends on input.

  • checks-effects-interactions pattern not followed (design): related to reentrancy, but broader.

  • There should be no checks on the msg.value if it has to be 0 (e.g. non-payable function) (superseded by ethereum/solidity#3770)

  • Call target and at least first 4 bytes of data of a CALL are user-controlled.

Print solc Stacktrace when solc fails

I have checked the following

  • The souffle binary is available, output when running souffle:
============================================================================
souffle -- A datalog engine.
Usage: souffle [OPTION] FILE.
----------------------------------------------------------------------------
Options:
        -F<DIR>                 --fact-dir=<DIR>                        Specify directory for fact files.
        -I<DIR>                 --include-dir=<DIR>                     Specify directory for include files.
        -D<DIR>                 --output-dir=<DIR>                      Specify directory for output files (if <DIR> is -, stdout is used).
        -j<N>                   --jobs=<N>                              Run interpreter/compiler in parallel using N threads, N=auto for system default.
        -c                      --compile                               Generate C++ source code, compile to a binary executable, then run this executable.
        -g<FILE>                --generate=<FILE>                       Generate C++ source code for the given Datalog program and write it to <FILE>.
        -w                      --no-warn                               Disable warnings.
        -m<RELATIONS>           --magic-transform=<RELATIONS>           Enable magic set transformation changes on the given relations, use '*' for all.
        -z<TRANSFORMERS>        --disable-transformers=<TRANSFORMERS>   Disable the given AST transformers.
        -o<FILE>                --dl-program=<FILE>                     Generate C++ source code, written to <FILE>, and compile this to a binary executable (without executing it).
        -l                      --live-profile                          Enable live profiling.
        -p<FILE>                --profile=<FILE>                        Enable profiling, and write profile data to <FILE>.
        -r<FILE>                --debug-report=<FILE>                   Write HTML debug report to <FILE>.
        -t<EXPLAIN>             --provenance=<EXPLAIN>                  Enable provenance information via guided SLD.
        -d<type>                --data-structure=<type>                 Specify data structure (brie/btree/eqrel/rbtset/hashset).
        -e<[ file | mpi ]>      --engine=<[ file | mpi ]>               Specify communication engine for distributed execution.
                                --hostfile=<FILE>                       Specify --hostfile option for call to mpiexec when using mpi as execution engine.
        -v                      --verbose                               Verbose output.
        -h                      --help                                  Display this help message.
----------------------------------------------------------------------------
Version: 1.4.0-174-geb5857a
----------------------------------------------------------------------------
Copyright (c) 2016-18 The Souffle Developers.
Copyright (c) 2013-16 Oracle and/or its affiliates.
All rights reserved.
============================================================================
  • Output of solc --version
solc, the solidity compiler commandline interface
Version: 0.4.25+commit.59dbf8f1.Linux.g++
  • Output of solc --bin-runtime MyContract.sol
src/test/resources/solidity/transaction-reordering.sol:1:1: Error: Source file requires different compiler version (current compiler is 0.4.25+commit.59dbf8f1.Linux.g++ - note that nightly builds are considered to be strictly less than the released version
pragma solidity 0.4.24;
^---------------------^
src/test/resources/solidity/transaction-reordering.sol:5:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(x);
        ^----------------^
src/test/resources/solidity/transaction-reordering.sol:11:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(y);
        ^----------------^
src/test/resources/solidity/transaction-reordering.sol:15:18: Warning: Using contract member "balance" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).balance" instead.
        uint x = this.balance;
                 ^----------^
src/test/resources/solidity/transaction-reordering.sol:16:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(x);
        ^----------------^
  • I can reproduce this issue in a Docker container with the following command

NA

Steps to reproduce

  1. Run java -jar build/libs/securify-0.1.jar -fs src/test/resources/solidity/transaction-reordering.sol with the wrong version of solc installed.
  2. Receive the following unhelpful output:
Exception in thread "main" java.io.IOException
        at ch.securify.CompilationHelpers.compileContracts(CompilationHelpers.java:97)
        at ch.securify.Main.processSolidityFile(Main.java:91)
        at ch.securify.Main.main(Main.java:186)

Proposed solution

Modify CompilationHelpers.compileContracts to the following:

ProcessBuilder p = new ProcessBuilder("solc", "--combined-json", "abi,ast,bin-runtime,srcmap-runtime", filesol);

        File f = File.createTempFile("securify_compilation_", ".json");
        f.deleteOnExit();

        final Process process = p.redirectOutput(f).start();

        Thread t = new Thread(){
            public void run(){
                try {
                    InputStreamReader isr = new InputStreamReader(process.getErrorStream());
                    BufferedReader br = new BufferedReader(isr);
                    String line = br.readLine();
                    if (!line.contains("Error")) {
                        return;
                    }
                    String stacktrace = line + "\n";
                    while ( (line = br.readLine()) != null) {
                        stacktrace += line + "\n";
                    }
                    System.err.println(stacktrace);
                } catch (IOException ioe) {
                    ioe.printStackTrace();  
                }
            }
        };
        t.start();

        process.waitFor();
        int exitValue = process.exitValue();
        if(exitValue != 0){            
            throw new RuntimeException();
        }


        JsonObject jsonObject = new JsonParser().parse(readFile(f.getPath())).getAsJsonObject();

        return jsonObject.get("contracts").getAsJsonObject();

and add the following imports:

import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.Thread;
import java.lang.RuntimeException;

Use of RuntimeException is suggested over use of IOException

Crash when not using default solc version

else:
solc_version = next(COMP_VERSION1_REX.finditer(l))
if solc_version not in SOLC_VERSIONS:
raise CompilerVersionNotSupported(
solc_version, solc_version < SOLC_VERSIONS[0])
return solc_version

When not matching the solc version using ^ in the pragma, the solc_version variable contains a _sre.SRE_Match object, but it is treated as a string. This causes several errors such as comparison to strings in line 78, and undeclared method calls (.split()) after the _sre.SRE_Match object is returned from the function.

To test this, you can actually just try to run the default example using:

docker run securify

Add Soufflé binaries to .jar

Currently the binaries generated in the build/ folder have to be copied along with the .jar. It would be better to just have everything runnable via the .jar.

Add alternative to specify solc binary manually.

Not using the template because this is mostly a feature, not a bug. Everything checks out perfectly.

The thing is that all my workstations systems default solc to v0.5, and when auditing I need to be able to have different versions (0.4.25 for example), otherwise securify crashes because of solc's errors (breaking changess, etc).

Going to add a PR myself after testing it works as intended.

Thanks for your good work :)

Error when running Securify on bytecode hex file

Running Securify on a bytecode hex file gives the following error -
I'm running the latest build.

java -jar build/libs/securify-0.1.jar -fh contract.hex

Attempt to decompile the contract with methods... Failed to decompile methods. Attempt to decompile the contract without identifying methods... Decompilation failed. Error in Securify Exception in thread "main" java.lang.NullPointerException at ch.securify.decompiler.DestackerFallback.findJumpCondition(DestackerFallback.java:403) at ch.securify.decompiler.DestackerFallback.handleStackMerging(DestackerFallback.java:356) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:205) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:201) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:216) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:238) at ch.securify.decompiler.DestackerFallback.decompile(DestackerFallback.java:131) at ch.securify.decompiler.DecompilerFallback.decompile(DecompilerFallback.java:73) at ch.securify.Main.decompileContract(Main.java:299) at ch.securify.Main.processHexFile(Main.java:163) at ch.securify.Main.main(Main.java:273)

contract.hex -
60606040526004361061012f5763ffffffff60e060020a60003504166325e89283811461013a5780632c4e722e146101615780632f923c59146101865780633197cbb6146101995780634042b66f146101ac578063471efce5146101bf5780634dc8ed02146101d257806350669a03146101e8578063518ab2a8146101fb578063521eb2731461020e57806360219c7b1461023d5780636317cc5b146102505780636cd022971461026357806378e97925146102855780637d64bcb4146102985780638746656f146102ab5780638da5cb5b146102c1578063a67bb583146102d4578063ccd65c0a146102e7578063da74ce27146102fa578063ec8ac4d81461030d578063ecb70fb714610321578063f2a0928d14610334578063f2fde38b14610347578063fc0c546a14610366575b61013833610379565b005b341561014557600080fd5b61014d6104c9565b604051901515815260200160405180910390f35b341561016c57600080fd5b6101746104d2565b60405190815260200160405180910390f35b341561019157600080fd5b6101746104d8565b34156101a457600080fd5b6101746104de565b34156101b757600080fd5b6101746104e4565b34156101ca57600080fd5b6101746104ea565b34156101dd57600080fd5b6101746004356104f0565b34156101f357600080fd5b610138610504565b341561020657600080fd5b610174610574565b341561021957600080fd5b61022161057a565b604051600160a060020a03909116815260200160405180910390f35b341561024857600080fd5b610174610589565b341561025b57600080fd5b61017461058f565b341561026e57600080fd5b610138600160a060020a0360043516602435610595565b341561029057600080fd5b610174610688565b34156102a357600080fd5b61013861068e565b34156102b657600080fd5b61013860043561070e565b34156102cc57600080fd5b610221610782565b34156102df57600080fd5b610174610791565b34156102f257600080fd5b610138610797565b341561030557600080fd5b610174610867565b610138600160a060020a0360043516610379565b341561032c57600080fd5b61014d61086d565b341561033f57600080fd5b610174610876565b341561035257600080fd5b610138600160a060020a036004351661087c565b341561037157600080fd5b610221610917565b6000610383610926565b80156103925750600754601354105b151561039d57600080fd5b600160a060020a038216158015906103bd575067016345785d8a00003410155b15156103c857600080fd5b601154421161040d57600254601354106103e157600080fd5b600b54610406906103f990600263ffffffff61095616565b349063ffffffff61095616565b905061042c565b60125460ff16151561041e57600080fd5b6104296103f961098c565b90505b60135461043f908263ffffffff6109f216565b601355600154600160a060020a03166340c10f19838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156104a157600080fd5b6102c65a03f115156104b257600080fd5b50505060405180519050506104c5610a01565b5050565b60125460ff1681565b600b5481565b60035481565b60095481565b600c5481565b60025481565b600d81600481106104fd57fe5b0154905081565b60005433600160a060020a0390811691161461051f57600080fd5b600154600160a060020a0316633f4ba83a6040518163ffffffff1660e060020a028152600401600060405180830381600087803b151561055e57600080fd5b6102c65a03f1151561056f57600080fd5b505050565b60135481565b600a54600160a060020a031681565b60075481565b60055481565b60005433600160a060020a039081169116146105b057600080fd5b6007546013546105c6908363ffffffff6109f216565b11156105d157600080fd5b6000811180156105e95750600160a060020a03821615155b15156105f457600080fd5b601354610607908263ffffffff6109f216565b601355600154600160a060020a03166340c10f19838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561066957600080fd5b6102c65a03f1151561067a57600080fd5b505050604051805150505050565b60085481565b60005433600160a060020a039081169116146106a957600080fd5b600154600160a060020a0316637d64bcb46000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156106f157600080fd5b6102c65a03f1151561070257600080fd5b50505060405180515050565b60005433600160a060020a0390811691161461072957600080fd5b8060095410801561073c575060125460ff165b151561074757600080fd5b60098190557f510de15a452138d481e5e964b168dcec3480a1fa9f68b18bd243765e153c888f8160405190815260200160405180910390a150565b600054600160a060020a031681565b60045481565b6000805433600160a060020a039081169116146107b357600080fd5b6011544211806107c7575060025460135410155b15156107d257600080fd5b60125460ff16156107e257600080fd5b6011544210156107f157426011555b6012805460ff191660011790556108114262093a8063ffffffff6109f216565b600d555060015b600481101561085e5761084762093a80600d60001984016004811061083957fe5b01549063ffffffff6109f216565b600d826004811061085457fe5b0155600101610818565b50601054600955565b60065481565b60095442115b90565b60115481565b60005433600160a060020a0390811691161461089757600080fd5b600160a060020a03811615156108ac57600080fd5b600054600160a060020a0380831691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600154600160a060020a031681565b6000806000600854421015801561093f57506009544211155b91505034151581801561094f5750805b9250505090565b6000808315156109695760009150610985565b5082820282848281151561097957fe5b041461098157fe5b8091505b5092915050565b6000601154421180156109a25750600754601354105b156109eb576109e4600b546109d860646109cc6109bd610a37565b600b549063ffffffff61095616565b9063ffffffff610ba616565b9063ffffffff6109f216565b9050610873565b50600b5490565b60008282018381101561098157fe5b600a54600160a060020a03163480156108fc0290604051600060405180830381858888f193505050501515610a3557600080fd5b565b600080600080600654601354101515610a4f57600080fd5b5042915060005b6004811015610a8757600d8160048110610a6c57fe5b01548311610a7f57806001019150610a87565b600101610a56565b816001148015610a9a5750600354601354105b15610aa457601493505b816001148015610ab8575060035460135410155b15610ac257600f93505b816001148015610ad6575060045460135410155b15610ae057600a93505b816001148015610af4575060055460135410155b15610afe57600093505b816002148015610b115750600454601354105b15610b1b57600f93505b816002148015610b2f575060045460135410155b15610b3957600a93505b816002148015610b4d575060055460135410155b15610b5757600093505b816003148015610b6a5750600554601354105b15610b7457600a93505b816003148015610b88575060055460135410155b15610b9257600093505b8160041415610ba057600093505b50505090565b6000808284811515610bb457fe5b049493505050505600a165627a7a72305820262ab9d58bca518df4fce066a7ed7b41a54e72aa17aad296a0b6418a2b75266e0029

This is the contract present at address 0x73Dac1423d69651a6F85462B45260f7c05de3548 on the ethereum blockchain.

Any help would be appreciated.

Line number is not correct when vulnerability occurs in helper routine

For some operations helper routines are added to the binary during compilation. In the source mapping these instructions reference the whole contract. Therefore if some vulnerability is detected in these helper routines, the line number of the contract definition is returned by securify.

To counteract, either helper routines should be detected during the analysis and jump instructions to them returned as the vulnerable instruction or another mechanism to track the vulnerability back to the actual line of code should be implemented.

Example contract:

contract c {
    int[] a;
    function f() public {
        a.length = 1;
    } 
}

More information:
ethereum/solidity#5135

Output json report to stdout with -fh

Currently the only option to get the report in json format is to write it to a file given with the --output or --livestatusfile. It would be handy in certain situations to pipe the json report to stdout.

StackOverflowError in contracts with a lot of statements

See also description at https://github.com/eth-sri/securify#known-limitations

Steps to reproduce

With
lots_of_statements.sol:

pragma solidity ^0.4.24;

interface ERC20 {
    function balanceOf(address _owner) external constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) external;
}

contract C {
    ERC20 t;

    function add(address _target) internal {
        t.transfer(_target, 0);
    }

    function f() public {
        add(0x0000000000000000000000000000000000000000);
        add(0x0000000000000000000000000000000000000001);
        add(0x0000000000000000000000000000000000000002);
        add(0x0000000000000000000000000000000000000003);
        add(0x0000000000000000000000000000000000000004);
        add(0x0000000000000000000000000000000000000005);
        add(0x0000000000000000000000000000000000000006);
        add(0x0000000000000000000000000000000000000007);
        add(0x0000000000000000000000000000000000000008);
        add(0x0000000000000000000000000000000000000009);
        add(0x0000000000000000000000000000000000000010);
        add(0x0000000000000000000000000000000000000011);
        add(0x0000000000000000000000000000000000000012);
        add(0x0000000000000000000000000000000000000013);
        add(0x0000000000000000000000000000000000000014);
        add(0x0000000000000000000000000000000000000015);
        add(0x0000000000000000000000000000000000000016);
        add(0x0000000000000000000000000000000000000017);
        add(0x0000000000000000000000000000000000000018);
        add(0x0000000000000000000000000000000000000019);
        add(0x0000000000000000000000000000000000000020);
        add(0x0000000000000000000000000000000000000021);
        add(0x0000000000000000000000000000000000000022);
        add(0x0000000000000000000000000000000000000023);
        add(0x0000000000000000000000000000000000000024);
        add(0x0000000000000000000000000000000000000025);
        add(0x0000000000000000000000000000000000000026);
        add(0x0000000000000000000000000000000000000027);
        add(0x0000000000000000000000000000000000000028);
        add(0x0000000000000000000000000000000000000029);
        add(0x0000000000000000000000000000000000000030);
        add(0x0000000000000000000000000000000000000031);
        add(0x0000000000000000000000000000000000000032);
        add(0x0000000000000000000000000000000000000033);
        add(0x0000000000000000000000000000000000000034);
        add(0x0000000000000000000000000000000000000035);
        add(0x0000000000000000000000000000000000000036);
        add(0x0000000000000000000000000000000000000037);
        add(0x0000000000000000000000000000000000000038);
        add(0x0000000000000000000000000000000000000039);
        add(0x0000000000000000000000000000000000000040);
        add(0x0000000000000000000000000000000000000041);
        add(0x0000000000000000000000000000000000000042);
        add(0x0000000000000000000000000000000000000043);
        add(0x0000000000000000000000000000000000000044);
        add(0x0000000000000000000000000000000000000045);
        add(0x0000000000000000000000000000000000000046);
        add(0x0000000000000000000000000000000000000047);
        add(0x0000000000000000000000000000000000000048);
        add(0x0000000000000000000000000000000000000049);
        add(0x0000000000000000000000000000000000000050);
        add(0x0000000000000000000000000000000000000051);
        add(0x0000000000000000000000000000000000000052);
        add(0x0000000000000000000000000000000000000053);
        add(0x0000000000000000000000000000000000000054);
        add(0x0000000000000000000000000000000000000055);
        add(0x0000000000000000000000000000000000000056);
        add(0x0000000000000000000000000000000000000057);
        add(0x0000000000000000000000000000000000000058);
        add(0x0000000000000000000000000000000000000059);
        add(0x0000000000000000000000000000000000000060);
        add(0x0000000000000000000000000000000000000061);
        add(0x0000000000000000000000000000000000000062);
        add(0x0000000000000000000000000000000000000063);
        add(0x0000000000000000000000000000000000000064);
        add(0x0000000000000000000000000000000000000065);
        add(0x0000000000000000000000000000000000000066);
        add(0x0000000000000000000000000000000000000067);
        add(0x0000000000000000000000000000000000000068);
        add(0x0000000000000000000000000000000000000069);
        add(0x0000000000000000000000000000000000000070);
        add(0x0000000000000000000000000000000000000071);
        add(0x0000000000000000000000000000000000000072);
        add(0x0000000000000000000000000000000000000073);
        add(0x0000000000000000000000000000000000000074);
        add(0x0000000000000000000000000000000000000075);
        add(0x0000000000000000000000000000000000000076);
        add(0x0000000000000000000000000000000000000077);
        add(0x0000000000000000000000000000000000000078);
        add(0x0000000000000000000000000000000000000079);
        add(0x0000000000000000000000000000000000000080);
        add(0x0000000000000000000000000000000000000081);
        add(0x0000000000000000000000000000000000000082);
        add(0x0000000000000000000000000000000000000083);
        add(0x0000000000000000000000000000000000000084);
        add(0x0000000000000000000000000000000000000085);
        add(0x0000000000000000000000000000000000000086);
        add(0x0000000000000000000000000000000000000087);
        add(0x0000000000000000000000000000000000000088);
        add(0x0000000000000000000000000000000000000089);
        add(0x0000000000000000000000000000000000000090);
        add(0x0000000000000000000000000000000000000091);
        add(0x0000000000000000000000000000000000000092);
        add(0x0000000000000000000000000000000000000093);
        add(0x0000000000000000000000000000000000000094);
        add(0x0000000000000000000000000000000000000095);
        add(0x0000000000000000000000000000000000000096);
        add(0x0000000000000000000000000000000000000097);
        add(0x0000000000000000000000000000000000000098);
        add(0x0000000000000000000000000000000000000099);
        add(0x0000000000000000000000000000000000000100);
        add(0x0000000000000000000000000000000000000101);
        add(0x0000000000000000000000000000000000000102);
        add(0x0000000000000000000000000000000000000103);
        add(0x0000000000000000000000000000000000000104);
        add(0x0000000000000000000000000000000000000105);
        add(0x0000000000000000000000000000000000000106);
        add(0x0000000000000000000000000000000000000107);
        add(0x0000000000000000000000000000000000000108);
        add(0x0000000000000000000000000000000000000109);
        add(0x0000000000000000000000000000000000000110);
        add(0x0000000000000000000000000000000000000111);
        add(0x0000000000000000000000000000000000000112);
        add(0x0000000000000000000000000000000000000113);
        add(0x0000000000000000000000000000000000000114);
        add(0x0000000000000000000000000000000000000115);
        add(0x0000000000000000000000000000000000000116);
        add(0x0000000000000000000000000000000000000117);
        add(0x0000000000000000000000000000000000000118);
        add(0x0000000000000000000000000000000000000119);
        add(0x0000000000000000000000000000000000000120);
        add(0x0000000000000000000000000000000000000121);
        add(0x0000000000000000000000000000000000000122);
        add(0x0000000000000000000000000000000000000123);
        add(0x0000000000000000000000000000000000000124);
        add(0x0000000000000000000000000000000000000125);
        add(0x0000000000000000000000000000000000000126);
        add(0x0000000000000000000000000000000000000127);
        add(0x0000000000000000000000000000000000000128);
        add(0x0000000000000000000000000000000000000129);
        add(0x0000000000000000000000000000000000000130);
        add(0x0000000000000000000000000000000000000131);
        add(0x0000000000000000000000000000000000000132);
        add(0x0000000000000000000000000000000000000133);
        add(0x0000000000000000000000000000000000000134);
        add(0x0000000000000000000000000000000000000135);
        add(0x0000000000000000000000000000000000000136);
        add(0x0000000000000000000000000000000000000137);
        add(0x0000000000000000000000000000000000000138);
        add(0x0000000000000000000000000000000000000139);
        add(0x0000000000000000000000000000000000000140);
        add(0x0000000000000000000000000000000000000141);
        add(0x0000000000000000000000000000000000000142);
        add(0x0000000000000000000000000000000000000143);
        add(0x0000000000000000000000000000000000000144);
        add(0x0000000000000000000000000000000000000145);
        add(0x0000000000000000000000000000000000000146);
        add(0x0000000000000000000000000000000000000147);
        add(0x0000000000000000000000000000000000000148);
        add(0x0000000000000000000000000000000000000149);
        add(0x0000000000000000000000000000000000000150);
        add(0x0000000000000000000000000000000000000151);
        add(0x0000000000000000000000000000000000000152);
        add(0x0000000000000000000000000000000000000153);
        add(0x0000000000000000000000000000000000000154);
        add(0x0000000000000000000000000000000000000155);
        add(0x0000000000000000000000000000000000000156);
        add(0x0000000000000000000000000000000000000157);
        add(0x0000000000000000000000000000000000000158);
        add(0x0000000000000000000000000000000000000159);
        add(0x0000000000000000000000000000000000000160);
        add(0x0000000000000000000000000000000000000161);
        add(0x0000000000000000000000000000000000000162);
        add(0x0000000000000000000000000000000000000163);
        add(0x0000000000000000000000000000000000000164);
        add(0x0000000000000000000000000000000000000165);
        add(0x0000000000000000000000000000000000000166);
        add(0x0000000000000000000000000000000000000167);
        add(0x0000000000000000000000000000000000000168);
        add(0x0000000000000000000000000000000000000169);
        add(0x0000000000000000000000000000000000000170);
        add(0x0000000000000000000000000000000000000171);
        add(0x0000000000000000000000000000000000000172);
        add(0x0000000000000000000000000000000000000173);
        add(0x0000000000000000000000000000000000000174);
        add(0x0000000000000000000000000000000000000175);
        add(0x0000000000000000000000000000000000000176);
        add(0x0000000000000000000000000000000000000177);
        add(0x0000000000000000000000000000000000000178);
        add(0x0000000000000000000000000000000000000179);
        add(0x0000000000000000000000000000000000000180);
        add(0x0000000000000000000000000000000000000181);
        add(0x0000000000000000000000000000000000000182);
        add(0x0000000000000000000000000000000000000183);
        add(0x0000000000000000000000000000000000000184);
        add(0x0000000000000000000000000000000000000185);
        add(0x0000000000000000000000000000000000000186);
        add(0x0000000000000000000000000000000000000187);
        add(0x0000000000000000000000000000000000000188);
        add(0x0000000000000000000000000000000000000189);
        add(0x0000000000000000000000000000000000000190);
        add(0x0000000000000000000000000000000000000191);
        add(0x0000000000000000000000000000000000000192);
        add(0x0000000000000000000000000000000000000193);
        add(0x0000000000000000000000000000000000000194);
        add(0x0000000000000000000000000000000000000195);
        add(0x0000000000000000000000000000000000000196);
        add(0x0000000000000000000000000000000000000197);
        add(0x0000000000000000000000000000000000000198);
        add(0x0000000000000000000000000000000000000199);
        add(0x0000000000000000000000000000000000000200);
        add(0x0000000000000000000000000000000000000201);
        add(0x0000000000000000000000000000000000000202);
        add(0x0000000000000000000000000000000000000203);
        add(0x0000000000000000000000000000000000000204);
        add(0x0000000000000000000000000000000000000205);
        add(0x0000000000000000000000000000000000000206);
        add(0x0000000000000000000000000000000000000207);
        add(0x0000000000000000000000000000000000000208);
        add(0x0000000000000000000000000000000000000209);
        add(0x0000000000000000000000000000000000000210);
        add(0x0000000000000000000000000000000000000211);
        add(0x0000000000000000000000000000000000000212);
        add(0x0000000000000000000000000000000000000213);
        add(0x0000000000000000000000000000000000000214);
        add(0x0000000000000000000000000000000000000215);
        add(0x0000000000000000000000000000000000000216);
        add(0x0000000000000000000000000000000000000217);
        add(0x0000000000000000000000000000000000000218);
        add(0x0000000000000000000000000000000000000219);
        add(0x0000000000000000000000000000000000000220);
        add(0x0000000000000000000000000000000000000221);
        add(0x0000000000000000000000000000000000000222);
        add(0x0000000000000000000000000000000000000223);
        add(0x0000000000000000000000000000000000000224);
        add(0x0000000000000000000000000000000000000225);
        add(0x0000000000000000000000000000000000000226);
        add(0x0000000000000000000000000000000000000227);
        add(0x0000000000000000000000000000000000000228);
        add(0x0000000000000000000000000000000000000229);
        add(0x0000000000000000000000000000000000000230);
        add(0x0000000000000000000000000000000000000231);
        add(0x0000000000000000000000000000000000000232);
        add(0x0000000000000000000000000000000000000233);
        add(0x0000000000000000000000000000000000000234);
        add(0x0000000000000000000000000000000000000235);
        add(0x0000000000000000000000000000000000000236);
        add(0x0000000000000000000000000000000000000237);
        add(0x0000000000000000000000000000000000000238);
        add(0x0000000000000000000000000000000000000239);
        add(0x0000000000000000000000000000000000000240);
        add(0x0000000000000000000000000000000000000241);
        add(0x0000000000000000000000000000000000000242);
        add(0x0000000000000000000000000000000000000243);
        add(0x0000000000000000000000000000000000000244);
        add(0x0000000000000000000000000000000000000245);
        add(0x0000000000000000000000000000000000000246);
        add(0x0000000000000000000000000000000000000247);
        add(0x0000000000000000000000000000000000000248);
        add(0x0000000000000000000000000000000000000249);
        add(0x0000000000000000000000000000000000000250);
        add(0x0000000000000000000000000000000000000251);
        add(0x0000000000000000000000000000000000000252);
        add(0x0000000000000000000000000000000000000253);
        add(0x0000000000000000000000000000000000000254);
        add(0x0000000000000000000000000000000000000255);
        add(0x0000000000000000000000000000000000000256);
        add(0x0000000000000000000000000000000000000257);
        add(0x0000000000000000000000000000000000000258);
        add(0x0000000000000000000000000000000000000259);
        add(0x0000000000000000000000000000000000000260);
        add(0x0000000000000000000000000000000000000261);
        add(0x0000000000000000000000000000000000000262);
        add(0x0000000000000000000000000000000000000263);
        add(0x0000000000000000000000000000000000000264);
        add(0x0000000000000000000000000000000000000265);
        add(0x0000000000000000000000000000000000000266);
        add(0x0000000000000000000000000000000000000267);
        add(0x0000000000000000000000000000000000000268);
        add(0x0000000000000000000000000000000000000269);
        add(0x0000000000000000000000000000000000000270);
        add(0x0000000000000000000000000000000000000271);
        add(0x0000000000000000000000000000000000000272);
        add(0x0000000000000000000000000000000000000273);
        add(0x0000000000000000000000000000000000000274);
        add(0x0000000000000000000000000000000000000275);
        add(0x0000000000000000000000000000000000000276);
        add(0x0000000000000000000000000000000000000277);
        add(0x0000000000000000000000000000000000000278);
        add(0x0000000000000000000000000000000000000279);
        add(0x0000000000000000000000000000000000000280);
        add(0x0000000000000000000000000000000000000281);
        add(0x0000000000000000000000000000000000000282);
        add(0x0000000000000000000000000000000000000283);
        add(0x0000000000000000000000000000000000000284);
        add(0x0000000000000000000000000000000000000285);
        add(0x0000000000000000000000000000000000000286);
        add(0x0000000000000000000000000000000000000287);
        add(0x0000000000000000000000000000000000000288);
        add(0x0000000000000000000000000000000000000289);
        add(0x0000000000000000000000000000000000000290);
        add(0x0000000000000000000000000000000000000291);
        add(0x0000000000000000000000000000000000000292);
        add(0x0000000000000000000000000000000000000293);
        add(0x0000000000000000000000000000000000000294);
        add(0x0000000000000000000000000000000000000295);
        add(0x0000000000000000000000000000000000000296);
        add(0x0000000000000000000000000000000000000297);
        add(0x0000000000000000000000000000000000000298);
        add(0x0000000000000000000000000000000000000299);
        add(0x0000000000000000000000000000000000000300);
        add(0x0000000000000000000000000000000000000301);
        add(0x0000000000000000000000000000000000000302);
        add(0x0000000000000000000000000000000000000303);
        add(0x0000000000000000000000000000000000000304);
        add(0x0000000000000000000000000000000000000305);
        add(0x0000000000000000000000000000000000000306);
        add(0x0000000000000000000000000000000000000307);
        add(0x0000000000000000000000000000000000000308);
        add(0x0000000000000000000000000000000000000309);
        add(0x0000000000000000000000000000000000000310);
        add(0x0000000000000000000000000000000000000311);
        add(0x0000000000000000000000000000000000000312);
        add(0x0000000000000000000000000000000000000313);
        add(0x0000000000000000000000000000000000000314);
        add(0x0000000000000000000000000000000000000315);
        add(0x0000000000000000000000000000000000000316);
        add(0x0000000000000000000000000000000000000317);
        add(0x0000000000000000000000000000000000000318);
        add(0x0000000000000000000000000000000000000319);
        add(0x0000000000000000000000000000000000000320);
        add(0x0000000000000000000000000000000000000321);
        add(0x0000000000000000000000000000000000000322);
        add(0x0000000000000000000000000000000000000323);
        add(0x0000000000000000000000000000000000000324);
        add(0x0000000000000000000000000000000000000325);
        add(0x0000000000000000000000000000000000000326);
        add(0x0000000000000000000000000000000000000327);
        add(0x0000000000000000000000000000000000000328);
        add(0x0000000000000000000000000000000000000329);
        add(0x0000000000000000000000000000000000000330);
        add(0x0000000000000000000000000000000000000331);
        add(0x0000000000000000000000000000000000000332);
        add(0x0000000000000000000000000000000000000333);
        add(0x0000000000000000000000000000000000000334);
        add(0x0000000000000000000000000000000000000335);
        add(0x0000000000000000000000000000000000000336);
    }
}
java -jar build/libs/securify-0.1.jar -fs stat/lots_of_statements.sol

Docker image does not run

I have checked the following

This issue is about the Docker image, so the outputs shown below were run within a Securify container built by following the README.

  • The souffle binary is available, output when running souffle:
============================================================================
souffle -- A datalog engine.
Usage: souffle [OPTION] FILE.
----------------------------------------------------------------------------
Options:
        -F<DIR>                 --fact-dir=<DIR>                        Specify directory for fact files.
        -I<DIR>                 --include-dir=<DIR>                     Specify directory for include files.
        -D<DIR>                 --output-dir=<DIR>                      Specify directory for output files (if <DIR> is -, stdout is used).
        -j<N>                   --jobs=<N>                              Run interpreter/compiler in parallel using N threads, N=auto for system default.
        -c                      --compile                               Generate C++ source code, compile to a binary executable, then run this executable.
        -g<FILE>                --generate=<FILE>                       Generate C++ source code for the given Datalog program and write it to <FILE>.
        -w                      --no-warn                               Disable warnings.
        -m<RELATIONS>           --magic-transform=<RELATIONS>           Enable magic set transformation changes on the given relations, use '*' for all.
        -o<FILE>                --dl-program=<FILE>                     Generate C++ source code, written to <FILE>, andcompile this to a binary executable (without executing it).
        -l                      --live-profile                          Enable live profiling.
        -p<FILE>                --profile=<FILE>                        Enable profiling, and write profile data to <FILE>.
        -r<FILE>                --debug-report=<FILE>                   Write HTML debug report to <FILE>.
        -t<EXPLAIN>             --provenance=<EXPLAIN>                  Enable provenance information via guided SLD.
        -d<type>                --data-structure=<type>                 Specify data structure (brie/btree/eqrel/rbtset/hashset).
        -e<[ file | mpi ]>      --engine=<[ file | mpi ]>               Specify communication engine for distributed execution.
                                --hostfile=<FILE>                       Specify --hostfile option for call to mpiexec when using mpi as execution engine.
        -v                      --verbose                               Verbose output.
        -h                      --help                                  Display this help message.
----------------------------------------------------------------------------
Version: 1.4.0
----------------------------------------------------------------------------
Copyright (c) 2016-18 The Souffle Developers.
Copyright (c) 2013-16 Oracle and/or its affiliates.
All rights reserved.
============================================================================
  • Output of solc --version
solc, the solidity compiler commandline interface
Version: 0.4.24+commit.e67f0147.Linux.g++
  • Output of solc --bin-runtime MyContract.sol

solc --bin-runtime project/example.sol outputs:

project/example.sol:5:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(x);
        ^----------------^
project/example.sol:11:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(y);
        ^----------------^
project/example.sol:15:18: Warning: Using contract member "balance" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).balance" instead.
        uint x = this.balance;
                 ^----------^
project/example.sol:16:9: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
        msg.sender.send(x);
        ^----------------^
project/example.sol:3:5: Warning: No visibility specified. Defaulting to "public".
    function safeTransfer1() {
    ^ (Relevant source part starts here and spans across multiple lines).
project/example.sol:4:18: Warning: "msg.value" used in non-payable function. Do you want to add the "payable" modifier to this function?
        uint x = msg.value;
                 ^-------^
project/example.sol:8:5: Warning: No visibility specified. Defaulting to "public".
    function safeTransfer2() {
    ^ (Relevant source part starts here and spans across multiple lines).
project/example.sol:14:5: Warning: No visibility specified. Defaulting to "public".
    function unsafeTransfer() {
    ^ (Relevant source part starts here and spans across multiple lines).

======= project/example.sol:MarketPlace =======
Binary of the runtime part:
608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633155194c1461005c578063bc5a6c2014610073578063c7961f2a1461008a575b600080fd5b34801561006857600080fd5b506100716100a1565b005b34801561007f57600080fd5b506100886100df565b005b34801561009657600080fd5b5061009f610134565b005b60003490503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff163190503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050505050565b600080606491506064820290503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050505050505600a165627a7a72305820d909d9e9daefa07cd162b106f126c93011e07a987d21e0f19b567a6e1cadf06b0029

  • I can reproduce this issue in a Docker container with the following command

N/A since this is in a Docker container

Steps to reproduce

  1. Clone the repository
  2. Follow the steps in the README to build and run the Docker image

Upon running docker run securify I receive the following output:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/sec/scripts/pysolc.py", line 161, in <module>
    res = compile_project(sys.argv[1])
  File "/sec/scripts/pysolc.py", line 136, in compile_project
    return compile_solfiles(sources, path)
  File "/sec/scripts/pysolc.py", line 126, in compile_solfiles
    stdoutdata, _, _, _ = solc_wrapper(**compiler_kwargs)
  File "/root/.local/lib/python3.6/site-packages/solc/utils/string.py", line 85, in inner
    return force_obj_to_text(fn(*args, **kwargs))
  File "/root/.local/lib/python3.6/site-packages/solc/wrapper.py", line 159, in solc_wrapper
    stderr=subprocess.PIPE)
  File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/root/.py-solc/solc-v0.4.24/bin/solc':'/root/.py-solc/solc-v0.4.24/bin/solc'

Proposed solution

Assuming that the path it is looking for is the desired path of solc, I updated the # install solc part of Dockerfile to this:

# install solc
RUN mkdir -p ~/.py-solc/solc-v0.4.24/bin/

RUN wget https://github.com/ethereum/solidity/releases/download/v0.4.24/solc-static-linux -O ~/.py-solc/solc-v0.4.24/bin/solc &&\
  chmod u+x ~/.py-solc/solc-v0.4.24/bin/solc

After building the image I can now successfully run the demo using docker run securify. However, using docker run -v $(pwd)/contracts:/project securify to run Securify on my own files fails with the message Killed.

Google tells me this problem is due to the max size of the Java heap memory, which is set to 16GB in docker_run_securify. My machine only has 8GB of memory, and Docker is set to use a max of 4GB, so in docker_run_securify I changed:

securify_cmd="java -Xmx16G -jar /securify_jar/securify.jar -co"

to

securify_cmd="java -Xmx4G -jar /securify_jar/securify.jar -co"

Everything now seems to work properly. I could be missing something, but it seems Dockerfile and docker_run_securify should be updated with the above changes. Perhaps the max heap memory size can be optionally passed in as an input when running the container. I can submit a pull request with these changes if you'd like.

False positives for actions on a reverting branch

Consider the following example:

contract Wallet {

  uint balance;
  function send(){
    if (balance > 0){
      msg.sender.call.value(balance)();
      balance = 0;
    }
    revert();
  }
}

Securify reports violations for multiple patterns even though they cannot take place. In my intuition, the patterns (probably most securify patterns) are lacking something saying that this action, e.g. the storage write in case of the DAO pattern, may be followed by a STOP or RETURN.

Add souffle compilation to docker build phase

Currently for each contract being analyzed, a new souffle is compiled, which slows down the process a lot. This step should be done once as part of the docker image build process.

LockedEther is buggy

This triggers the pattern:

contract MarketPlace {

    function transfer() {
        uint x = msg.value;
    }
}

Docker image - couldn't give input path to run for.

Hello,

I get Securify from dockerhub.

When I type
docker run chainsecurity/securify, it works for project/example.sol.

However, when I run for these commands,
$ docker run -v $(pwd)/C:\Users\asus\Desktop\SomeSolFiles:/project securify
$ docker run -v $(pwd)/C:\Users\asus\Desktop\SomeSolFiles chainsecurity/securify
$ docker run -v $(pwd)/C://Users//asus//Desktop//SomeSolFiles chainsecurity/securify
$ docker run -v $(pwd)/c:\users\asus\desktop\somesolfiles chainsecurity/securify

I got repository must be lowercase error.

when I run for these commands,
$ docker run -v "$PWD"/c:\users\asus\desktop\somesolfiles chainsecurity/securify
invalid mount config for type "bind": invalid mount path: 'usersasusdesktopsomesolfiles' mount path must be absolute.

$ docker run -v "$PWD"/c:\users\asus\desktop\somesolfiles:/CallDepth chainsecurity/securify
C:\Program Files\Docker Toolbox\docker.exe: Error response from daemon: invalid mode: /CallDepth.

$ docker run -v "$PWD":/c:/users/asus/desktop/somesolfiles chainsecurity/securify
C:\Program Files\Docker Toolbox\docker.exe: Error response from daemon: invalid mode: /users/asus/desktop/somesolfiles.

To sum up, I could not run securify to scan my solidity file or folder.

Could you please help me what I kind of command I should type to run it ?

Thanks in advance.

Add end-to-end tests for popular projects

We should run tests against some popular open-source projects in end-to-end tests. I am suggesting to use the following projects, please evaluate and feel free to use other representative projects:

Known vulnerable contracts:
https://github.com/SmartContractSecurity/SWC-registry/tree/9e65c7066df7c08a997f3dc9aa735e5a04b13b51/test_cases

Kyber.Network:
https://github.com/KyberNetwork/smart-contracts/tree/bac2a299a92a248e6fc63b115056b07490667eb3

Paxos:
https://github.com/paxosglobal/pax-contracts/tree/9090650238e9576f1284764f132d72af9b0d267a

As running these tests will take considerable time and resources due to their size, they should be run manually before release.

Errors in TODTransfer Pattern

Reference:

Additional examples:

pragma solidity 0.4.24;

contract game {
  bool won = false;
  
  function play() public {
    if (!won) {
      won = true;
      msg.sender.transfer(1);
    }
  }

  function play2() public {
    require(!won);
    won = true;
    msg.sender.transfer(1);
  }
}

play and play2 have different analysis results with regards to TODTransfer.

pragma solidity 0.4.24;

contract game {
  bool won = false;

  function play() public {
    if (!won) {
      won = true;
      msg.sender.transfer(10 ** 18);
    } else {
      msg.sender.transfer(10 ** 18);
    }
    msg.sender.transfer(10 ** 18);
  }
}

The last transfer is also tagged as TODTransfer. It is unclear whether that is desirable or not.

Missed unhandled exception

pragma solidity ^0.4.24;

contract C{

  function f(){
    if(sha256(msg.data) < 2){
      msg.sender.send(3);
    }
  }
}

Vulnerabilities detected by Securify

I was researching on the various tools for Ethereum smart contract security and came across Securify. I read through in this document that Securify detects 18 critical vulnerabilities in Ethereum smart contracts. Can someone kindly consider my humble request for a list of all the 18 vulnerabilities?

Secondly, I would like to know how the vulnerability report presented in the below report can be obtained on Securify. Is it through the web application or can I obtain a similar report through the command prompt?

image

The above image is also available as Fig 2 in the document whose link has been shared.

Kindly assist me with this information.

NullPointerException in README's example

I think that the issue is the correlated to #19, but probably it is the same.

I have a NullPointerException when I run the example README's example:

java -jar build/libs/securify-0.1.jar -fh src/test/resources/solidity/transaction-reordering.bin.hex

[Ljava.lang.StackTraceElement;@32d2fa64
FAILURE
Exception in thread "main" java.lang.NullPointerException
at ch.securify.analysis.Dataflow.dispose(Dataflow.java:43)
at ch.securify.Main.checkPatterns(Main.java:416)
at ch.securify.Main.processHexFile(Main.java:151)
at ch.securify.Main.main(Main.java:201)

I am running securify on Linux and with Java:

openjdk version "1.8.0_172"
OpenJDK Runtime Environment (build 1.8.0_172-b11)
OpenJDK 64-Bit Server VM (build 25.172-b11, mixed mode)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.