Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Must depend on Analysis #2502

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft

Must depend on Analysis #2502

wants to merge 2 commits into from

Conversation

priyankabose
Copy link

@priyankabose priyankabose commented Jul 3, 2024

This implements #175 .

Linter and reformatter ran locally.

Brief analysis description:

  1. Given a target variable, infer its dependencies within the function
  2. Then for each such dependencies, take the intersection of the original variables that resulted in those dependencies
  3. Stop when we find public/external function parameters, constants, and solidity variable as origin variables

Summary by CodeRabbit

  • New Features

    • Introduced functionality to determine and compute must dependencies for variables in smart contracts.
  • Tests

    • Added tests to validate the new must dependency features, ensuring correct behavior and reliability.

@priyankabose priyankabose requested a review from montyly as a code owner July 3, 2024 18:29
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link

coderabbitai bot commented Jul 3, 2024

Walkthrough

Walkthrough

The recent changes introduce mechanisms to determine and compute "must dependencies" for variables within the data_dependency module of the slither analysis framework. This includes new functions for dependency analysis and corresponding tests. Additionally, a Solidity contract and an interface were added to test these dependencies through specific smart contract conditions.

Changes

File(s) Summary
slither/analyses/data_dependency/data_dependency.py Added functions get_must_depends_on(variable) and compute_must_dependencies(v) to analyze must dependencies for variables.
tests/unit/core/test_data/must_depend_on.sol Introduced Solidity contract Unsafe with a bug in token transfers to test must dependency functionality. Added IERC20 interface.
tests/unit/core/test_must_depend_on.py Added test test_must_depend_on_returns to validate the behavior of get_must_depends_on function. Imported relevant declarations for testing.

Sequence Diagram(s)

sequenceDiagram
    participant Tester
    participant Slither
    participant DataDependencyModule
    participant MustDependOnFunction
    participant SolidityContract

    Tester->>Slither: Initialize Slither object
    Slither->>DataDependencyModule: Request must dependencies
    DataDependencyModule->>MustDependOnFunction: Call get_must_depends_on(variable)
    MustDependOnFunction->>SolidityContract: Analyze smart contract for dependencies
    SolidityContract->>MustDependOnFunction: Return analyzed dependencies
    MustDependOnFunction->>DataDependencyModule: Return must dependencies
    DataDependencyModule->>Slither: Provide must dependencies
    Slither->>Tester: Return results of must dependency analysis
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 7c7b71f and a159d60.

Files selected for processing (1)
  • slither/analyses/data_dependency/data_dependency.py (1 hunks)
Additional context used
Ruff
slither/analyses/data_dependency/data_dependency.py

328-328: Test for membership should be not in

Convert to not in

(E713)

GitHub Check: Lint Code Base
slither/analyses/data_dependency/data_dependency.py

[warning] 303-303:
R0912: Too many branches (16/12) (too-many-branches)

slither/analyses/data_dependency/data_dependency.py Outdated Show resolved Hide resolved
slither/analyses/data_dependency/data_dependency.py Outdated Show resolved Hide resolved
lvalue = lvalue_details[0]
ir = lvalue_details[2]

if not lvalue in function_dependencies["context"]:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix membership test.

Convert the membership test to not in for better readability.

- if not lvalue in function_dependencies["context"]:
+ if lvalue not in function_dependencies["context"]:
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if not lvalue in function_dependencies["context"]:
if lvalue not in function_dependencies["context"]:
Tools
Ruff

328-328: Test for membership should be not in

Convert to not in

(E713)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Outside diff range and nitpick comments (1)
tests/unit/core/test_must_depend_on.py (1)

14-14: Add a final newline.

A final newline is missing at the end of the file.

- assert isinstance(result, list) and len(result) <= 1
+ assert isinstance(result, list) and len(result) <= 1
+
Tools
GitHub Check: Lint Code Base

[warning] 14-14:
C0304: Final newline missing (missing-final-newline)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between a159d60 and 4710753.

