Merge branch 'master' into HEAD

pull/1625/head
Feist Josselin 2 years ago
commit ef2b707675
  1. 46
      .github/workflows/docs.yml
  2. 2
      .github/workflows/linter.yml
  3. 3
      .gitignore
  4. 93
      README.md
  5. 7
      scripts/ci_test_etherscan.sh
  6. 5
      setup.py
  7. 4
      slither/detectors/variables/uninitialized_storage_variables.py
  8. 8
      slither/utils/type_helpers.py
  9. 17
      tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol
  10. 90
      tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol.0.8.19.UninitializedStorageVars.json
  11. 5
      tests/test_detectors.py

@ -0,0 +1,46 @@
name: docs
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
build:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v3
- uses: actions/setup-python@v4
with:
python-version: '3.8'
- run: pip install -e ".[dev]"
- run: pdoc -o docs/ slither '!slither.tools' #TODO fix import errors on pdoc run
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload the doc
path: 'docs/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

@ -64,5 +64,7 @@ jobs:
VALIDATE_EDITORCONFIG: false VALIDATE_EDITORCONFIG: false
VALIDATE_JSCPD: false VALIDATE_JSCPD: false
VALIDATE_PYTHON_MYPY: false VALIDATE_PYTHON_MYPY: false
# Until we upgrade the super linter for actionlintÒ
VALIDATE_GITHUB_ACTIONS: false
SHELLCHECK_OPTS: "-e SC1090" SHELLCHECK_OPTS: "-e SC1090"
FILTER_REGEX_EXCLUDE: .*tests/.*.(json|zip|sol) FILTER_REGEX_EXCLUDE: .*tests/.*.(json|zip|sol)

3
.gitignore vendored

@ -111,3 +111,6 @@ test_artifacts/
# crytic export # crytic export
crytic-export/ crytic-export/
# Auto-generated Github pages docs
docs/

