Skip to content

Commit

Permalink
Merge branch 'dev' into fix-shadowed-before-shadowing-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiko7454 authored Aug 21, 2023
2 parents 20007c4 + 0de7a25 commit 5cabcb3
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- run: pip install -e ".[doc]"
- run: pdoc -o html/ slither '!slither.tools' #TODO fix import errors on pdoc run
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v2
with:
# Upload the doc
path: './html/'
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ defaults:
on:
pull_request:
branches: [master, dev]
paths:
- "**/*.py"

schedule:
# run CI every day even if no PRs/merges occur
Expand Down Expand Up @@ -42,6 +40,10 @@ jobs:
mkdir -p .github/linters
cp pyproject.toml .github/linters
- name: Register yamllint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/yamllint.json"
- name: Lint everything else
uses: super-linter/super-linter/slim@v4.9.2
if: always()
Expand All @@ -55,7 +57,6 @@ jobs:
VALIDATE_PYTHON_PYLINT: false
VALIDATE_PYTHON_BLACK: false
VALIDATE_PYTHON_ISORT: false
# Always false
VALIDATE_JSON: false
VALIDATE_JAVASCRIPT_STANDARD: false
VALIDATE_PYTHON_FLAKE8: false
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/matchers/pylint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"problemMatcher": [
{
"owner": "pylint-error",
"severity": "error",
"pattern": [
{
"regexp": "^(.+):(\\d+):(\\d+):\\s(([EF]\\d{4}):\\s.+)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
},
{
"owner": "pylint-warning",
"severity": "warning",
"pattern": [
{
"regexp": "^(.+):(\\d+):(\\d+):\\s(([CRW]\\d{4}):\\s.+)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}
22 changes: 22 additions & 0 deletions .github/workflows/matchers/yamllint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"problemMatcher": [
{
"owner": "yamllint",
"pattern": [
{
"regexp": "^(.*\\.ya?ml)$",
"file": 1
},
{
"regexp": "^\\s{2}(\\d+):(\\d+)\\s+(error|warning)\\s+(.*?)\\s+\\((.*)\\)$",
"line": 1,
"column": 2,
"severity": 3,
"message": 4,
"code": 5,
"loop": true
}
]
}
]
}
5 changes: 2 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ jobs:
path: dist/

- name: publish
uses: pypa/gh-action-pypi-publish@v1.8.7
uses: pypa/gh-action-pypi-publish@v1.8.10

- name: sign
uses: sigstore/gh-action-sigstore-python@v1.2.3
uses: sigstore/gh-action-sigstore-python@v2.0.1
with:
inputs: ./dist/*.tar.gz ./dist/*.whl
release-signing-artifacts: true
bundle-only: true
6 changes: 6 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ defaults:
on:
pull_request:
branches: [master, dev]
paths:
- "**/*.py"

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -36,6 +38,10 @@ jobs:
mkdir -p .github/linters
cp pyproject.toml .github/linters
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
- name: Pylint
uses: super-linter/super-linter/slim@v4.9.2
if: always()
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ For each new detector, at least one regression tests must be present.
#### Adding parsing tests

1. Create a test in `tests/e2e/solc_parsing/`
2. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git.
3. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py`.
2. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py`.
3. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git.
4. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/e2e/solc_parsing/expected_json`. Add the generated files to git.
5. Run `pytest tests/e2e/solc_parsing/test_ast_parsing.py` and check that everything worked.

Expand Down
2 changes: 2 additions & 0 deletions slither/core/declarations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
from .function_contract import FunctionContract
from .function_top_level import FunctionTopLevel
from .custom_error_contract import CustomErrorContract
from .custom_error_top_level import CustomErrorTopLevel
from .custom_error import CustomError
2 changes: 1 addition & 1 deletion slither/core/declarations/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ def get_state_variable_from_canonical_name(
Returns:
StateVariable
"""
return next((v for v in self.state_variables if v.name == canonical_name), None)
return next((v for v in self.state_variables if v.canonical_name == canonical_name), None)

def get_structure_from_name(self, structure_name: str) -> Optional["StructureContract"]:
"""
Expand Down
4 changes: 4 additions & 0 deletions slither/core/declarations/custom_error_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ def is_declared_by(self, contract: "Contract") -> bool:
:return:
"""
return self.contract == contract

@property
def canonical_name(self) -> str:
return self.contract.name + "." + self.full_name
4 changes: 4 additions & 0 deletions slither/core/declarations/custom_error_top_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ class CustomErrorTopLevel(CustomError, TopLevel):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None:
super().__init__(compilation_unit)
self.file_scope: "FileScope" = scope

@property
def canonical_name(self) -> str:
return self.full_name
2 changes: 0 additions & 2 deletions slither/core/expressions/unary_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ def __init__(
UnaryOperationType.MINUSMINUS_PRE,
UnaryOperationType.PLUSPLUS_POST,
UnaryOperationType.MINUSMINUS_POST,
UnaryOperationType.PLUS_PRE,
UnaryOperationType.MINUS_PRE,
]:
expression.set_lvalue()

Expand Down
29 changes: 29 additions & 0 deletions slither/utils/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Structure,
Pragma,
FunctionContract,
CustomError,
)
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.local_variable import LocalVariable
Expand Down Expand Up @@ -438,6 +439,8 @@ def add(self, add: SupportedOutput, additional_fields: Optional[Dict] = None) ->
self.add_event(add, additional_fields=additional_fields)
elif isinstance(add, Structure):
self.add_struct(add, additional_fields=additional_fields)
elif isinstance(add, CustomError):
self.add_custom_error(add, additional_fields=additional_fields)
elif isinstance(add, Pragma):
self.add_pragma(add, additional_fields=additional_fields)
elif isinstance(add, Node):
Expand Down Expand Up @@ -585,6 +588,32 @@ def add_event(self, event: Event, additional_fields: Optional[Dict] = None) -> N

self._data["elements"].append(element)

# endregion
###################################################################################
###################################################################################
# region CustomError
###################################################################################
###################################################################################

def add_custom_error(
self, custom_error: CustomError, additional_fields: Optional[Dict] = None
) -> None:
if additional_fields is None:
additional_fields = {}
type_specific_fields = {
"parent": _create_parent_element(custom_error),
"signature": custom_error.full_name,
}
element = _create_base_element(
"custom_error",
custom_error.name,
custom_error.source_mapping.to_json(),
type_specific_fields,
additional_fields,
)

self._data["elements"].append(element)

# endregion
###################################################################################
###################################################################################
Expand Down
55 changes: 31 additions & 24 deletions tests/unit/slithir/test_ternary_expressions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from pathlib import Path
from slither import Slither
from slither.core.cfg.node import NodeType
from slither.slithir.operations import Assignment
from slither.core.expressions import AssignmentOperation, TupleExpression
from slither.slithir.operations import Assignment, Unpack
from slither.core.expressions import (
AssignmentOperation,
TupleExpression,
NewElementaryType,
CallExpression,
)


TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
Expand All @@ -12,27 +17,29 @@ def test_ternary_conversions(solc_binary_path) -> None:
solc_path = solc_binary_path("0.8.0")
slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path)
for contract in slither.contracts:
for function in contract.functions:
vars_declared = 0
vars_assigned = 0
for node in function.nodes:
if node.type in [NodeType.IF, NodeType.IFLOOP]:
if not contract.is_signature_only:
for function in contract.functions:
vars_declared = 0
vars_assigned = 0
for node in function.nodes:
if node.type in [NodeType.IF, NodeType.IFLOOP]:

# Iterate over true and false son
for inner_node in node.sons:
# Count all variables declared
expression = inner_node.expression
if isinstance(expression, AssignmentOperation):
var_expr = expression.expression_left
# Only tuples declare more than one var
if isinstance(var_expr, TupleExpression):
vars_declared += len(var_expr.expressions)
else:
vars_declared += 1
# Iterate over true and false son
for inner_node in node.sons:
# Count all variables declared
expression = inner_node.expression
if isinstance(
expression, (AssignmentOperation, NewElementaryType, CallExpression)
):
var_expr = expression.expression_left
# Only tuples declare more than one var
if isinstance(var_expr, TupleExpression):
vars_declared += len(var_expr.expressions)
else:
vars_declared += 1

for ir in inner_node.irs:
# Count all variables defined
if isinstance(ir, Assignment):
vars_assigned += 1

assert vars_declared == vars_assigned
for ir in inner_node.irs:
# Count all variables defined
if isinstance(ir, (Assignment, Unpack)):
vars_assigned += 1
assert vars_declared == vars_assigned and vars_assigned != 0

0 comments on commit 5cabcb3

Please sign in to comment.