Files selected for processing (3)
  • slither/analyses/data_dependency/data_dependency.py (1 hunks)
  • tests/unit/core/test_data/must_depend_on.sol (1 hunks)
  • tests/unit/core/test_must_depend_on.py (1 hunks)
Additional context used
GitHub Check: Lint Code Base
tests/unit/core/test_must_depend_on.py

[warning] 14-14:
C0304: Final newline missing (missing-final-newline)

slither/analyses/data_dependency/data_dependency.py

[warning] 308-308:
R0912: Too many branches (16/12) (too-many-branches)

Ruff
slither/analyses/data_dependency/data_dependency.py

333-333: Test for membership should be not in

Convert to not in

(E713)

Additional comments not posted (8)
tests/unit/core/test_must_depend_on.py (3)

1-5: Imports look good.

The imported modules and functions are necessary for the test function.


7-7: Constant definition looks good.

The constant TEST_DATA_DIR is correctly defined to locate the test data directory.


9-14: Test function looks good.

The function test_must_depend_on_returns correctly sets up a Slither object, retrieves function parameters, and asserts the results of get_must_depends_on.

Tools
GitHub Check: Lint Code Base

[warning] 14-14:
C0304: Final newline missing (missing-final-newline)

tests/unit/core/test_data/must_depend_on.sol (5)

1-1: Pragma statement looks good.

The pragma statement correctly specifies the Solidity version ^0.8.19.


3-5: Interface definition looks good.

The interface IERC20 correctly defines the transferFrom function.


16-19: Function good2 looks good.

The function good2 correctly calls int_transferFrom with a constant from address.


22-24: Function bad2 looks good.

The function bad2 correctly demonstrates a missing return value bug by calling int_transferFrom with a non-constant from address.


26-28: Function int_transferFrom looks good.

The function int_transferFrom correctly calls transferFrom on the erc20 interface.

Comment on lines 296 to 307
def get_must_depends_on(variable: SUPPORTED_TYPES) -> SUPPORTED_TYPES | None:
"""
Return must dependency of a variable if exist otherwise return None.

:param variable: target variable whose must dependency needs to be computed
:return: Variable | None
"""
must_dependencies = compute_must_dependencies(variable)
if len(must_dependencies) > 1 or len(must_dependencies) == 0:
return []
return [list(must_dependencies)[0]]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add type annotations and docstring.

The function lacks type annotations and a docstring. Adding these will improve readability and maintainability.

def get_must_depends_on(variable: SUPPORTED_TYPES) -> List[SUPPORTED_TYPES]:
    """
    Compute the must dependencies for a given variable.

    Args:
        variable (SUPPORTED_TYPES): The target variable.

    Returns:
        List[SUPPORTED_TYPES]: The must dependency if it exists, otherwise an empty list.
    """
    must_dependencies = compute_must_dependencies(variable)
    if len(must_dependencies) > 1 or len(must_dependencies) == 0:
        return []
    return [list(must_dependencies)[0]]

slither/analyses/data_dependency/data_dependency.py Outdated Show resolved Hide resolved
)
for i, data_dependency in enumerate(data_dependencies):
result = compute_must_dependencies(data_dependency)
if i > 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this condition as it seems it will always take the intersection. Could you clarify why this is done?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i here is the index for the element data_dependency, for the first data_dependency element, my idea was to put its must dependency into the result , next onwards I try to see whether must dependency is the same or not. that is why for i>0 i do intersection, but for i=0 i do union