@ -5,13 +5,15 @@
[![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com) [![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com)
[![PyPI version](https://badge.fury.io/py/slither-analyzer.svg)](https://badge.fury.io/py/slither-analyzer) [![PyPI version](https://badge.fury.io/py/slither-analyzer.svg)](https://badge.fury.io/py/slither-analyzer)
Slither is a Solidity static analysis framework written in Python 3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. Slither is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.
- [Features](#features) - [Features](#features)
- [Bugs and Optimizations Detection](#bugs-and-optimizations-detection) - [Usage](#usage)
- [How to Install](#how-to-install)
- [Detectors](#detectors)
- [Printers](#printers) - [Printers](#printers)
- [Tools](#tools) - [Tools](#tools)
- [How to Install](#how-to-install) - [API Documentation](#api-documentation)
- [Getting Help](#getting-help) - [Getting Help](#getting-help)
- [FAQ](#faq) - [FAQ](#faq)
- [Publications](#publications) - [Publications](#publications)
@ -20,35 +22,68 @@ Slither is a Solidity static analysis framework written in Python 3. It runs a s
* Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md)) * Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md))
* Identifies where the error condition occurs in the source code * Identifies where the error condition occurs in the source code
* Easily integrates into continuous integration and Truffle builds * Easily integrates into continuous integration and Hardhat/Foundry builds
* Built-in 'printers' quickly report crucial contract information * Built-in 'printers' quickly report crucial contract information
* Detector API to write custom analyses in Python * Detector API to write custom analyses in Python
* Ability to analyze contracts written with Solidity >= 0.4 * Ability to analyze contracts written with Solidity >= 0.4
* Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses * Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses
* Correctly parses 99.9% of all public Solidity code * Correctly parses 99.9% of all public Solidity code
* Average execution time of less than 1 second per contract * Average execution time of less than 1 second per contract
* Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action)
## Usage
## Bugs and Optimizations Detection Run Slither on a Hardhat/Foundry/Dapp/Brownie application:
Run Slither on a Truffle/Embark/Dapp/Etherlime/Hardhat application:
```bash ```bash
slither . slither .
``` ```
This is the preferred option if your project has dependencies as Slither relies on the underlying compilation framework to compile source code.
Run Slither on a single file: However, you can run Slither on a single file that does not import dependencies:
```bash ```bash
slither tests/uninitialized.sol slither tests/uninitialized.sol
``` ```
## How to install
Slither requires Python 3.8+.
If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile), you need [solc](https://github.com/ethereum/solidity/), the Solidity compiler; we recommend using [solc-select](https://github.com/crytic/solc-select) to conveniently switch between solc versions.
### Using Pip
```bash
pip3 install slither-analyzer
```
### Using Git
```bash
git clone https://github.com/crytic/slither.git && cd slither
python3 setup.py install
```
We recommend using a Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git.
### Using Docker
Use the [`eth-security-toolbox`](https://github.com/trailofbits/eth-security-toolbox/) docker image. It includes all of our security tools and every major version of Solidity in a single image. `/home/share` will be mounted to `/share` in the container.
```bash
docker pull trailofbits/eth-security-toolbox
```
To share a directory in the container:
```bash
docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
```
### Integration ### Integration
- For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action). - For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action).
- To generate a Markdown report, use `slither [target] --checklist`. - To generate a Markdown report, use `slither [target] --checklist`.
- To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`) - To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`)
Use [solc-select](https://github.com/crytic/solc-select) if your contracts require older versions of solc. For additional configuration, see the [usage](https://github.com/trailofbits/slither/wiki/Usage) documentation. ## Detectors
### Detectors
Num | Detector | What it Detects | Impact | Confidence Num | Detector | What it Detects | Impact | Confidence
@ -173,40 +208,8 @@ See the [Tool documentation](https://github.com/crytic/slither/wiki/Tool-Documen
[Contact us](https://www.trailofbits.com/contact/) to get help on building custom tools. [Contact us](https://www.trailofbits.com/contact/) to get help on building custom tools.
## How to install ## API Documentation
Documentation on Slither's internals is available [here](https://crytic.github.io/slither/slither.html).
Slither requires Python 3.8+.
If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile),
you need to have on your machine the right version of [solc](https://github.com/ethereum/solidity/), the Solidity compiler.
### Using Pip
```bash
pip3 install slither-analyzer
```
### Using Git
```bash
git clone https://github.com/crytic/slither.git && cd slither
python3 setup.py install
```
We recommend using a Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git.
### Using Docker
Use the [`eth-security-toolbox`](https://github.com/trailofbits/eth-security-toolbox/) docker image. It includes all of our security tools and every major version of Solidity in a single image. `/home/share` will be mounted to `/share` in the container.
```bash
docker pull trailofbits/eth-security-toolbox
```
To share a directory in the container:
```bash
docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
```
## Getting Help ## Getting Help

@ -17,12 +17,5 @@ if [ "$GITHUB_ETHERSCAN" = "" ]; then
sleep $(( ( RANDOM % 5 ) + 1 ))s sleep $(( ( RANDOM % 5 ) + 1 ))s
fi fi
echo "::group::Etherscan rinkeby"
if ! slither rinkeby:0xFe05820C5A92D9bc906D4A46F662dbeba794d3b7 --etherscan-apikey "$GITHUB_ETHERSCAN" --no-fail-pedantic; then
echo "Etherscan rinkeby test failed"
exit 1
fi
echo "::endgroup::"
exit 0 exit 0

@ -15,8 +15,8 @@ setup(
"packaging", "packaging",
"prettytable>=0.7.2", "prettytable>=0.7.2",
"pycryptodome>=3.4.6", "pycryptodome>=3.4.6",
"crytic-compile>=0.3.0", # "crytic-compile>=0.3.0",
# "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile",
], ],
extras_require={ extras_require={
"dev": [ "dev": [
@ -29,6 +29,7 @@ setup(
"numpy", "numpy",
"solc-select>=v1.0.0b1", "solc-select>=v1.0.0b1",
"openai", "openai",
"pdoc",
] ]
}, },
license="AGPL-3.0", license="AGPL-3.0",

@ -103,9 +103,11 @@ Bob calls `func`. As a result, `owner` is overridden to `0`.
for contract in self.compilation_unit.contracts: for contract in self.compilation_unit.contracts:
for function in contract.functions: for function in contract.functions:
if function.is_implemented and function.entry_point: if function.is_implemented and function.entry_point:
locals_except_params = set(function.variables) - set(function.parameters)
uninitialized_storage_variables = [ uninitialized_storage_variables = [
v for v in function.local_variables if v.is_storage and v.uninitialized v for v in locals_except_params if v.is_storage and v.uninitialized
] ]
function.entry_point.context[self.key] = uninitialized_storage_variables function.entry_point.context[self.key] = uninitialized_storage_variables
self._detect_uninitialized(function, function.entry_point, []) self._detect_uninitialized(function, function.entry_point, [])

@ -11,7 +11,7 @@ if TYPE_CHECKING:
### core.declaration ### core.declaration
# pylint: disable=used-before-assignment # pylint: disable=used-before-assignment
InternalCallType = Union[Function, SolidityFunction] InternalCallType = Union["Function", "SolidityFunction"]
HighLevelCallType = Tuple[Contract, Union[Function, Variable]] HighLevelCallType = Tuple["Contract", Union["Function", "Variable"]]
LibraryCallType = Tuple[Contract, Function] LibraryCallType = Tuple["Contract", "Function"]
LowLevelCallType = Tuple[Union[Variable, SolidityVariable], str] LowLevelCallType = Tuple[Union["Variable", "SolidityVariable"], str]

@ -0,0 +1,17 @@
contract Uninitialized{
struct St{
uint a;
}
function bad() internal returns (St storage ret){
ret = ret;
ret.a += 1;
}
function ok(St storage ret) internal {
ret = ret;
ret.a += 1;
}
}

@ -0,0 +1,90 @@
[
[
{
"elements": [
{
"type": "variable",
"name": "ret",
"source_mapping": {
"start": 100,
"length": 14,
"filename_relative": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"is_dependency": false,
"lines": [
7
],
"starting_column": 38,
"ending_column": 52
},
"type_specific_fields": {
"parent": {
"type": "function",
"name": "bad",
"source_mapping": {
"start": 67,
"length": 95,
"filename_relative": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"is_dependency": false,
"lines": [
7,
8,
9,
10
],
"starting_column": 5,
"ending_column": 6
},
"type_specific_fields": {
"parent": {
"type": "contract",
"name": "Uninitialized",
"source_mapping": {
"start": 0,
"length": 262,
"filename_relative": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"filename_absolute": "/GENERIC_PATH",
"filename_short": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol",
"is_dependency": false,
"lines": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17
],
"starting_column": 1,
"ending_column": 2
}
},
"signature": "bad()"
}
}
}
}
],
"description": "Uninitialized.bad().ret (tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol#7) is a storage variable never initialized\n",
"markdown": "[Uninitialized.bad().ret](tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol#L7) is a storage variable never initialized\n",
"first_markdown_element": "tests/detectors/uninitialized-storage/0.8.19/uninitialized_storage_pointer.sol#L7",
"id": "979d28e501693ed7ece0d429e7c30266f8e9d6a2e2eedc87006c4bad63e78706",
"check": "uninitialized-storage",
"impact": "High",
"confidence": "High"
}
]
]

@ -371,6 +371,11 @@ ALL_TEST_OBJECTS = [
"uninitialized_storage_pointer.sol", "uninitialized_storage_pointer.sol",
"0.4.25", "0.4.25",
), ),
Test(
all_detectors.UninitializedStorageVars,
"uninitialized_storage_pointer.sol",
"0.8.19",
),
Test(all_detectors.TxOrigin, "tx_origin.sol", "0.4.25"), Test(all_detectors.TxOrigin, "tx_origin.sol", "0.4.25"),
Test(all_detectors.TxOrigin, "tx_origin.sol", "0.5.16"), Test(all_detectors.TxOrigin, "tx_origin.sol", "0.5.16"),
Test(all_detectors.TxOrigin, "tx_origin.sol", "0.6.11"), Test(all_detectors.TxOrigin, "tx_origin.sol", "0.6.11"),

Loading…
Cancel
Save