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

Implement ebpf_check_constraints_at_label #729

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Alan-Jowett
Copy link
Contributor

@Alan-Jowett Alan-Jowett commented Oct 14, 2024

Resolves: #728

This pull request exposes a new API "ebpf_check_constraints_at_label" which permits the caller to compare a set of constraints against the model at a specific label. If the model and the constraints differ it will return the two sets of constraints.

Enhancements and New Features:

Test Case Updates:

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new constructor for label parsing capabilities in label_t.
    • Added a boolean option store_pre_invariants for managing pre-invariant states during verification.
    • Implemented functions to check constraints and retrieve invariants associated with specific labels.
    • Added a new function for parsing linear constraints from strings.
    • Enhanced the testing framework to validate invariants during test execution.
  • Bug Fixes

    • Improved error handling for invalid label formats and numeric overflow in new functions.
  • Tests

    • Added new test cases to validate concrete state and invariants.
  • Documentation

    • Updated documentation for new functions, detailing parameters and return types.

Copy link

coderabbitai bot commented Oct 14, 2024

Walkthrough

The changes in this pull request introduce new functionalities and enhancements related to the handling of invariants and label parsing within the codebase. A new constructor for the label_t struct is added to facilitate parsing of label strings, while the ebpf_verifier_options_t structure is updated to include a member for storing pre-invariants. Several functions are introduced to manage and validate these pre-invariants during the verification process. Additionally, new test cases are added to validate the expected behavior of these changes.

Changes

File Change Summary
src/asm_syntax.hpp Added constructor explicit label_t(std::string_view string_label) in label_t struct.
src/config.hpp Added boolean member store_pre_invariants to ebpf_verifier_options_t.
src/crab_verifier.cpp Added saved_pre_invariants variable, save_invariants_if_needed, ebpf_check_constraints_at_label, and ebpf_get_invariants_at_label functions. Updated existing functions to utilize new logic.
src/crab_verifier.hpp Declared ebpf_check_constraints_at_label and ebpf_get_invariants_at_label functions.
test-data/add.yaml Introduced two new test cases: "check concrete state" and "check concrete state - negative."
src/asm_parse.hpp Added parse_linear_constraints function and include directives for new dependencies.
src/test/ebpf_yaml.cpp Updated RawTestCase structure to include invariants_to_check. Enhanced several functions to handle invariants.
src/test/ebpf_yaml.hpp Added invariants_to_check member to TestCase struct.

Assessment against linked issues

Objective Addressed Explanation
Expose API to compare abstract state to concrete state (728)
Ensure proper validation of pre-invariants against expected values (728)
Implement error handling for invalid label formats (728)

Possibly related PRs

Suggested reviewers

  • elazarg
  • dthaler

🐰 In the code where I hop and play,
New constructors brighten the day!
With invariants checked and states aligned,
In this pull request, joy we find!
So let’s parse those labels, clear and bright,
In the land of code, all feels just right! 🌟


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between e3efb4b and e92408c.