Comment on lines +349 to +354
data_dependencies = (
list(function_dependencies["context"][v])
if function_dependencies["context"] is not None
else []
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
data_dependencies = (
list(function_dependencies["context"][v])
if function_dependencies["context"] is not None
else []
)
data_dependencies = list(function_dependencies["context"].get(v, set()))

This could probably be a defaultdict with an empty set as the default to avoid this

slither/analyses/data_dependency/data_dependency.py Outdated Show resolved Hide resolved
@@ -293,6 +293,72 @@ def get_all_dependencies_ssa(
return context.context[KEY_SSA]


def get_must_depends_on(variable: SUPPORTED_TYPES) -> SUPPORTED_TYPES | None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def get_must_depends_on(variable: SUPPORTED_TYPES) -> SUPPORTED_TYPES | None:
def get_must_depends_on(variable: SUPPORTED_TYPES) -> SUPPORTED_TYPES | None:

The return type doesn't agree with what is actually returned (a list). Since we always return 1 item, maybe it should be Union[SUPPORTED_TYPES, None] (using Union since | limits which python versions can be used

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Outside diff range and nitpick comments (1)
tests/unit/core/test_must_depend_on.py (1)

14-14: Use TypeAlias for type aliasing.

For better readability and maintainability, use TypeAlias when defining type aliases.

- SUPPORTED_TYPES = Union[Variable, SolidityVariable, Constant]
+ SUPPORTED_TYPES: TypeAlias = Union[Variable, SolidityVariable, Constant]
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 4710753 and 24a022f.

Files selected for processing (2)
  • slither/analyses/data_dependency/data_dependency.py (1 hunks)
  • tests/unit/core/test_must_depend_on.py (1 hunks)
Additional context used
GitHub Check: Lint Code Base
tests/unit/core/test_must_depend_on.py

[warning] 23-23:
C0304: Final newline missing (missing-final-newline)


[warning] 8-8:
C0411: standard import "from typing import Union" should be placed before "from slither import Slither" (wrong-import-order)

slither/analyses/data_dependency/data_dependency.py

[warning] 309-309:
R0912: Too many branches (16/12) (too-many-branches)

Ruff
slither/analyses/data_dependency/data_dependency.py

334-334: Test for membership should be not in

Convert to not in

(E713)

tests/unit/core/test_must_depend_on.py Outdated Show resolved Hide resolved
tests/unit/core/test_must_depend_on.py Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Outside diff range, codebase verification and nitpick comments (1)
tests/unit/core/test_must_depend_on.py (1)

15-30: Add more assertions to cover edge cases.

The test function should include more assertions to cover edge cases, such as when the result contains multiple dependencies.

def test_must_depend_on_returns(solc_binary_path):
    solc_path = solc_binary_path("0.8.19")
    file = Path(TEST_DATA_DIR, "must_depend_on.sol").as_posix()
    slither_obj = Slither(file, solc=solc_path)
    result = get_must_depends_on(slither_obj.contracts[1].functions[2].parameters[0])
    assert isinstance(result, list)
    assert len(result) == 0 or (len(result) == 1 and result[0] in SUPPORTED_TYPES)
+   # Add more assertions for edge cases
+   assert all(isinstance(dep, SUPPORTED_TYPES) for dep in result)
+   assert len(result) <= 1
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 24a022f and 52416ba.

Files selected for processing (3)
  • slither/analyses/data_dependency/data_dependency.py (1 hunks)
  • tests/unit/core/test_data/must_depend_on.sol (1 hunks)
  • tests/unit/core/test_must_depend_on.py (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • tests/unit/core/test_data/must_depend_on.sol
Additional context used
GitHub Check: Lint Code Base
tests/unit/core/test_must_depend_on.py

[warning] 6-6:
C0411: standard import "from typing import Union" should be placed before "from slither import Slither" (wrong-import-order)

slither/analyses/data_dependency/data_dependency.py

[warning] 309-309:
R0912: Too many branches (16/12) (too-many-branches)

Ruff
slither/analyses/data_dependency/data_dependency.py

334-334: Test for membership should be not in

Convert to not in

(E713)

tests/unit/core/test_must_depend_on.py Show resolved Hide resolved
slither/analyses/data_dependency/data_dependency.py Outdated Show resolved Hide resolved
@0xalpharush 0xalpharush marked this pull request as draft August 23, 2024 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants