Merge branch 'dev' into dev-fix-enum-max-min

pull/2051/head
Simone 1 year ago
commit 8b33694a81
  1. 2
      .github/workflows/docs.yml
  2. 7
      .github/workflows/linter.yml
  3. 32
      .github/workflows/matchers/pylint.json
  4. 22
      .github/workflows/matchers/yamllint.json
  5. 5
      .github/workflows/publish.yml
  6. 6
      .github/workflows/pylint.yml
  7. 4
      CONTRIBUTING.md
  8. 2
      slither/core/declarations/__init__.py
  9. 2
      slither/core/declarations/contract.py
  10. 4
      slither/core/declarations/custom_error_contract.py
  11. 4
      slither/core/declarations/custom_error_top_level.py
  12. 2
      slither/core/expressions/unary_operation.py
  13. 29
      slither/utils/output.py
  14. 55
      tests/unit/slithir/test_ternary_expressions.py

@ -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/'

@ -9,8 +9,6 @@ defaults:
on:
pull_request:
branches: [master, dev]
paths:
- "**/*.py"
schedule:
# run CI every day even if no PRs/merges occur
@ -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()
@ -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

@ -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
}
]
}
]
}

@ -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
}
]
}
]
}

@ -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

@ -9,6 +9,8 @@ defaults:
on:
pull_request:
branches: [master, dev]
paths:
- "**/*.py"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@ -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()

@ -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.

@ -18,3 +18,5 @@ from .structure_top_level import StructureTopLevel
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

@ -861,7 +861,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
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"]:
"""

@ -16,3 +16,7 @@ class CustomErrorContract(CustomError, ContractLevel):
:return:
"""
return self.contract == contract
@property
def canonical_name(self) -> str:
return self.contract.name + "." + self.full_name

@ -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

@ -106,8 +106,6 @@ class UnaryOperation(Expression):
UnaryOperationType.MINUSMINUS_PRE,
UnaryOperationType.PLUSPLUS_POST,
UnaryOperationType.MINUSMINUS_POST,
UnaryOperationType.PLUS_PRE,
UnaryOperationType.MINUS_PRE,
]:
expression.set_lvalue()

@ -18,6 +18,7 @@ from slither.core.declarations import (
Structure,
Pragma,
FunctionContract,
CustomError,
)
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.local_variable import LocalVariable
@ -438,6 +439,8 @@ class Output:
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):
@ -585,6 +588,32 @@ class Output:
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
###################################################################################
###################################################################################

@ -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"
@ -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

Loading…
Cancel
Save