📒 Files selected for processing (2)
  • src/asm_parse.cpp (4 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (2)
src/asm_parse.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.cpp:234-236
Timestamp: 2024-11-09T03:30:33.391Z
Learning: In `src/asm_parse.cpp`, the constraint parser can handle leading and trailing whitespaces in constraints, so trimming is unnecessary.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (6)
test-data/add.yaml (3)

180-183: LGTM: Well-structured test case initialization.

The test case follows the established pattern with clear initialization of registers to zero.


184-193: LGTM: Comprehensive step-by-step verification.

Each operation is followed by appropriate requirements checking both type safety and value correctness, which aligns well with the PR objective of checking constraints at specific labels.


205-232: LGTM: Well-designed negative test case.

The test case effectively validates the constraint checking functionality by:

  1. Using an incorrect value (2 instead of 3) to trigger verification failure
  2. Following the verifier's error message format
  3. Including clear documentation of the test's purpose
src/asm_parse.cpp (3)

57-58: LGTM: Well-designed regex pattern for parsing require statements.

The regex pattern is well-structured with non-greedy matching and proper whitespace handling.


263-269: 🛠️ Refactor suggestion

Enhance error handling for unexpected variant types.

When convert_to_original fails, the code silently falls through to Undefined{0}. Consider logging or throwing an exception for unexpected variant types to aid in debugging.

 auto ins_or_constraints = parse_instruction(line, {});

 if (std::holds_alternative<ConstraintsSet>(ins_or_constraints)) {
     continue;
 }

+if (!std::holds_alternative<Instruction>(ins_or_constraints)) {
+    throw std::runtime_error("Unexpected variant type in parse_program");
+}
 Instruction ins = convert_to_original<Instruction>(ins_or_constraints).value_or(Undefined{0});

Likely invalid or redundant comment.


228-237: 🧹 Nitpick (assertive)

Consider adding early validation of constraint syntax.

While the constraint parsing works correctly, consider validating each constraint's syntax before insertion into the set. This would provide earlier feedback for malformed constraints rather than deferring validation to parse_linear_constraints.

 for (; first != last; ++first) {
+    std::string constraint = *first;
+    if (!is_valid_constraint(constraint)) {
+        throw std::runtime_error("Invalid constraint syntax: " + constraint);
+    }
     constraint_set.insert(*first);
 }

Likely invalid or redundant comment.


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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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 using 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.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration 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: 11

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 3427faa and 286a914.

📒 Files selected for processing (8)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/ebpf_yaml.cpp (6 hunks)
  • src/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/ebpf_yaml.cpp (1)
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment

🔇 Additional comments (9)
src/asm_parse.hpp (1)

6-6: LGTM: New header inclusions are appropriate.

The added headers (, "crab/interval.hpp", and "crab/linear_constraint.hpp") are necessary for the new function declaration and align with the PR objectives of implementing constraint checking functionality.

Also applies to: 9-10

src/config.hpp (1)

24-24: Verify integration of the new option

While the addition of store_pre_invariants is correct, we should ensure its proper integration:

  1. Verify that ebpf_verifier_default_options (declared at the end of this file) is updated to include a default value for store_pre_invariants.
  2. Check that thread_local_options is properly initialized with this new option where relevant in the codebase.

To verify the integration, run the following script:

This script will help ensure that the new option is properly integrated into the codebase.

src/crab_verifier.hpp (1)

29-42: LGTM! Function declaration aligns well with PR objectives.

The new function ebpf_check_constraints_at_label is well-declared and documented. It accurately implements the PR objective of allowing users to compare a set of constraints against a model at a specific label. The function signature and documentation provide clear information about its purpose, parameters, and return value.

test-data/add.yaml (3)

182-182: LGTM: Pre-conditions are well-defined.

The pre-conditions for registers r0, r1, and r2 are clearly specified and consistent, initializing them as numbers with a value of 0. This sets up a good starting point for the test case.


184-190: LGTM: Code section is concise and relevant.

The code section contains a series of simple arithmetic operations and register assignments. This is well-suited for testing the eBPF verifier's ability to track concrete register states, which aligns with the PR objectives.


179-219: Overall, the new test case is well-designed and aligns with PR objectives.

The "check concrete state" test case is a valuable addition to the test suite. It effectively demonstrates the ability to check constraints at specific labels and verify concrete state invariants, which aligns perfectly with the PR objectives.

The test case is well-structured with clear pre-conditions, a concise code section, comprehensive invariants-to-check, and thorough post-conditions. The minor formatting and duplication issues mentioned earlier can be easily addressed to further improve the quality of the test case.

Great job on implementing this test case to validate the new ebpf_check_constraints_at_label functionality!

🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment

src/crab_verifier.cpp (2)

287-287: Validate label string before constructing label_t

The construction of label_t label(label_string); assumes that label_string is a valid label. Consider adding validation to ensure that label_string corresponds to a valid label in the program, and handle any exceptions that may be thrown if the label is invalid.

You can verify whether the label exists by checking against the available labels in the save_pre_invariants. If the label is invalid, provide a clear error message to the user.


305-309: Handle bottom abstract invariant appropriately

If the from_inv (abstract invariant) is bottom, it means the program state at that label is unreachable.

Ensure that this situation is expected in your use case. If reaching a bottom invariant is unexpected, you might need to investigate why the invariant is bottom at this label.

src/ebpf_yaml.cpp (1)

262-262: Verify the necessity of setting 'store_pre_invariants' to true

Setting test_case.options.store_pre_invariants to true unconditionally may have unintended side effects or performance implications. Ensure that this option needs to be enabled for all test cases, or consider making it configurable per test case.

src/asm_parse.hpp Outdated Show resolved Hide resolved
src/config.hpp Outdated Show resolved Hide resolved
src/ebpf_yaml.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Oct 14, 2024

Coverage Status

coverage: 90.8% (+0.3%) from 90.532%
when pulling e92408c on Alan-Jowett:issue728
into 41fbd5a on vbpf:main.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 286a914 and 0f6520e.

📒 Files selected for processing (8)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/ebpf_yaml.cpp (6 hunks)
  • src/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
🔇 Additional comments (11)
src/asm_parse.hpp (3)

6-6: LGTM: New header inclusions are appropriate.

The added headers (, "crab/interval.hpp", "crab/linear_constraint.hpp") are necessary for the new function declaration and align with the PR objectives.

Also applies to: 9-10


14-21: Excellent addition of function documentation.

The detailed comment above the parse_linear_constraints function provides clear information about its purpose, parameters, and return value. This addition addresses the suggestion from the previous review and enhances code readability and maintainability.


22-23: LGTM: New function declaration is well-structured and aligns with PR objectives.

The parse_linear_constraints function declaration is appropriately designed with efficient parameter passing (const and reference) and a clear return type. The function signature matches the description in the comment and supports the new functionality for constraint checking.

src/config.hpp (1)

24-25: LGTM: New option for storing pre-invariants added with clear documentation

The addition of bool store_pre_invariants; to the ebpf_verifier_options_t structure is appropriate and aligns with the PR objectives. The comment explaining its purpose is clear and concise, which improves code readability and maintainability.

src/ebpf_yaml.hpp (1)

17-17: LGTM! Documentation suggestion addressed.

The new member variable invariants_to_check is well-defined and appropriately documented. The inline comment clearly explains its purpose, addressing the suggestion from the previous review.

This addition aligns with the PR objectives, enabling the checking of constraints at specific labels. The use of std::map<std::string, std::set<std::string>> is a good choice for efficient lookup and prevention of duplicate invariants.

test-data/add.yaml (1)

178-261: Excellent addition of comprehensive test cases.

The two new test cases, "check concrete state" and "check concrete state - negative", are excellent additions to the test suite. They provide thorough coverage of the new functionality for checking constraints at specific labels, including both positive and negative scenarios. These test cases align perfectly with the PR objectives and significantly enhance the overall quality of the test suite.

Great job on improving the test coverage and ensuring the robustness of the new feature!

src/ebpf_yaml.cpp (5)

102-102: LGTM

The addition of the invariants_to_check member to RawTestCase is appropriate and integrates well with the existing code. This allows for the storage of invariants to check from the YAML test cases.


130-142: Function 'parse_invariants_to_check' is correctly implemented

The function properly checks for the existence of 'invariants-to-check' before accessing it, preventing potential exceptions. It correctly parses the invariants and constructs the required map for further processing.


151-151: Assignment of 'invariants_to_check' in 'parse_case'

The field invariants_to_check in RawTestCase is correctly initialized using the parse_invariants_to_check(case_node) function. This ensures that the invariants are properly loaded from the YAML configuration.


223-225: Proper propagation of 'invariants_to_check' in 'read_case'

The invariants_to_check member is correctly assigned from raw_case to the new TestCase, ensuring that the invariants are available for verification during test execution.


266-267: Setting 'store_pre_invariants' to 'true'

Setting test_case.options.store_pre_invariants to true ensures that pre-invariants are stored. This is necessary for checking invariants at specific labels during the test case execution.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
@Alan-Jowett Alan-Jowett force-pushed the issue728 branch 3 times, most recently from 8a8a8fd to 73a9473 Compare October 14, 2024 22:05
@Alan-Jowett
Copy link
Contributor Author

The PR was rebased. @coderabbitai full review

Copy link

coderabbitai bot commented Oct 14, 2024

@Alan-Jowett: Understood, I will perform a full review of the updated PR.

✅ Actions performed

Full review triggered.

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: 10

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 0f6520e and 8ecfe92.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/ebpf_yaml.cpp (6 hunks)
  • src/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (2)
src/ebpf_yaml.cpp (1)
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:220-261
Timestamp: 2024-10-14T21:52:47.957Z
Learning: In `test-data/add.yaml`, error messages in test cases should match the style used by the verifier by including the label number at the beginning of the message, e.g., `"3: message"`.
🔇 Additional comments (8)
src/asm_parse.hpp (2)

6-6: LGTM: New includes are appropriate and well-organized.

The added includes for <vector>, "crab/interval.hpp", and "crab/linear_constraint.hpp" are necessary for the new function declaration. The ordering of includes follows good practices, with standard library headers preceding project-specific ones.

Also applies to: 9-10


14-23: LGTM: Well-documented function declaration aligns with PR objectives.

The new parse_linear_constraints function declaration is well-structured and consistent with the existing code style. The added documentation provides a clear description of the function's purpose, parameters, and return value, which addresses the previous review comments and enhances code readability and maintainability.

src/config.hpp (1)

24-25: LGTM: New option for storing pre-invariants added with clear documentation

The addition of bool store_pre_invariants; to the ebpf_verifier_options_t structure is appropriate and aligns with the PR objectives. The inline comment clearly explains the purpose of this new option, which enhances code readability and maintainability.

src/ebpf_yaml.hpp (1)

17-17: LGTM! Documentation added as suggested.

The new member variable invariants_to_check has been added to the TestCase struct with appropriate documentation. This addition aligns well with the PR objectives, allowing for the storage and checking of invariants at specific labels. The implementation uses suitable data structures (std::map and std::set) for efficient lookup and prevention of duplicate invariants.

The inline comment provides a clear explanation of the member's purpose, addressing the suggestion from the previous review.

test-data/add.yaml (1)

180-261: Overall: Excellent addition of test cases for constraint checking.

The two new test cases, "check concrete state" and "check concrete state - negative", are valuable additions to the test suite. They effectively cover the functionality of checking constraints at specific labels, which aligns perfectly with the PR objectives. The positive and negative test scenarios provide comprehensive coverage for the new ebpf_check_constraints_at_label API function.

These test cases will help ensure the reliability and correctness of the constraint checking feature, contributing to the overall robustness of the eBPF verifier.

src/asm_syntax.hpp (1)

26-47: Well-implemented constructor and appropriate exception handling

The new label_t constructor correctly parses the input std::string_view to initialize from, to, and stack_frame_prefix. Exception handling for std::invalid_argument and std::out_of_range is properly implemented, ensuring robustness against invalid inputs.

src/crab_verifier.cpp (1)

165-166: Confirm thread-local storage usage for save_pre_invariants

The introduction of static thread_local std::optional<crab::invariant_table_t> save_pre_invariants ensures that pre-invariants are stored per thread. If the verifier operates in a multi-threaded environment, this approach is appropriate. However, please verify that all accesses to save_pre_invariants are thread-safe and that its use aligns with the intended concurrency model.

src/ebpf_yaml.cpp (1)

130-142: Function parse_invariants_to_check handles YAML parsing correctly

The parse_invariants_to_check function effectively parses the "invariants-to-check" node from the YAML file and appropriately handles the case when the node is not defined, ensuring robustness against missing data.

src/config.cpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp 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: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 8ecfe92 and 924ad43.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/ebpf_yaml.cpp (6 hunks)
  • src/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (2)
src/ebpf_yaml.cpp (1)
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:220-261
Timestamp: 2024-10-14T21:52:47.957Z
Learning: In `test-data/add.yaml`, error messages in test cases should match the style used by the verifier by including the label number at the beginning of the message, e.g., `"3: message"`.
🔇 Additional comments (17)
src/config.cpp (1)

17-17: LGTM! Consider adding documentation for the new option.

The addition of .store_pre_invariants = false is consistent with the PR objectives and provides a sensible default value. This new option enhances the configurability of the verifier, allowing users to opt-in to storing pre-invariants when needed.

As previously suggested, consider adding a comment above this line or in the header file to briefly explain the purpose and usage of this new option. This would improve the maintainability of the code and help future developers understand its significance.

src/asm_parse.hpp (2)

6-6: LGTM: New includes are appropriate and well-ordered.

The addition of these headers is necessary for the new parse_linear_constraints function. The ordering follows the convention of placing standard library headers before project-specific ones.

Also applies to: 9-10


14-23: LGTM: Well-documented and properly declared new function.

The parse_linear_constraints function declaration is well-structured and consistent with the existing code style. The added comment provides a clear description of the function's purpose, parameters, and return value, which enhances code readability and maintainability.

src/config.hpp (1)

24-25: LGTM: Well-documented addition of store_pre_invariants option

The new store_pre_invariants boolean member has been added to the ebpf_verifier_options_t structure with a clear and informative comment. This addition aligns well with the PR objectives and supports the new functionality for storing pre-invariants.

The comment above the new member effectively explains its purpose, addressing the suggestion from the previous review. The naming is consistent with other boolean options in the structure, maintaining good code readability.

src/ebpf_yaml.hpp (1)

17-17: LGTM. Documentation added as suggested.

The new member variable invariants_to_check has been added to the TestCase struct with appropriate documentation. This addition aligns well with the PR objectives and the requirements from the linked issue #728.

The use of std::map<std::string, std::set<std::string>> is a good choice for efficient lookup of invariants by label and prevention of duplicate invariants for each label.

src/crab_verifier.hpp (1)

30-43: LGTM! Documentation enhancement implemented.

The function declaration and documentation for ebpf_check_constraints_at_label are well-defined and align with the PR objectives. The previous suggestion to explain "abstract verifier constraints" has been implemented, improving the clarity of the documentation.

src/crab_verifier.cpp (7)

20-20: Appropriate inclusion of 'asm_parse.hpp' header

The inclusion of #include "asm_parse.hpp" is necessary to expose the function for parsing linear constraints. This ensures that the parsing functionality is accessible within this source file.


165-166: Declaration of thread-local variable 'save_pre_invariants'

The addition of the thread-local variable save_pre_invariants correctly initializes it to std::nullopt. This variable is used to store pre-invariants when the store_pre_invariants option is enabled.


178-180: Conditional storage of pre-invariants in 'get_ebpf_report'

The code appropriately checks if store_pre_invariants is enabled before storing pre_invariants in save_pre_invariants. This ensures that pre-invariants are only stored when required.


230-232: Conditional storage of pre-invariants in 'ebpf_analyze_program_for_test'

Similarly, the function ebpf_analyze_program_for_test now stores pre_invariants in save_pre_invariants when store_pre_invariants is enabled. This maintains consistency across functions that perform analysis.


279-280: Clearing thread-local state in 'ebpf_verifier_clear_thread_local_state'

Resetting save_pre_invariants to std::nullopt ensures that the thread-local state is properly cleared when the verifier's state is reset. This prevents any potential leakage of pre-invariants between verifications.


282-326: Implementation of 'ebpf_check_constraints_at_label' function

The new ebpf_check_constraints_at_label function provides the ability to compare a set of constraints against the stored pre-invariants at a specific label. The function includes detailed error messages to aid in debugging when discrepancies are found.


328-337: Implementation of 'ebpf_get_invariants_at_label' function

The addition of ebpf_get_invariants_at_label allows retrieval of the stored invariants at a given label. The function checks if pre-invariants are available and returns them appropriately.

src/ebpf_yaml.cpp (4)

102-102: Addition of 'invariants_to_check' to 'RawTestCase' Structure

The new member invariants_to_check is appropriately added to the RawTestCase struct to store invariants for testing purposes.


151-151: Initializing 'invariants_to_check' in 'parse_case' Function

The parse_case function correctly initializes the invariants_to_check member by invoking parse_invariants_to_check(case_node).


223-225: Transferring 'invariants_to_check' to 'TestCase'

The read_case function appropriately transfers the invariants_to_check member from RawTestCase to TestCase, ensuring that the invariants are available for test execution.


266-269: Setting 'store_pre_invariants' Based on Invariants to Check

The logic correctly sets test_case.options.store_pre_invariants to true when test_case.invariants_to_check is not empty, enabling the storage of pre-invariants necessary for invariant checks.

src/ebpf_yaml.hpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 924ad43 and fc5d74a.

📒 Files selected for processing (5)
  • src/config.cpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/ebpf_yaml.cpp (6 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (3)
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/crab_verifier.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/ebpf_yaml.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 232-232:
232:6 [comments] too few spaces before comment


[warning] 236-236:
236:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 244-244:
244:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment

🔇 Additional comments (13)
src/config.cpp (1)

17-17: LGTM! The new option is well-implemented and documented.

The addition of .store_pre_invariants = false with an explanatory comment is consistent with the PR objectives. It provides a sensible default value and clear guidance on its usage, enhancing the configurability of the verifier while maintaining backward compatibility.

src/crab_verifier.hpp (3)

30-45: LGTM! Function aligns well with PR objectives.

The ebpf_check_constraints_at_label function declaration and its documentation are well-defined and directly address the PR objectives. The function provides a way to compare concrete constraints against abstract verifier constraints at a specific label, which is a key requirement outlined in the linked issue #728.

The documentation is comprehensive and includes a clear explanation of abstract constraints, which enhances usability. The function signature accurately reflects its purpose and the described behavior.


46-53: LGTM! Function complements the PR objectives well.

The ebpf_get_invariants_at_label function declaration and its documentation are well-defined and support the PR objectives. This function provides a mechanism to retrieve invariants at a specific label, which is crucial for comparing abstract and concrete states as outlined in the linked issue #728.

The documentation clearly states the function's purpose and requirements, and the exception handling is properly documented. The function signature accurately reflects its intended behavior.


29-53: Overall, excellent additions to the codebase.

The new functions ebpf_check_constraints_at_label and ebpf_get_invariants_at_label are well-implemented and documented. They directly address the requirements outlined in the linked issue #728 and align perfectly with the PR objectives. These additions will significantly enhance the ability to compare abstract and concrete states in the BPF verification process.

The code is clean, well-structured, and maintains the existing coding style of the file. Great job on these implementations!

test-data/add.yaml (2)

180-219: LGTM: Well-structured test case for concrete state checking.

The "check concrete state" test case is well-designed and aligns perfectly with the PR objective of checking constraints at specific labels. The pre-conditions, code execution, invariants-to-check, and post-conditions are all correctly defined and provide a thorough validation of the register states throughout the execution.

🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


220-261: LGTM: Well-designed negative test case for constraint checking.

The "check concrete state - negative" test case is well-structured and serves as an excellent negative test for the constraint checking functionality. It intentionally includes an incorrect invariant to trigger a mismatch between concrete and abstract invariants, which aligns with the PR objectives.

The error message format correctly includes the label number at the beginning, which is consistent with the verifier's error reporting style.

🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 232-232:
232:6 [comments] too few spaces before comment


[warning] 236-236:
236:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 244-244:
244:7 [comments] too few spaces before comment

src/crab_verifier.cpp (6)

165-172: Modularize invariant saving logic for maintainability

The addition of save_invariants_if_needed improves code maintainability by encapsulating the logic for saving pre-invariants. This adheres to the DRY principle and makes future changes easier.


184-184: Ensure pre-invariants are saved consistently

By calling save_invariants_if_needed(pre_invariants);, the function ensures that pre-invariants are stored when necessary. This is crucial for functions that rely on these invariants later in the verification process.


234-234: Consistent use of invariant saving function

The invocation of save_invariants_if_needed(pre_invariants); here ensures that pre-invariants are consistently saved across different analysis functions, promoting code consistency.


281-282: Properly clear thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that the thread-local state is clean for subsequent analyses. This prevents potential issues from residual data.


284-328: Robust exception handling during constraint checking

The ebpf_check_constraints_at_label function is wrapped in a try-catch block to handle exceptions derived from std::exception. This ensures that any errors during constraint checking are caught and reported gracefully.


330-341: Intentional exception propagation for label parsing

In ebpf_get_invariants_at_label, constructing label_t l = label_t(label); may throw an exception if the label is invalid. The comment indicates that this is intentional so that the caller can handle malformed labels appropriately.

src/ebpf_yaml.cpp (1)

266-269: Ensure side effects of setting 'store_pre_invariants' are intended

Setting test_case.options.store_pre_invariants to true when invariants_to_check is not empty allows pre-invariants to be stored for later checks. Verify that enabling this option does not unintentionally affect other parts of the verifier or introduce performance overhead.

To assess any potential side effects, consider reviewing where store_pre_invariants is used in the codebase:

✅ Verification successful

Side Effects of Setting store_pre_invariants Confirmed

After reviewing all usages of store_pre_invariants, enabling this option is intentional and does not introduce unintended side effects or significant performance overhead. The flag is used in a controlled manner within the verifier, ensuring that activating it supports necessary functionalities without negatively impacting other parts of the system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of 'store_pre_invariants' in the codebase.

# Expected Result: Identify code that relies on 'store_pre_invariants' to ensure enabling it is safe.
rg --type cpp 'store_pre_invariants'

Length of output: 832

test-data/add.yaml Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
src/ebpf_yaml.cpp Outdated Show resolved Hide resolved
@Alan-Jowett
Copy link
Contributor Author

@elazarg is this the best option for allowing the caller to check the current concrete state of the vm against the abstract state the verifier has?

I had considered just passing in the register values, but that doesn't really work well as there is additional context that the VM has that can be used to filter the assertions (things like if the register value is pointing to context, packet, shared, or stack memory) that the verifier would otherwise not know. This becomes an issue as the concrete values for pointers tend to be > 2GB which trips some assertions in the verifier.

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: 10

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between fc5d74a and fa3ab02.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (4)
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/crab_verifier.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 232-232:
232:6 [comments] too few spaces before comment


[warning] 236-236:
236:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 244-244:
244:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment

🔇 Additional comments (19)
src/config.cpp (1)

17-17: LGTM! The new option is well-implemented and documented.

The addition of .store_pre_invariants = false with an explanatory comment is consistent with the PR objectives. It provides a sensible default value and clear guidance on its usage, enhancing the configurability of the verifier while maintaining backward compatibility.

src/asm_parse.hpp (3)

6-6: LGTM: New include directives are appropriate.

The added include directives for <vector>, crab/interval.hpp, and crab/linear_constraint.hpp are necessary for the new functionality and are placed in a logical order.

Also applies to: 9-10


14-21: LGTM: Function comment is clear and informative.

The added comment for the parse_linear_constraints function provides clear information about its purpose, parameters, and return value. This addition addresses the suggestion from the previous review and enhances code documentation.


22-23: LGTM: Function declaration is well-structured and aligns with PR objectives.

The parse_linear_constraints function declaration is consistent with its documentation and the PR objectives. It appropriately uses const and reference parameters for efficiency.

src/config.hpp (1)

24-25: LGTM: New option for storing pre-invariants added with clear documentation

The addition of bool store_pre_invariants; to the ebpf_verifier_options_t structure is appropriate and aligns with the PR objectives. The comment above the new member clearly explains its purpose, addressing the suggestion from the previous review.

src/crab_verifier.hpp (2)

30-45: LGTM! Documentation improvements are appreciated.

The function declaration for ebpf_check_constraints_at_label is well-defined and aligns with the PR objectives. The documentation has been enhanced as suggested in the previous review, providing a clear explanation of "abstract verifier constraints". This addition improves the overall clarity and usability of the function.


46-53: LGTM! Concise and clear documentation.

The function declaration for ebpf_get_invariants_at_label is well-defined and aligns with the PR objectives. The documentation provides essential information about the function's purpose and requirements. The concise approach to documentation is appropriate, as per the previous feedback from Alan-Jowett.

test-data/add.yaml (2)

180-261: Overall: Excellent addition of concrete state checking test cases.

The new test cases "check concrete state" and "check concrete state - negative" are well-designed and significantly contribute to the PR's objective of implementing and validating the ebpf_check_constraints_at_label functionality. They provide comprehensive coverage for both successful constraint checking and error detection scenarios.

The minor formatting suggestions and the removal of a duplicate assertion will further improve the readability and maintainability of these test cases. Once these small adjustments are made, the changes to this file will be in excellent shape.

🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


[warning] 200-200:
200:6 [comments] too few spaces before comment


[warning] 204-204:
204:7 [comments] too few spaces before comment


[warning] 232-232:
232:6 [comments] too few spaces before comment


[warning] 236-236:
236:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 244-244:
244:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 196-196:
196:6 [comments] too few spaces before comment


209-219: 🧹 Nitpick (assertive)

Minor: Remove duplicate assertion in post-conditions.

There's a minor duplication in the post-conditions for register r0.

Consider removing one of the duplicate assertions:

post:
  - r0.type=number
  - r0.uvalue=3
- - r0.svalue=3
  - r1.type=number
  - r1.svalue=3
  - r1.uvalue=3
  - r2.type=number
  - r2.svalue=2
  - r2.uvalue=2

Likely invalid or redundant comment.

src/asm_syntax.hpp (1)

26-47: Well-implemented label parsing constructor

The new label_t constructor effectively parses the string label and initializes the from, to, and stack_frame_prefix members. Exception handling is appropriately included for invalid inputs.

src/crab_verifier.cpp (6)

20-20: Include Statement Added Appropriately

The inclusion of "asm_parse.hpp" is necessary for exposing the function for parsing linear constraints and is correctly added.


165-172: Refactored Code Enhances Maintainability

The introduction of saved_pre_invariants and the helper function save_invariants_if_needed improves code modularity and adheres to the DRY principle, enhancing maintainability.


184-184: Correct Usage of Helper Function in get_ebpf_report

The call to save_invariants_if_needed(pre_invariants); correctly stores pre-invariants when the store_pre_invariants option is enabled.


234-234: Appropriate Invocation of Helper Function in Testing

The use of save_invariants_if_needed(pre_invariants); in ebpf_analyze_program_for_test ensures that pre-invariants are stored as needed during testing.


281-282: Thread-Local State Reset Properly

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that the thread-local state is cleared correctly.


284-328: ebpf_check_constraints_at_label Implemented Effectively

The new function ebpf_check_constraints_at_label accurately compares concrete constraints against pre-invariants at a specified label, providing detailed output and handling exceptions appropriately.

src/test/ebpf_yaml.cpp (3)

102-102: Ensure consistent initialization of invariants_to_check in RawTestCase

The new member invariants_to_check has been added to the RawTestCase struct. Verify that this member is properly initialized in all instances to prevent potential uninitialized member usage.


151-151: Confirm correct assignment of invariants_to_check in parse_case

In the parse_case function, ensure that the assignment of invariants_to_check correctly populates the RawTestCase structure. This guarantees that all invariants are accurately captured for the test cases.


223-225: Verify accurate transfer of invariants_to_check to TestCase in read_case

The invariants_to_check member from RawTestCase is assigned to TestCase. Ensure that this transfer preserves all the invariants without any data loss or corruption.

src/test/ebpf_yaml.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/test/ebpf_yaml.cpp Show resolved Hide resolved
src/test/ebpf_yaml.cpp Outdated Show resolved Hide resolved
src/test/ebpf_yaml.cpp 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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between fa3ab02 and 499572d.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (4)
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/crab_verifier.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/test/ebpf_yaml.cpp:280-291
Timestamp: 2024-10-25T15:33:32.202Z
Learning: In `src/test/ebpf_yaml.cpp`, error messages for invariant mismatches should be concise single-line messages, as the test authors already know the expected invariants. Detailed diagnostic messages are not necessary.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment


[warning] 202-202:
202:6 [comments] too few spaces before comment


[warning] 207-207:
207:7 [comments] too few spaces before comment


[warning] 235-235:
235:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 245-245:
245:6 [comments] too few spaces before comment


[warning] 250-250:
250:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment

🔇 Additional comments (20)
src/config.cpp (1)

17-17: LGTM! The implementation is clean and well-documented.

The new option is properly initialized with a sensible default value of false, making it an opt-in feature. The added comment clearly explains its purpose and relationship with the new API functions.

Let's verify the usage of this option in the codebase:

✅ Verification successful

Let me gather more information about the usage of this option.


Implementation and usage of store_pre_invariants is consistent and well-integrated

The verification confirms that:

  • The option is properly integrated with the new API functions in crab_verifier.hpp/cpp
  • Implementation uses thread-local storage for pre-invariants when the option is enabled
  • The option is correctly used in test cases (ebpf_yaml.cpp) to verify invariants
  • Documentation clearly explains the requirement of enabling this option for the new API functions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of store_pre_invariants option
# Expected: References in the implementation of ebpf_check_constraints_at_label and ebpf_get_invariants_at_label

# Test 1: Find where the option is used
rg -l "store_pre_invariants"

# Test 2: Find the implementation of the mentioned API functions
ast-grep --pattern 'ebpf_check_constraints_at_label($_)'
ast-grep --pattern 'ebpf_get_invariants_at_label($_)'

Length of output: 240


Script:

#!/bin/bash
# Look for actual implementation and usage of the option
rg "store_pre_invariants" -C 3

# Look specifically for the API functions mentioned in the comment
rg "ebpf_(check_constraints|get_invariants)_at_label" -C 3

Length of output: 5448

src/asm_parse.hpp (2)

6-6: LGTM: Includes are properly organized and necessary.

The new includes follow the standard ordering (STL before project headers) and are required for the new functionality.

Also applies to: 9-10


14-23: Verify consistent usage of linear constraints parsing.

The function declaration looks good and aligns with the PR objectives. Let's verify its usage across the codebase to ensure consistency.

✅ Verification successful

Let me gather more context about the usage pattern by checking the implementation and call sites.


Function usage is consistent across the codebase

The verification shows that parse_linear_constraints is used consistently:

  • Implementation in asm_parse.cpp correctly handles the parsing of constraints and populates the numeric ranges
  • Single usage point in ebpf_domain.cpp correctly uses both the returned constraints and the populated numeric ranges
  • The function signature and parameter types are used as intended across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of parse_linear_constraints function
# and related linear constraint handling

# Check for linear constraint parsing patterns
echo "Checking for linear constraint parsing patterns..."
rg -l "linear_constraint" --type cpp

# Look for related constraint checking implementations
echo "Looking for constraint checking implementations..."
ast-grep --pattern 'parse_linear_constraints($$$)'

Length of output: 1032


Script:

#!/bin/bash
# Check the implementation in asm_parse.cpp
echo "Checking implementation in asm_parse.cpp..."
rg -A 10 "parse_linear_constraints" src/asm_parse.cpp

# Check the usage context in ebpf_domain.cpp
echo "Checking usage in ebpf_domain.cpp..."
rg -B 5 -A 5 "parse_linear_constraints" src/crab/ebpf_domain.cpp

Length of output: 1279

src/config.hpp (1)

24-25: LGTM: Well-documented configuration option for pre-invariant storage

The addition of store_pre_invariants is well-placed and properly documented. The implementation aligns with the PR objectives to support constraint checking at labels by allowing the storage of pre-invariants during verification.

src/test/ebpf_yaml.hpp (1)

17-17: LGTM! Well-structured addition to support label-specific invariant checking.

The new invariants_to_check member is well-documented and properly integrated with the existing test framework. Its type (std::map<std::string, std::set<std::string>>) effectively supports the PR's objective of allowing constraint validation at specific labels during test execution.

src/crab_verifier.hpp (1)

30-45: LGTM! Well-documented API function.

The function declaration and documentation are clear, complete, and align perfectly with the PR objectives. The documentation properly explains the requirements and behavior of the function.

test-data/add.yaml (1)

180-222: LGTM: Well-structured test case aligns with PR objectives.

The test case effectively validates the new ebpf_check_constraints_at_label API by:

  1. Checking constraints at multiple labels (1, 2, 3, -2)
  2. Verifying both register types and values
  3. Tracking state transitions through the program execution
🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment


[warning] 202-202:
202:6 [comments] too few spaces before comment


[warning] 207-207:
207:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment

src/asm_syntax.hpp (1)

26-26: LGTM! Constructor declaration follows best practices.

The constructor is correctly marked explicit and uses std::string_view for efficient string parsing.

src/crab_verifier.cpp (7)

20-20: Include asm_parse.hpp for constraint parsing

The inclusion of "asm_parse.hpp" is appropriate as it exposes the function for parsing linear constraints, aligning with the PR objectives.


165-166: Proper initialization of thread-local saved_pre_invariants

Declaring saved_pre_invariants as a thread_local std::optional ensures thread safety and correct initialization for storing pre-invariants.


167-171: Good use of helper function save_invariants_if_needed

Introducing the save_invariants_if_needed function eliminates code duplication and adheres to the DRY principle, enhancing maintainability.


184-184: Consistent invocation of save_invariants_if_needed

Using save_invariants_if_needed in both get_ebpf_report and ebpf_analyze_program_for_test ensures pre-invariants are stored when needed, promoting code reuse.

Also applies to: 234-234


281-282: Resetting saved_pre_invariants in thread-local state

Properly resetting saved_pre_invariants to std::nullopt prevents stale data from persisting across analyses, ensuring accurate results.


284-328: Robust error handling in ebpf_check_constraints_at_label

The function provides comprehensive error messages and uses a try-catch block to handle exceptions derived from std::exception, enhancing reliability and user feedback.


330-341: Intentional exception propagation in ebpf_get_invariants_at_label

By allowing exceptions to propagate, the function enables callers to handle invalid labels appropriately, which is acceptable if documented and expected.

src/test/ebpf_yaml.cpp (5)

102-102: LGTM!

Adding invariants_to_check to the RawTestCase struct enhances the capability to handle invariants in test cases.


130-143: LGTM!

The parse_invariants_to_check function correctly parses invariants from the YAML node with proper exception handling.


153-153: LGTM!

Including invariants_to_check in the parse_case function ensures that invariants are parsed and included in the test cases.


225-227: LGTM!

Assigning invariants_to_check to the TestCase object in read_case appropriately passes the invariants to the test execution.


268-271: LGTM!

Conditionally setting store_pre_invariants based on invariants_to_check is appropriate and ensures that pre-invariants are stored only when needed.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/asm_syntax.hpp Show resolved Hide resolved
src/test/ebpf_yaml.cpp 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 499572d and 3d79b66.

📒 Files selected for processing (3)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/test/ebpf_yaml.cpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment


[warning] 202-202:
202:6 [comments] too few spaces before comment


[warning] 207-207:
207:7 [comments] too few spaces before comment


[warning] 235-235:
235:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 245-245:
245:6 [comments] too few spaces before comment


[warning] 246-246:
246:6 [comments-indentation] comment not indented like content


[warning] 251-251:
251:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment

🔇 Additional comments (8)
src/crab_verifier.hpp (2)

30-45: LGTM! Well-documented function declaration.

The function declaration is well-structured and the documentation clearly explains its purpose, requirements, and behavior. It aligns perfectly with the PR objectives of comparing abstract state to concrete state at specific labels.


46-54: LGTM! Well-documented function declaration.

The function declaration is well-structured and the documentation clearly explains its purpose, requirements, and behavior.

src/test/ebpf_yaml.cpp (6)

102-102: Addition of invariants_to_check member to RawTestCase

The new member invariants_to_check is appropriately added to the RawTestCase struct to store invariants from the YAML configuration.


130-143: Proper parsing and error handling in parse_invariants_to_check

The function parse_invariants_to_check correctly processes the invariants-to-check YAML node and handles exceptions by throwing a std::runtime_error with a meaningful message.


153-153: Integration of invariants_to_check in parse_case function

The invariants_to_check member is properly initialized in the parse_case function by calling parse_invariants_to_check(case_node).


225-227: Passing invariants_to_check to TestCase

The invariants_to_check member is correctly assigned from raw_case to TestCase in the read_case function, ensuring the invariants are available for testing.


268-271: Conditional setting of store_pre_invariants

By setting test_case.options.store_pre_invariants = true only when invariants_to_check is not empty, you ensure pre-invariants are stored only when necessary, avoiding unintended side effects.


282-295: Invariant checks with exception handling

The loop over test_case.invariants_to_check correctly calls ebpf_check_constraints_at_label for each invariant and handles exceptions appropriately. This ensures that any discrepancies or exceptions are captured in actual_messages, maintaining test robustness.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml 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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 3d79b66 and 5f2de4e.

📒 Files selected for processing (1)
  • src/crab_verifier.hpp (1 hunks)

src/crab_verifier.hpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp 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: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 5f2de4e and 8d4bc1e.

📒 Files selected for processing (1)
  • src/crab_verifier.hpp (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/crab_verifier.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
🔇 Additional comments (1)
src/crab_verifier.hpp (1)

53-63: LGTM! Documentation accurately reflects implementation behavior.

The function declaration and documentation are well-structured and complete. The documentation correctly describes:

  • The requirement for the store_pre_invariants option
  • The return value behavior, including the empty set case
  • The exception handling for invalid labels

src/crab_verifier.hpp 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: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 8d4bc1e and 3c44c97.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (5)
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/test/ebpf_yaml.cpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/test/ebpf_yaml.cpp:280-291
Timestamp: 2024-10-25T15:33:32.202Z
Learning: In `src/test/ebpf_yaml.cpp`, error messages for invariant mismatches should be concise single-line messages, as the test authors already know the expected invariants. Detailed diagnostic messages are not necessary.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:207-211
Timestamp: 2024-10-25T18:03:35.790Z
Learning: The label `-2` in the test cases represents the exit label defined by the core code and should not be changed.
🪛 GitHub Check: validate-yaml
test-data/add.yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment


[warning] 202-202:
202:6 [comments] too few spaces before comment


[warning] 207-207:
207:7 [comments] too few spaces before comment


[warning] 235-235:
235:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 245-245:
245:6 [comments] too few spaces before comment


[warning] 246-246:
246:6 [comments-indentation] comment not indented like content


[warning] 251-251:
251:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment

🔇 Additional comments (17)
src/config.cpp (1)

17-17: LGTM! Well-documented configuration option.

The new .store_pre_invariants option is correctly implemented with an appropriate default value and clear documentation explaining its purpose and related functions. This addition aligns well with the PR objectives for enabling state comparison functionality.

src/asm_parse.hpp (3)

6-6: LGTM: Includes are well-organized and necessary.

The new includes are properly ordered (STL before project headers) and directly support the new functionality.

Also applies to: 9-10


14-23: LGTM: Function declaration and documentation are well-structured.


22-23: Verify integration with constraint checking system.

Let's ensure this function is properly integrated with the constraint checking system.

✅ Verification successful

Based on the search results, I can now generate the final response:

Integration with constraint checking system verified successfully

The function parse_linear_constraints is properly integrated with the constraint checking system:

  • Called directly in ebpf_domain.cpp to process constraints into the invariant system
  • Used in conjunction with ebpf_check_constraints_at_label through the constraint checking workflow
  • Configuration support exists via store_pre_invariants option
  • Integration is tested in the test suite (test/ebpf_yaml.cpp)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of parse_linear_constraints and its integration
# with the constraint checking system.

# Test 1: Find all calls to parse_linear_constraints
echo "=== Searching for parse_linear_constraints usage ==="
rg "parse_linear_constraints" -A 3

# Test 2: Find related constraint checking code
echo -e "\n=== Searching for related constraint checking code ==="
rg "check_constraints_at_label|ebpf_check_constraints_at_label" -A 3

Length of output: 2953

src/config.hpp (1)

25-25: Verify initialization of the new option.

Ensure that store_pre_invariants is properly initialized in the default options.

✅ Verification successful

store_pre_invariants is properly initialized

The option is correctly initialized to false in the default options structure with a helpful comment explaining its purpose.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check initialization of store_pre_invariants in default options
# Expected: Find the initialization of ebpf_verifier_default_options

# Search for the definition of default options
rg "ebpf_verifier_default_options\s*=" -A 15

Length of output: 787

src/test/ebpf_yaml.hpp (1)

17-17: LGTM! Well-structured addition to support constraint validation.

The new invariants_to_check member is well-designed for the task:

  • Efficient label-based lookup using map
  • Duplicate prevention using set
  • Clear documentation explaining its purpose

Previous nitpick about comment wording has already been addressed in this version.

src/crab_verifier.hpp (1)

30-52: LGTM! Function declaration and documentation are complete.

The function signature and documentation align well with the PR objectives. The documentation thoroughly covers normal operation, edge cases, and error handling. The parameter types and return type are appropriate for the function's purpose.

test-data/add.yaml (1)

180-268: LGTM: Well-structured test cases for constraint checking.

The test cases effectively validate the new constraint checking functionality:

  1. The positive test case verifies correct constraint checking at each execution step.
  2. The negative test case confirms that mismatches between concrete and abstract invariants are properly detected.
🧰 Tools
🪛 GitHub Check: validate-yaml

[warning] 192-192:
192:6 [comments] too few spaces before comment


[warning] 197-197:
197:6 [comments] too few spaces before comment


[warning] 202-202:
202:6 [comments] too few spaces before comment


[warning] 207-207:
207:7 [comments] too few spaces before comment


[warning] 235-235:
235:6 [comments] too few spaces before comment


[warning] 240-240:
240:6 [comments] too few spaces before comment


[warning] 245-245:
245:6 [comments] too few spaces before comment


[warning] 246-246:
246:6 [comments-indentation] comment not indented like content


[warning] 251-251:
251:7 [comments] too few spaces before comment


[warning] 192-192:
192:6 [comments] too few spaces before comment

src/crab_verifier.cpp (3)

165-171: Good use of a helper function to avoid code duplication

The introduction of save_invariants_if_needed effectively encapsulates the logic for saving pre-invariants and eliminates code duplication, adhering to the DRY principle.


281-281: Properly clearing thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that the thread-local state is correctly cleared between analyses, preventing potential issues with stale data.


284-328: Comprehensive error handling in ebpf_check_constraints_at_label

The function ebpf_check_constraints_at_label effectively handles various error conditions, providing clear and informative messages to the user. The use of detailed outputs when constraints do not match aids in debugging and understanding discrepancies between the concrete and abstract states.

src/test/ebpf_yaml.cpp (6)

102-102: Proper addition of invariants_to_check member

The new member invariants_to_check is correctly added to the RawTestCase struct, enhancing the test case's ability to handle invariants.


130-143: Correct implementation of parse_invariants_to_check function

The parse_invariants_to_check function effectively parses the invariants-to-check YAML node, handling cases where the node is undefined or null. The use of exception handling ensures robust parsing and meaningful error messages in case of parsing failures.


153-153: Accurate initialization in parse_case function

The invariants_to_check member is properly initialized using parse_invariants_to_check(case_node) within the parse_case function, ensuring that invariants are correctly parsed and stored for each test case.


230-232: Correct assignment in read_case function

The assignment of invariants_to_check from raw_case to test_case in the read_case function is accurate, maintaining the integrity of the test case data throughout the parsing process.


273-276: Appropriate conditional setting of store_pre_invariants

The condition to set test_case.options.store_pre_invariants = true when invariants_to_check is not empty is correctly implemented, ensuring that pre-invariants are stored only when necessary.


287-301: Robust invariant checking with concise error handling

The loop effectively checks the invariants at each label using ebpf_check_constraints_at_label. Exceptions are appropriately caught and handled, and error messages are kept concise, aligning with the established guidelines for test error reporting.

src/config.hpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/asm_syntax.hpp Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
@Alan-Jowett Alan-Jowett force-pushed the issue728 branch 2 times, most recently from 58bbb34 to 75fdf33 Compare October 26, 2024 18:39
src/asm_parse.hpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/crab_verifier.hpp 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 3c44c97 and b5006f8.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (6)
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/crab_verifier.hpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (22)
src/config.cpp (1)

17-17: LGTM! The new configuration option is well-documented.

The addition of .store_pre_invariants with its explanatory comment aligns perfectly with the PR objectives, specifically supporting the new ebpf_check_constraints_at_label and ebpf_get_invariants_at_label functions. The default value of false is appropriate as it makes this an opt-in feature.

src/asm_parse.hpp (3)

6-6: LGTM: Required headers for new functionality.

The new includes are appropriate for the added functionality:

  • <vector> for the return type and parameter
  • crab/interval.hpp and crab/linear_constraint.hpp for the Crab-specific types

Also applies to: 9-10


22-23: LGTM: Function declaration.


14-21: 🧹 Nitpick (assertive)

Consider updating parameter documentation format.

While the documentation is clear and informative, consider adopting the format suggested by @dthaler for consistency:

 /***
  * Parse a set of string form linear constraints into a vector of crab::linear_constraint_t
  *
- * @param[in] constraints A set of string form linear constraints.
- * @param[out] numeric_ranges A vector of numeric ranges that are extracted from the constraints.
+ * @param[in] constraints A set of string form linear constraints.
+ * @param[out] numeric_ranges A vector of numeric ranges that are extracted from the constraints.
  *
  * @return A vector of crab::linear_constraint_t
  */

Likely invalid or redundant comment.

src/config.hpp (1)

24-26: LGTM: Well-documented configuration option added

The new store_pre_invariants option is properly documented and aligns well with the PR objectives. The comment clearly explains its purpose and related functions. The code maintains consistent style with the rest of the file.

src/test/ebpf_yaml.hpp (1)

17-17: LGTM! Well-designed addition to support label-specific invariant checking.

The new invariants_to_check member is well-structured and properly documented. The use of std::map with std::set is an appropriate choice for storing multiple invariants per label, aligning perfectly with the PR's objective of enabling constraint validation at specific labels.

Note: The previous nitpick about enhancing the comment has already been addressed in this version.

src/crab_verifier.hpp (1)

53-66: LGTM! Documentation and implementation are well-aligned.

The function is well-documented with clear explanations of:

  • Purpose and requirements
  • Behavior when store_pre_invariants is not set
  • Return value semantics
  • Exception handling
test-data/add.yaml (2)

180-222: LGTM: Well-structured test case with comprehensive invariants.

The test case effectively validates the concrete state at each step of execution, with proper initialization, state tracking, and final state verification. The invariants correctly track the progression of register values through the arithmetic operations.


223-268: LGTM: Well-designed negative test case.

The test case effectively validates error detection by:

  1. Maintaining identical setup and execution as the positive test case
  2. Introducing a specific, well-documented invariant mismatch at label 3
  3. Including appropriate error message in the verifier's format
src/asm_syntax.hpp (1)

26-31: LGTM! Efficient implementation of stack frame prefix parsing.

The constructor efficiently uses string_view and correctly handles the stack frame prefix extraction.

src/crab_verifier.cpp (6)

167-171: Good refactoring to eliminate code duplication

The introduction of the save_invariants_if_needed function consolidates repeated code for saving pre-invariants. This improves maintainability and adheres to the DRY (Don't Repeat Yourself) principle.


184-184: Appropriate use of the refactored function

Using save_invariants_if_needed enhances code clarity and ensures consistent handling of pre-invariants within get_ebpf_report.


234-234: Consistent application of the refactored function

Applying save_invariants_if_needed in ebpf_analyze_program_for_test maintains consistency across functions that handle pre-invariants.


281-282: Properly clearing thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that thread-local state does not persist between verifier runs, preventing potential state leakage.


284-328: Robust exception handling in ebpf_check_constraints_at_label

The function appropriately handles exceptions during label parsing and constraint processing, ensuring that errors are caught and informative messages are provided to the user.


330-341: Exception behavior is correctly managed

The function ebpf_get_invariants_at_label relies on the caller to handle exceptions if the label is malformed. Since the exception behavior is documented in the header files, no additional handling is necessary here.

src/test/ebpf_yaml.cpp (6)

102-102: LGTM!

The addition of the invariants_to_check member to RawTestCase correctly extends the struct to accommodate invariants parsing.


130-143: Function parse_invariants_to_check is well-implemented.

The function properly handles the parsing of invariants from the YAML node, including exception handling for malformed inputs.


153-153: Integration of invariants parsing into parse_case.

The assignment of .invariants_to_check = parse_invariants_to_check(case_node) ensures that RawTestCase correctly includes invariants from the test cases.


230-232: Proper propagation of invariants to TestCase.

Including invariants_to_check in TestCase aligns with its addition to RawTestCase, ensuring consistency in data handling between parsing and test execution.


273-276: Conditional enabling of pre-invariant storage is appropriate.

Setting test_case.options.store_pre_invariants = true when invariants_to_check is not empty correctly configures the verifier options without unintended side effects.


287-301: Invariant checks are correctly implemented.

The loop correctly iterates over invariants_to_check, resets the std::stringstream, handles exceptions, and maintains concise error messages as per guidelines.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp Show resolved Hide resolved
src/asm_syntax.hpp Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.hpp 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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between b5006f8 and 79b4c76.

📒 Files selected for processing (9)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (6)
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:323-326
Timestamp: 2024-10-16T04:59:11.616Z
Learning: In `src/crab_verifier.cpp`, all exceptions thrown in the function `ebpf_check_constraints_at_label` derive from `std::exception`, making a catch-all handler unnecessary.
src/crab_verifier.hpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (22)
src/asm_parse.hpp (1)

6-6: LGTM: Required includes are properly ordered.

The new includes are necessary for the types used in the parse_linear_constraints function and follow the standard include ordering (STL before external dependencies).

Also applies to: 9-10

src/config.hpp (1)

24-26: LGTM: Well-documented configuration option for pre-invariants storage

The addition of store_pre_invariants is well-implemented and properly documented. The option aligns with the PR objectives of enabling state comparison functionality through the new ebpf_check_constraints_at_label and ebpf_get_invariants_at_label APIs.

src/test/ebpf_yaml.hpp (1)

17-17: LGTM! The implementation aligns perfectly with PR objectives.

The invariants_to_check member is well-designed for mapping labels to their expected invariants, which directly supports the PR's goal of comparing abstract and concrete states at specific labels. The documentation clearly describes its purpose in test execution.

src/crab_verifier.hpp (2)

30-52: LGTM! Documentation and function signature are well-structured.

The function declaration and its documentation are thorough, covering all essential aspects including purpose, requirements, error handling, and edge cases. The function signature is appropriate for its validation purpose.


53-66: LGTM! Documentation and function signature are well-defined.

The function declaration and its documentation are comprehensive, with clear explanation of behavior, return values, and error cases. The function signature is appropriate for retrieving invariants.

test-data/add.yaml (5)

180-190: LGTM: Well-structured test case initialization.

The test case setup is clear and follows a logical flow:

  1. Initializes all registers to zero
  2. Performs a sequence of basic operations (assignment and addition)
  3. Transfers the result to register r0

191-211: LGTM: Comprehensive invariant checks at each program point.

The invariants-to-check section effectively validates the program state at each critical point:

  • Label 1: After first assignment
  • Label 2: After second assignment
  • Label 3: After addition
  • Label -2: At program exit

Each check includes both signed and unsigned values, which aligns with the verifier's behavior.


212-222: LGTM: Complete post-conditions with both signed and unsigned values.

The post-conditions correctly include both signed and unsigned values for all registers, matching the verifier's behavior of emitting both types of invariants.


223-233: LGTM: Well-designed negative test case.

The negative test case effectively:

  1. Uses the same initial setup as the positive test
  2. Introduces an intentional mismatch in the invariants
  3. Includes an appropriate error message that follows the verifier's format ("3: Concrete invariants do not match abstract invariants")

Also applies to: 267-268


256-266: LGTM: Consistent post-conditions in negative test.

The post-conditions correctly reflect the actual final state of the program, not the incorrect invariants used for testing. This ensures the test verifies both the error detection and the correct program execution.

src/crab_verifier.cpp (6)

165-171: Implementation of pre-invariant storage is appropriate

The addition of saved_pre_invariants and the save_invariants_if_needed function correctly handles the storage of pre-invariants based on the store_pre_invariants option. This ensures that the pre-invariants are saved only when necessary, maintaining thread-local state appropriately.


184-184: Appropriate invocation of pre-invariant storage

The call to save_invariants_if_needed(pre_invariants); correctly saves the pre-invariants after running the forward analyzer in get_ebpf_report. This ensures that the pre-invariants are available for subsequent checks if required.


234-234: Consistent saving of pre-invariants in test analysis

The invocation of save_invariants_if_needed(pre_invariants); in ebpf_analyze_program_for_test maintains consistency in storing pre-invariants during test analysis, aligning with the behavior in the main analysis function.


281-283: Proper clearing of thread-local state

The assignment saved_pre_invariants = std::nullopt; in ebpf_verifier_clear_thread_local_state ensures that the thread-local pre-invariants are cleared appropriately, preventing potential state leakage between analyses.


284-328: Robust implementation of constraint checking function

The ebpf_check_constraints_at_label function is well-implemented:

  • Exception Handling: The use of a try-catch block ensures that exceptions thrown during the label construction or constraint processing are caught, and informative error messages are provided to the user.
  • Pre-invariant Availability Checks: It appropriately checks for the availability of pre-invariants before proceeding, providing clear messages if they are absent.
  • Constraint Validation: The function systematically validates the provided constraints against the stored pre-invariants, handling various edge cases such as unsatisfiable constraints or unreachable abstract states.
  • Informative Output: When the concrete state does not match the abstract invariant, the function outputs detailed information about both states, aiding in debugging.

330-341: Efficient retrieval of invariants at a label

The ebpf_get_invariants_at_label function effectively retrieves the pre-invariants for a given label:

  • Exception Propagation: By allowing exceptions from label_t construction to propagate, it ensures that invalid labels are handled by the caller, promoting safer usage patterns.
  • Pre-invariant Checks: It checks for the existence of pre-invariants before attempting to access them, returning an empty set if none are available.
  • Direct Conversion: The function converts the invariant to the desired set representation efficiently.
src/test/ebpf_yaml.cpp (6)

102-102: Good addition of invariants_to_check to RawTestCase

Including the invariants_to_check member enhances the ability to test invariants in the YAML test cases.


130-143: Proper parsing and exception handling in parse_invariants_to_check

The implementation correctly parses the invariants-to-check node and includes exception handling to manage parsing errors.


153-153: Correct integration of invariants_to_check in parse_case

The parse_case function appropriately initializes invariants_to_check, ensuring it is included in the test case.


230-232: Consistent handling of invariants_to_check in read_case

The read_case function correctly transfers invariants_to_check from the raw test case to the TestCase struct.


273-276: Appropriate setting of store_pre_invariants option

When invariants_to_check is not empty, setting store_pre_invariants ensures that pre-invariants are stored during analysis. This change is consistent with the intended functionality.


288-301: Proper exception handling in invariant checks

The try-catch block around ebpf_check_constraints_at_label effectively captures exceptions, preventing the test runner from crashing due to unhandled exceptions.

src/config.cpp Outdated Show resolved Hide resolved
src/asm_parse.hpp Outdated Show resolved Hide resolved
test-data/add.yaml Outdated Show resolved Hide resolved
src/asm_syntax.hpp Show resolved Hide resolved
@Alan-Jowett
Copy link
Contributor Author

@elazarg and @dthaler thanks for taking a look. Please let me know if there are additional changes this PR needs before we can merge?

I would like to start work on integrating this with bpf2c, which will be easier once this is merged. So far this approach has netted quite a few bugs and I see continued value in having this, not just for this case, but also for supporting callx in bpf2c.

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: 6

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 79b4c76 and 1cf5dad.

📒 Files selected for processing (5)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.cpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
🧰 Additional context used
📓 Learnings (3)
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
src/crab_verifier.hpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
🔇 Additional comments (8)
src/config.cpp (1)

17-19: LGTM! Well-documented configuration option.

The addition of .store_pre_invariants with a default value of false is well-implemented and thoroughly documented. The comment effectively explains both the purpose and performance implications of this option, which aligns perfectly with the PR objectives for implementing the ebpf_check_constraints_at_label API.

src/asm_parse.hpp (2)

6-6: LGTM: Includes are well-organized and necessary.

The new includes are properly ordered and required for the types used in parse_linear_constraints.

Also applies to: 9-10


26-27: LGTM: Function signature is well-designed.

The function signature:

  • Uses efficient parameter passing (const reference for input)
  • Separates concerns by extracting numeric ranges separately
  • Follows the single responsibility principle
src/crab_verifier.hpp (2)

30-52: LGTM! Well-documented function declaration.

The function declaration and documentation are thorough and well-structured. The documentation clearly explains:

  • Purpose and requirements
  • Abstract constraints concept
  • Error handling behavior
  • Parameter descriptions with proper qualifiers
  • Return value descriptions using @RetVal
  • Exception cases

53-66: LGTM! Well-documented function declaration.

The function declaration and documentation are clear and complete. The documentation effectively communicates:

  • Purpose and requirements
  • Behavior when store_pre_invariants is not set
  • Return value semantics including empty set case
  • Exception cases
src/asm_syntax.hpp (1)

39-60: LGTM! Implementation is correct and efficient.

The constructor correctly implements:

  • Efficient string handling with std::string_view
  • Proper parsing of stack frame prefix and label components
  • Appropriate error handling for invalid formats and out-of-range values
src/crab_verifier.cpp (2)

165-172: Refactor: Consolidate Invariant Saving Logic

The introduction of save_invariants_if_needed encapsulates the logic for saving pre-invariants based on the store_pre_invariants option. This promotes code reuse and adheres to the DRY (Don't Repeat Yourself) principle, improving maintainability.


284-330: ⚠️ Potential issue

Robustness: Handle Empty Optional in to_set()

In ebpf_check_constraints_at_label, when converting constraints into a concrete domain, the to_set() function may return an empty std::optional. Directly accessing .value() without checking could lead to exceptions if the optional is empty. To enhance robustness, consider verifying that to_set() has a value before accessing it.

Apply this diff to safely handle the optional:

         ebpf_domain_t from_inv(saved_pre_invariants.value().at(label));
         auto concrete_domain = ebpf_domain_t::from_constraints(constraints, false);

+        if (!concrete_domain.to_set().has_value()) {
+            os << "Failed to convert constraints into concrete domain\n";
+            return false;
+        }

         if (concrete_domain.is_bottom()) {
             os << "The provided constraints are unsatisfiable (concrete domain is bottom)\n";

Likely invalid or redundant comment.

src/asm_parse.hpp Show resolved Hide resolved
src/asm_syntax.hpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/crab_verifier.cpp 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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 1cf5dad and 24bbdea.

📒 Files selected for processing (3)
  • src/asm_syntax.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
🧰 Additional context used
📓 Learnings (3)
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:332-343
Timestamp: 2024-10-30T21:33:52.255Z
Learning: In `src/crab_verifier.cpp`, the `to_set()` function used in `ebpf_get_invariants_at_label` does not return an `std::optional`, so accessing `.value()` directly is correct.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
src/crab_verifier.hpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
🔇 Additional comments (8)
src/crab_verifier.hpp (1)

30-53: LGTM! Documentation and function declaration are well-structured.

The function declaration and its documentation are thorough, clear, and follow best practices. The documentation effectively covers all important aspects including requirements, behavior, error handling, and return values.

src/asm_syntax.hpp (2)

26-45: LGTM! Documentation is comprehensive and well-structured.

The documentation clearly explains the label format, includes relevant examples, and properly documents exceptions.


46-67: 🛠️ Refactor suggestion

Consider performance optimization for string parsing.

The implementation is correct and handles all cases properly, including the special case where "to" can be -1 for next instruction. However, there's a minor performance optimization opportunity.

Consider using std::from_chars instead of std::stoi to avoid string allocations:

         try {
             if (pos != std::string_view::npos) {
-                from = std::stoi(std::string(string_label.substr(0, pos)));
-                to = std::stoi(std::string(string_label.substr(pos + 1)));
+                auto from_sv = string_label.substr(0, pos);
+                auto [ptr_from, ec_from] = std::from_chars(from_sv.data(), from_sv.data() + from_sv.size(), from);
+                if (ec_from != std::errc())
+                    throw std::invalid_argument("Invalid 'from' value");
+                
+                auto to_sv = string_label.substr(pos + 1);
+                auto [ptr_to, ec_to] = std::from_chars(to_sv.data(), to_sv.data() + to_sv.size(), to);
+                if (ec_to != std::errc())
+                    throw std::invalid_argument("Invalid 'to' value");
             } else {
-                from = std::stoi(std::string(string_label));
-                to = -1;
+                auto [ptr, ec] = std::from_chars(string_label.data(), string_label.data() + string_label.size(), from);
+                if (ec != std::errc())
+                    throw std::invalid_argument("Invalid label value");
+                to = -1;
             }

Likely invalid or redundant comment.

src/crab_verifier.cpp (5)

19-19: Approved: Inclusion of required header file

Including "asm_parse.hpp" is appropriate here to access parsing functionalities needed for the code changes.


165-171: Appropriate use of thread-local storage for pre-invariants

The addition of saved_pre_invariants as a static thread_local variable ensures thread safety when storing pre-invariants. Utilizing std::optional appropriately handles cases where pre-invariants may not be available.


184-184: Consistent saving of pre-invariants across functions

Good job ensuring that pre-invariants are saved consistently by invoking save_invariants_if_needed in both get_ebpf_report and ebpf_analyze_program_for_test.

Also applies to: 234-234


281-282: Properly resetting thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that stale invariants do not persist between different verification runs, maintaining the correctness of analyses.


330-341: Confirmed: Exception handling aligns with design

Constructing label_t l = label_t(label); in ebpf_get_invariants_at_label may throw an exception for an invalid label. Since the function is designed to let exceptions propagate to the caller, and the behavior is documented in the header, this implementation is appropriate.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/crab_verifier.cpp 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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 24bbdea and dcaf502.

📒 Files selected for processing (8)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (1 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (7)
src/asm_parse.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:21-24
Timestamp: 2024-10-30T21:42:08.748Z
Learning: There are too many possible constraint formats to document them all in the examples.
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:332-343
Timestamp: 2024-10-30T21:33:52.255Z
Learning: In `src/crab_verifier.cpp`, the `to_set()` function used in `ebpf_get_invariants_at_label` does not return an `std::optional`, so accessing `.value()` directly is correct.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
src/crab_verifier.hpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (21)
src/asm_parse.hpp (1)

6-10: LGTM: Includes are well-organized and necessary.

The new includes are properly ordered (standard library before project headers) and directly support the new functionality.

src/test/ebpf_yaml.hpp (1)

17-17: Well-designed addition of invariants_to_check member!

The implementation demonstrates several good design choices:

  • Using map allows efficient lookup of invariants by label
  • Using set ensures uniqueness of invariants per label
  • Clear documentation explains both the structure and its purpose in test execution

The member fits well with the PR's objective of implementing label-specific constraint checking.

src/config.hpp (1)

41-42: LGTM: Well-documented configuration option for pre-invariant storage

The addition of store_pre_invariants with a default value of false is well-placed and properly documented. The opt-in nature ensures backward compatibility and memory efficiency.

Let's verify that this option is properly used in the mentioned functions:

✅ Verification successful

LGTM: The store_pre_invariants option is properly integrated and used

The option is well-integrated into the codebase:

  • Used in crab_verifier.cpp to conditionally store pre-invariants
  • Required by both ebpf_check_constraints_at_label and ebpf_get_invariants_at_label functions as documented
  • Properly tested in test/ebpf_yaml.cpp where it's enabled for testing constraints
  • Well-documented in crab_verifier.hpp with clear explanations of behavior when enabled/disabled
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of store_pre_invariants in the related functions

# Test: Search for references to store_pre_invariants
echo "Checking references to store_pre_invariants:"
rg "store_pre_invariants" -A 3

# Test: Search for the functions mentioned in the comment
echo "Checking implementation of the mentioned functions:"
rg "ebpf_check_constraints_at_label|ebpf_get_invariants_at_label" -A 3

Length of output: 3872

src/crab_verifier.hpp (2)

30-53: LGTM! Documentation and declaration are well-structured.

The function declaration and its documentation are thorough and align perfectly with the PR objectives. The documentation clearly explains:

  • The purpose and requirements
  • The concept of abstract constraints
  • All error cases and their handling
  • Parameter usage and return values

54-67: 🧹 Nitpick (assertive)

Improve exception documentation format for consistency.

The function is well-documented, but the exception documentation should follow a consistent format:

- * @throw std::invalid_argument The label format is invalid
- * @throw std::out_of_range The label value causes numeric overflow
+ * @throw std::invalid_argument If the label format is invalid
+ * @throw std::out_of_range If the label value causes numeric overflow

Likely invalid or redundant comment.

test-data/add.yaml (2)

180-222: LGTM: Well-structured test case with comprehensive invariants.

The test case effectively validates the concrete state at each execution step:

  1. Initial assignment of r1=1
  2. Assignment of r2=2
  3. Addition r1+=r2
  4. Final assignment r0=r1

The invariants and post-conditions correctly include both signed and unsigned values, which aligns with the verifier's requirements.


223-268: LGTM: Well-designed negative test case.

The test case effectively validates the error handling:

  1. Uses identical code to the positive test case
  2. Introduces a specific incorrect invariant at label 3
  3. Includes appropriate error message following the verifier's format

The comment on line 246 clearly explains the purpose of using the incorrect value, which aids in test maintenance.

src/asm_syntax.hpp (2)

26-45: LGTM! Well-structured and comprehensive documentation.

The documentation follows good practices with clear @tags, format specification, and illustrative examples.


46-67: LGTM! Implementation correctly handles all label formats.

The constructor implementation:

  • Efficiently uses std::string_view for string parsing
  • Correctly handles stack frame prefixes
  • Properly supports labels with "-1" as next instruction
  • Includes appropriate error handling for invalid formats and out-of-range values

Note: Based on the learnings from previous reviews, the implementation correctly supports labels in the form "from:-1" where "-1" signifies the next instruction.

src/crab_verifier.cpp (6)

166-172: Proper use of thread-local storage for saved_pre_invariants

Introducing saved_pre_invariants as a thread_local variable ensures thread safety and prevents data races in a multithreaded environment.


186-186: Effective use of helper function to save pre-invariants

Utilizing save_invariants_if_needed(pre_invariants); enhances code readability and maintainability by encapsulating the saving logic.


233-233: Consistent application of save_invariants_if_needed

Calling save_invariants_if_needed(pre_invariants); here maintains consistency across the codebase and ensures pre-invariants are stored when necessary.


276-277: Appropriate clearing of thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state effectively clears the thread-local state between verification runs.


279-323: ebpf_check_constraints_at_label function effectively validates constraints

The implementation correctly checks the provided constraints against the abstract invariants and handles exceptions appropriately, providing meaningful feedback to the user.


325-336: ebpf_get_invariants_at_label function retrieves invariants correctly

The function properly retrieves the invariants for a given label and handles cases where no invariants are available, returning an empty set as expected.

src/test/ebpf_yaml.cpp (6)

102-102: Addition of invariants_to_check member to RawTestCase

The addition of the invariants_to_check member to the RawTestCase struct is appropriate and integrates well with the existing data structure.


130-143: Proper parsing and exception handling in parse_invariants_to_check

The parse_invariants_to_check function correctly parses the invariants-to-check section from the YAML node and handles exceptions appropriately, ensuring robust and reliable YAML parsing.


153-153: Integrating invariants_to_check in parse_case

Including invariants_to_check in the parse_case function ensures that invariants are properly initialized during test case parsing, maintaining consistency throughout the test setup.


233-235: Extending TestCase with invariants_to_check

Adding invariants_to_check to the TestCase struct in read_case aligns it with the updated RawTestCase, ensuring that the test cases accurately reflect the specified invariants.


276-279: Conditional setting of store_pre_invariants

Setting test_case.options.store_pre_invariants = true only when invariants_to_check is not empty is appropriate, ensuring that pre-invariants are stored when necessary without affecting other test cases.


290-304: Iterating over invariants and handling exceptions

The loop over invariants_to_check correctly checks constraints at each label, and the exception handling ensures that any errors during invariant checks are gracefully managed, maintaining test robustness.

src/asm_parse.hpp Outdated Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
Copy link
Collaborator

@elazarg elazarg left a comment

Choose a reason for hiding this comment

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

Why store particular invariants, instead of using no-simplify?

What do you think about putting the assertions/concrete states right after each instruction?
Either

r1 = 1; r1.type=number, r1.svalue=1
r2 = 2;

Or

r1 = 1;
require [r1.type=number, r1.svalue=1]
r2 = 2;

Also (just an idea, probably not for this PR), tests may be simplified using a syntactic sugar that allow simply r1=1, and maybe r2=8s, r5=16p etc.

src/crab_verifier.hpp Outdated Show resolved Hide resolved
src/asm_parse.hpp 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: 5

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between dcaf502 and ff56cf7.

📒 Files selected for processing (2)
  • src/asm_parse.hpp (1 hunks)
  • src/crab_verifier.hpp (1 hunks)
🧰 Additional context used
📓 Learnings (2)
src/asm_parse.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:21-24
Timestamp: 2024-10-30T21:42:08.748Z
Learning: There are too many possible constraint formats to document them all in the examples.
src/crab_verifier.hpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
🔇 Additional comments (2)
src/asm_parse.hpp (2)

6-10: LGTM: Includes are properly organized.

The new includes are correctly ordered (STL before project headers) and all are necessary for the types used in the new function.


14-27: Verify integration with ebpf_check_constraints_at_label.

The function declaration aligns with the PR objectives. Let's verify its usage in the implementation.

✅ Verification successful

Function declaration aligns with implementation and usage

The verification confirms proper integration:

  • parse_linear_constraints is correctly implemented in asm_parse.cpp to parse string constraints into linear_constraint_t
  • It's used by ebpf_check_constraints_at_label through the ebpf_domain.cpp module which applies the parsed constraints
  • The function is properly tested in the YAML test suite for verifying concrete invariants
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the integration of parse_linear_constraints with ebpf_check_constraints_at_label

# Test: Search for usage of parse_linear_constraints in the implementation
rg -A 5 "parse_linear_constraints" src/crab_verifier.cpp

Length of output: 56


Script:

#!/bin/bash
# Let's broaden our search to find any references to parse_linear_constraints
rg "parse_linear_constraints" --type cpp

# Also search for files that might contain the implementation
fd "asm_parse" --type f

# Look for ebpf_check_constraints_at_label to understand the integration
rg "ebpf_check_constraints_at_label" --type cpp

Length of output: 1187


Script:

#!/bin/bash
# Let's examine the implementation of ebpf_check_constraints_at_label to see how it uses parse_linear_constraints
rg -A 10 "ebpf_check_constraints_at_label.*{" src/crab_verifier.cpp

# Also check the implementation of parse_linear_constraints
rg -A 10 "parse_linear_constraints.*{" src/asm_parse.cpp

# Check how it's used in ebpf_domain.cpp
rg -B 5 -A 5 "parse_linear_constraints" src/crab/ebpf_domain.cpp

Length of output: 869


Script:

#!/bin/bash
# Fix the regex syntax and try again
rg -A 10 "bool ebpf_check_constraints_at_label" src/crab_verifier.cpp

# Check the implementation in asm_parse.cpp
rg -A 10 "std::vector<.*> parse_linear_constraints" src/asm_parse.cpp

# Look at the test usage to understand the integration
rg -A 10 "ebpf_check_constraints_at_label" src/test/ebpf_yaml.cpp

Length of output: 1861

src/asm_parse.hpp Show resolved Hide resolved
src/crab_verifier.hpp Show resolved Hide resolved
src/crab_verifier.hpp Show resolved Hide resolved
src/crab_verifier.hpp 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: 8

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between ff56cf7 and ffb17ce.

📒 Files selected for processing (6)
  • src/asm_parse.cpp (4 hunks)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (3 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (5)
src/asm_parse.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:21-24
Timestamp: 2024-10-30T21:42:08.748Z
Learning: There are too many possible constraint formats to document them all in the examples.
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/test/ebpf_yaml.cpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: dthaler
PR: vbpf/ebpf-verifier#721
File: src/ebpf_yaml.cpp:327-329
Timestamp: 2024-10-11T20:51:53.396Z
Learning: In `src/ebpf_yaml.cpp`, avoid suggesting changes to error handling code in the `run_conformance_test_case` function if the code is not modified in the current PR.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/test/ebpf_yaml.cpp:280-291
Timestamp: 2024-10-25T15:33:32.202Z
Learning: In `src/test/ebpf_yaml.cpp`, error messages for invariant mismatches should be concise single-line messages, as the test authors already know the expected invariants. Detailed diagnostic messages are not necessary.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🪛 cppcheck
src/test/ebpf_yaml.cpp

[style] 129-129: The function 'parse_invariants_to_check' is never used.

(unusedFunction)

🔇 Additional comments (6)
src/asm_parse.hpp (2)

6-6: LGTM: New includes are properly ordered and necessary.

The added includes support the new linear constraints functionality and follow proper include ordering (STL before project headers).

Also applies to: 9-10


27-28: 🧹 Nitpick (assertive)

Fix function declaration indentation.

The function declaration is correct but needs consistent indentation.

 std::vector<crab::linear_constraint_t> parse_linear_constraints(const std::set<std::string>& constraints,
-                                                                std::vector<crab::interval_t>& numeric_ranges);
+                                                              std::vector<crab::interval_t>& numeric_ranges);

Likely invalid or redundant comment.

test-data/add.yaml (2)

180-204: LGTM: Well-structured test case with comprehensive validation.

The test case effectively validates the new API functionality with:

  • Clear pre-conditions initializing registers
  • Good intermediate state validation using require statements
  • Comprehensive post-conditions checking both signed and unsigned values

205-231: LGTM: Well-designed negative test case.

The test case effectively validates the error detection:

  • Introduces a subtle but effective error in the require statement
  • Uses the correct error message format
  • Maintains proper post-conditions to ensure the test framework continues to work correctly
src/asm_syntax.hpp (2)

452-454: LGTM! Clean formatting improvement.

The reformatting of the AssertionConstraint type improves readability while maintaining functionality.


46-67: 🧹 Nitpick (assertive)

Consider performance optimizations for string parsing.

The implementation is correct, but the string parsing could be more efficient:

  1. std::stoi creates temporary strings, which could be avoided using std::from_chars
  2. Modifying string_label in place makes the code harder to follow
 explicit label_t(std::string_view string_label) {
     auto pos = string_label.find(STACK_FRAME_DELIMITER);
+    std::string_view label_part = string_label;
     if (pos != std::string_view::npos) {
         stack_frame_prefix = std::string(string_label.substr(0, pos));
-        string_label = string_label.substr(pos + 1);
+        label_part = string_label.substr(pos + 1);
     }
 
-    pos = string_label.find(':');
+    pos = label_part.find(':');
     try {
         if (pos != std::string_view::npos) {
-            from = std::stoi(std::string(string_label.substr(0, pos)));
-            to = std::stoi(std::string(string_label.substr(pos + 1)));
+            auto [ptr_from, ec_from] = std::from_chars(label_part.data(), 
+                label_part.data() + pos, from);
+            if (ec_from != std::errc()) {
+                throw std::invalid_argument("Invalid label format: " + 
+                    std::string(string_label));
+            }
+            auto to_part = label_part.substr(pos + 1);
+            auto [ptr_to, ec_to] = std::from_chars(to_part.data(), 
+                to_part.data() + to_part.size(), to);
+            if (ec_to != std::errc()) {
+                throw std::invalid_argument("Invalid label format: " + 
+                    std::string(string_label));
+            }
         } else {
-            from = std::stoi(std::string(string_label));
+            auto [ptr, ec] = std::from_chars(label_part.data(), 
+                label_part.data() + label_part.size(), from);
+            if (ec != std::errc()) {
+                throw std::invalid_argument("Invalid label format: " + 
+                    std::string(string_label));
+            }
             to = -1;
         }
     } catch (...) {
         throw std::invalid_argument("Invalid label format: " + std::string(string_label));
     }
 }

Likely invalid or redundant comment.

src/asm_parse.hpp Show resolved Hide resolved
src/asm_parse.hpp Show resolved Hide resolved
src/test/ebpf_yaml.hpp Show resolved Hide resolved
src/asm_syntax.hpp Outdated Show resolved Hide resolved
src/asm_syntax.hpp Outdated Show resolved Hide resolved
src/asm_parse.cpp Show resolved Hide resolved
src/test/ebpf_yaml.cpp Outdated Show resolved Hide resolved
src/test/ebpf_yaml.cpp 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between ffb17ce and ae19fe9.

📒 Files selected for processing (9)
  • src/asm_parse.cpp (4 hunks)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (2 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (7)
src/asm_parse.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:21-24
Timestamp: 2024-10-30T21:42:08.748Z
Learning: There are too many possible constraint formats to document them all in the examples.
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
src/crab_verifier.hpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
src/test/ebpf_yaml.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
src/test/ebpf_yaml.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (22)
src/asm_parse.hpp (4)

6-6: LGTM: Required includes are properly organized.

The new includes are necessary for the added functionality and follow the standard include ordering convention.

Also applies to: 9-10


27-28: 🧹 Nitpick (assertive)

Fix indentation formatting.

The function declaration uses inconsistent spacing. Please adjust the indentation:

 std::vector<crab::linear_constraint_t> parse_linear_constraints(const std::set<std::string>& constraints,
-                                                                std::vector<crab::interval_t>& numeric_ranges);
+                                                              std::vector<crab::interval_t>& numeric_ranges);

Likely invalid or redundant comment.


15-26: 🧹 Nitpick (assertive)

Add error handling documentation.

The documentation is comprehensive, but should include information about possible error conditions.

 * @return A vector of crab::linear_constraint_t
+ * @throws std::invalid_argument If the constraints are malformed
+ * @throws std::runtime_error If parsing fails due to unsupported constraint format
 * Example of string constraints include:

Likely invalid or redundant comment.


12-13: 🧹 Nitpick (assertive)

Fix indentation while keeping the logical change.

The return type change to InstructionOrConstraintsSet aligns with the PR objectives. However, the indentation needs adjustment.

 InstructionOrConstraintsSet parse_instruction(const std::string& line,
-                                              const std::map<std::string, label_t>& label_name_to_label);
+                                            const std::map<std::string, label_t>& label_name_to_label);

Likely invalid or redundant comment.

src/test/ebpf_yaml.hpp (1)

17-17: 🧹 Nitpick (assertive)

Enhance documentation for the new member variable.

The addition of invariants_to_check aligns well with the PR objectives. However, it would benefit from comprehensive documentation that explains its role in the constraint checking feature.

Consider adding detailed documentation:

+    /// Stores constraints to be validated at specific labels during test execution.
+    /// Each constraint in this sequence is checked by ebpf_check_constraints_at_label
+    /// to verify that the concrete program state matches the expected abstract state.
+    /// This is used in conjunction with assumed_pre_invariant and expected_post_invariant
+    /// to provide comprehensive state validation throughout test execution.
     ConstraintsSeq invariants_to_check;

Likely invalid or redundant comment.

src/config.hpp (1)

41-42: LGTM: Well-documented configuration option for pre-invariant storage

The new option is properly initialized, well-documented, and correctly placed within the configuration structure. The comment clearly indicates its purpose and relationship with the new API functions.

src/crab_verifier.hpp (4)

29-67: LGTM! The new API functions are well-designed and documented.

The new functions ebpf_check_constraints_at_label and ebpf_get_invariants_at_label are well-designed and thoroughly documented. They successfully implement the requirements from issue #728, providing a robust API for comparing abstract and concrete states in the eBPF verifier.


66-67: 🧹 Nitpick (assertive)

Add newline before function declaration.

Add a newline between the documentation block and the function declaration for better readability.

 * @throw std::out_of_range The label value causes numeric overflow
 */
+
std::set<std::string> ebpf_get_invariants_at_label(const std::string& label);

Likely invalid or redundant comment.


64-65: 🧹 Nitpick (assertive)

Improve exception documentation format.

For consistency with standard practices, exception documentation should start with "If".

- * @throw std::invalid_argument The label format is invalid
- * @throw std::out_of_range The label value causes numeric overflow
+ * @throw std::invalid_argument If the label format is invalid
+ * @throw std::out_of_range If the label value causes numeric overflow

Likely invalid or redundant comment.


51-52: 🧹 Nitpick (assertive)

Add newline before function declaration.

Add a newline between the documentation block and the function declaration for better readability.

 * This can also return false if the label is not found in the CFG or if the label is malformed.
 */
+
bool ebpf_check_constraints_at_label(std::ostream& os, const std::string& label,
⛔ Skipped due to learnings
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
test-data/add.yaml (2)

180-204: LGTM: Well-structured test case with comprehensive state validation.

The test case effectively validates concrete state checking functionality with:

  • Clear pre-conditions initializing registers
  • Step-by-step validation using require statements
  • Comprehensive post-conditions including both signed and unsigned values

205-231: LGTM: Well-designed negative test case.

The test case effectively validates the verifier's ability to detect mismatches between concrete and abstract states:

  • Intentionally incorrect require statement at label 3
  • Appropriate error message format
  • Maintains consistent post-conditions with the positive test case
src/crab_verifier.cpp (4)

166-172: Initialization of saved_pre_invariants and Helper Function Looks Good

The introduction of the saved_pre_invariants thread-local variable and the save_invariants_if_needed function appropriately manages the storage of pre-invariants based on the verifier options.


276-278: Proper Reset of Thread-Local State in ebpf_verifier_clear_thread_local_state

Clearing saved_pre_invariants by setting it to std::nullopt ensures that the thread-local state is correctly reset, preventing potential stale data issues in subsequent analyses.


279-323: Implementation of ebpf_check_constraints_at_label is Well-Structured

The function effectively checks the provided constraints against the saved pre-invariants for a given label. Exception handling is properly implemented to catch and report errors without unexpected termination.


325-335: ebpf_get_invariants_at_label Correctly Retrieves Invariants

The function appropriately retrieves the invariants associated with a specified label. The decision to allow exceptions to propagate for malformed labels is acceptable given that it is documented and allows the caller to handle such cases.

src/asm_syntax.hpp (3)

26-45: Documentation for label_t constructor is clear and informative.

The added documentation for the label_t constructor thoroughly explains the label format, parameters, exceptions, and provides helpful examples. This enhances the code's readability and maintainability.


46-67: Robust implementation of label_t constructor.

The constructor correctly parses the label string, handling optional stack frame prefixes and jump targets. Exception handling for invalid formats and out-of-range values is appropriately implemented.


361-391: Well-implemented helper metafunctions.

The metafunctions append_to_variant, is_type_in_variant, and convert_to_original are correctly implemented, enhancing the code's modularity and facilitating variant type manipulations.

src/asm_parse.cpp (1)

139-140: Function parse_instruction updated to support constraints

The parse_instruction function's return type has been updated to InstructionOrConstraintsSet to handle both instructions and constraints, which aligns with the new requirement to parse require statements.

src/test/ebpf_yaml.cpp (2)

Line range hint 140-178: Implementation of raw_cfg_to_instruction_seq correctly handles constraints parsing

The updated raw_cfg_to_instruction_seq function now returns both the instruction sequence and the constraints sequence. The logic properly distinguishes between instructions and constraints using std::holds_alternative and processes them accordingly. This enhancement facilitates accurate parsing of constraints alongside instructions.


223-231: Integration of constraints into TestCase enhances test functionality

In the read_case function, the inclusion of invariants_to_check from instruction_seq_and_constraints into TestCase ensures that constraints are now part of the test case processing. This integration aligns with the objective of validating invariants during tests and improves the comprehensiveness of the testing framework.

src/asm_syntax.hpp Outdated Show resolved Hide resolved
src/asm_parse.cpp Outdated Show resolved Hide resolved
src/test/ebpf_yaml.cpp 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: 10

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between ae19fe9 and e3efb4b.

📒 Files selected for processing (9)
  • src/asm_parse.cpp (4 hunks)
  • src/asm_parse.hpp (1 hunks)
  • src/asm_syntax.hpp (2 hunks)
  • src/config.hpp (1 hunks)
  • src/crab_verifier.cpp (5 hunks)
  • src/crab_verifier.hpp (1 hunks)
  • src/test/ebpf_yaml.cpp (6 hunks)
  • src/test/ebpf_yaml.hpp (1 hunks)
  • test-data/add.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (7)
src/asm_parse.hpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:15-26
Timestamp: 2024-11-09T03:16:10.351Z
Learning: When reviewing `src/asm_parse.hpp`, do not suggest adding error handling documentation to the function `parse_linear_constraints`.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:27-28
Timestamp: 2024-11-09T03:14:02.608Z
Learning: In the ebpf-verifier project, the formatting guidelines permit using spaces for alignment in function declarations, such as in `parse_linear_constraints` in `src/asm_parse.hpp`.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_parse.hpp:21-24
Timestamp: 2024-10-30T21:42:08.748Z
Learning: There are too many possible constraint formats to document them all in the examples.
src/asm_syntax.hpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/asm_syntax.hpp:27-47
Timestamp: 2024-10-25T16:10:24.823Z
Learning: Labels can be in the form "from:-1", where "-1" signifies the next instruction, so validation checks must allow 'to' to be less than or equal to 'from'.
src/crab_verifier.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
src/crab_verifier.hpp (3)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:316-321
Timestamp: 2024-10-30T21:29:24.527Z
Learning: In the `ebpf_check_constraints_at_label` function in `src/crab_verifier.cpp`, avoid including the label in error messages since the caller already knows the label, making it redundant.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.hpp:44-51
Timestamp: 2024-10-16T05:00:24.900Z
Learning: In `src/crab_verifier.hpp`, adding usage examples to the documentation of `ebpf_get_invariants_at_label` is not necessary.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/crab_verifier.cpp:330-341
Timestamp: 2024-10-26T18:35:15.188Z
Learning: Before suggesting to document exception behavior in functions such as `ebpf_get_invariants_at_label`, check if the documentation already exists in the header files.
src/test/ebpf_yaml.cpp (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
src/test/ebpf_yaml.hpp (2)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/ebpf_yaml.hpp:17-17
Timestamp: 2024-10-16T04:59:56.598Z
Learning: Remember that the `invariants_to_check` member in `TestCase` is properly populated and used in the YAML parsing logic in `src/ebpf_yaml.cpp`.
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: src/test/ebpf_yaml.hpp:17-17
Timestamp: 2024-11-09T03:16:26.179Z
Learning: In `src/test/ebpf_yaml.hpp`, existing members of the `TestCase` struct are not documented, so it's acceptable to leave new members undocumented as well.
test-data/add.yaml (1)
Learnt from: Alan-Jowett
PR: vbpf/ebpf-verifier#729
File: test-data/add.yaml:213-215
Timestamp: 2024-10-26T18:30:31.364Z
Learning: In the eBPF verifier test cases (e.g., in `test-data/add.yaml`), include both `svalue` (signed value) and `uvalue` (unsigned value) assertions in the `post` conditions, as the verifier always emits both signed and unsigned invariants.
🔇 Additional comments (19)
src/asm_parse.hpp (3)

6-6: LGTM: Required includes added.

The new includes support the linear constraints functionality with appropriate types from the crab library.

Also applies to: 9-10


15-28: LGTM: Well-documented new function.

The parse_linear_constraints function is well-designed with:

  • Clear documentation of parameters and return value
  • Appropriate use of const references for efficiency
  • Relevant examples for register state validation

12-13: Verify callers of parse_instruction.

The return type change from Instruction to InstructionOrConstraintsSet looks good and aligns with the PR objectives. Let's verify all callers have been updated.

✅ Verification successful

Based on the search results, I can generate the final response as I have sufficient information to verify the impact of the return type change.

Return type change is properly handled by all callers

All callers of parse_instruction have been updated to handle the new InstructionOrConstraintsSet return type:

  • In src/test/ebpf_yaml.cpp: Properly checks variant type and handles both constraint sets and instructions
  • In src/asm_parse.cpp: Correctly handles the new return type in the internal usage
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all callers of parse_instruction to verify they handle the new return type
rg -l "parse_instruction\(" | xargs rg -A 5 "parse_instruction\("

Length of output: 2212

src/test/ebpf_yaml.hpp (1)

17-17: LGTM! Verify integration with constraint checking functionality.

The addition of invariants_to_check aligns well with the PR objectives for implementing label-specific constraint validation.

Let's verify the integration with the constraint checking functionality:

✅ Verification successful

Integration with constraint checking functionality verified

The invariants_to_check member is properly integrated with the constraint checking functionality:

  • It's populated during YAML parsing in raw_cfg_to_instruction_seq
  • It's used in run_yaml_test_case with ebpf_check_constraints_at_label to verify constraints at specific labels
  • The implementation handles both successful verification and error cases appropriately
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that invariants_to_check is properly used with ebpf_check_constraints_at_label

# Test 1: Check if the new member is properly populated in YAML parsing
rg -A 5 "invariants_to_check" src/ebpf_yaml.cpp

# Test 2: Check if it's used with ebpf_check_constraints_at_label
ast-grep --pattern 'ebpf_check_constraints_at_label($_)'

# Test 3: Look for test cases using this functionality
fd -e yaml . test-data --exec rg -l "invariants:"

Length of output: 214


Script:

#!/bin/bash
# Let's try different approaches to verify the integration

# Check for files containing ebpf_yaml
fd "ebpf.*yaml" src/

# Look for any YAML test files in the repository
fd -e yaml .

# Search for files containing ConstraintsSeq
rg "ConstraintsSeq"

# Search for files containing "invariants" or "constraints" in test files
fd -e cpp -e hpp "test" --exec rg -l "invariants|constraints" {}

Length of output: 1058


Script:

#!/bin/bash
# Let's examine the implementation in ebpf_yaml.cpp and related files

# Check the implementation in ebpf_yaml.cpp
cat src/test/ebpf_yaml.cpp

# Look for the definition and usage of LabeledConstraints
rg -A 5 "struct.*LabeledConstraints" 

# Check for constraint-related functions in the test files
rg -A 10 "ebpf_check_constraints|parse_constraints" src/test/

Length of output: 19050

src/config.hpp (1)

41-42: LGTM: Well-placed option with safe default value

The addition of store_pre_invariants with a default value of false is appropriate and aligns with the PR objectives for comparing abstract and concrete states.

test-data/add.yaml (2)

180-204: LGTM: Well-structured test case with comprehensive state validation.

The test case effectively validates the new API function by:

  • Initializing registers to known values
  • Using require statements to validate intermediate states
  • Including both signed and unsigned values in post-conditions

205-231: LGTM: Well-designed negative test case.

The test case effectively validates error handling by:

  • Using the same initial setup as the positive test case
  • Intentionally introducing an incorrect value in the require statement
  • Including the appropriate error message format
src/crab_verifier.cpp (4)

166-172: Implementation of save_invariants_if_needed is appropriate

The save_invariants_if_needed function correctly encapsulates the logic for conditionally saving pre-invariants based on the store_pre_invariants option. This enhances code maintainability by reducing duplication.


186-186: Consistent use of save_invariants_if_needed

Calling save_invariants_if_needed(pre_invariants); ensures that pre-invariants are stored when necessary, maintaining consistency across different functions.


233-233: Consistent use of save_invariants_if_needed

The invocation of save_invariants_if_needed(pre_invariants); here aligns with its usage in other parts of the code, promoting uniform handling of pre-invariants.


276-278: Properly clearing thread-local state

Resetting saved_pre_invariants to std::nullopt in ebpf_verifier_clear_thread_local_state ensures that thread-local data does not persist between different verification runs, preventing potential state leakage between threads.

src/asm_syntax.hpp (3)

26-45: Well-documented label_t constructor

The added documentation for the label_t constructor is clear and provides useful information on the expected string format and examples. This will aid users in understanding how to instantiate label_t objects from strings.


46-67: Constructor implementation correctly handles label parsing

The implementation of the label_t constructor accurately parses the string label, including optional stack frame prefixes and from:to formats. The error handling appropriately throws exceptions for invalid inputs, ensuring robustness.


396-402: New type definitions integrate well with existing structures

The addition of ConstraintsSet, InstructionOrConstraintsSet, LabeledConstraints, ConstraintsSeq, and InstructionAndConstraintsSeq is well-defined and enhances the flexibility of the codebase. These types seamlessly integrate constraints handling with instruction sequences.

src/asm_parse.cpp (1)

235-235: Trim leading and trailing whitespaces from constraints

After splitting the constraints string, individual constraints may contain leading or trailing whitespaces. Trimming them before inserting into constraint_set ensures accurate matching and avoids potential parsing issues.

src/test/ebpf_yaml.cpp (4)

Line range hint 140-178: Correctly parse and separate instructions and constraints

The implementation of raw_cfg_to_instruction_seq effectively parses raw blocks into an instruction sequence and captures constraints separately. The handling of InstructionOrConstraintsSet and the separation of constraints from instructions enhance the functionality and maintainability of the code.


222-231: Proper integration of constraints into TestCase structure

The read_case function appropriately updates the TestCase struct to include the invariants_to_check member. This ensures that constraints are correctly passed through for later verification, maintaining the consistency and integrity of test cases.


272-275: Conditional enabling of pre-invariant storage

Setting test_case.options.store_pre_invariants = true when invariants_to_check is not empty is appropriate. This condition ensures that pre-invariants are stored only when necessary, preventing unnecessary overhead and maintaining the efficiency of the test execution.


286-303: Verification loop with robust exception handling

The loop over test_case.invariants_to_check correctly verifies invariants at each label. Exception handling is effectively implemented to catch and handle any errors during the invariant checks without crashing the test runner. This approach aligns with the practice of providing concise error messages, as previously discussed.

src/config.hpp Show resolved Hide resolved
src/crab_verifier.hpp Show resolved Hide resolved
src/crab_verifier.hpp Show resolved Hide resolved
test-data/add.yaml Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/crab_verifier.cpp Show resolved Hide resolved
src/asm_syntax.hpp Show resolved Hide resolved
src/asm_parse.cpp Outdated Show resolved Hide resolved
src/asm_parse.cpp Outdated Show resolved Hide resolved
src/asm_parse.cpp Show resolved Hide resolved
Signed-off-by: Alan Jowett <[email protected]>
code:
<start>: |
r1 = 1
require [r1.type=number, r1.svalue=1, r1.uvalue=r1.svalue]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe the intention is to allow these numbers, not require, so maybe my suggestion was not the right terminology. Maybe it should be "require allow ..."? There must be a better term.

Comment on lines +139 to +140
InstructionOrConstraintsSet parse_instruction(const std::string& line,
const std::map<std::string, label_t>& label_name_to_label) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's better to add an instruction (assertion) of the kind you want. Then do the check from inside ebpf_checker like any other check.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And I think it's better to do it after #787

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal is to allow an external party to provide concrete state at a label and to then compare that concrete state to the abstract state for that label.

I.e. if verifier believes:
At label 4:-1 -> "r0.uvalue=0"

But execution of the BPF program results in:
At label 4:-1 -> "r0.uvalue=1"

Then this is a bug, in the VM (or possibly the verifier). This is what I am using the ebpf_check_constraints_at_label for and it has been hugely successful in finding bugs (much more than simply comparing the post-conditions after the program executes).

I am fine redoing this work once the code re-org is complete, but the goal here is to be able to reason about the program state post verification (i.e. when the program is actually executing).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure I understand the scenario. Does it happen online or offline? Do you want to query the final result of the computation during the execution of the program?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. The BPF VM is single stepped through the instructions. After each instruction, a series of assertions is generated from the concrete state of the VM and checked against the abstract state at that label.

Divergence between the two signifies that either the VM is wrong or the verifier is wrong.

The majority of the verifier bugs I have been filing have been found using this technique (using BPF programs generated by specdif or libfuzzer).

@elazarg
Copy link
Collaborator

elazarg commented Nov 9, 2024

@Alan-Jowett I'm putting this on hold, until the work on restructuring ebpf_domain and the transformer/checker is finished. Then you may add dedicated user assertions. There's going to be a lot of conflicts, so I think it's better re-opened aftewards instead of maintaining mergeability.

@elazarg
Copy link
Collaborator

elazarg commented Nov 24, 2024

@Alan-Jowett I think this can now be implemented it using is_valid_after() or ebpf_domain_transform() and Invariants::is_valid_after().

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.

Expose API to compare abstract state to concrete state
4 participants