-
Notifications
You must be signed in to change notification settings - Fork 43
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
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe 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 Changes
Assessment against linked issues
Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🧰 Additional context used📓 Learnings (2)src/asm_parse.cpp (1)
test-data/add.yaml (1)
🔇 Additional comments (6)test-data/add.yaml (3)
The test case follows the established pattern with clear initialization of registers to zero.
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.
The test case effectively validates the constraint checking functionality by:
src/asm_parse.cpp (3)
The regex pattern is well-structured with non-greedy matching and proper whitespace handling.
Enhance error handling for unexpected variant types. When 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});
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 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);
}
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
📒 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 optionWhile the addition of
store_pre_invariants
is correct, we should ensure its proper integration:
- Verify that
ebpf_verifier_default_options
(declared at the end of this file) is updated to include a default value forstore_pre_invariants
.- 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 commentsrc/crab_verifier.cpp (2)
287-287
: Validate label string before constructinglabel_t
The construction of
label_t label(label_string);
assumes thatlabel_string
is a valid label. Consider adding validation to ensure thatlabel_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 appropriatelyIf 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 trueSetting
test_case.options.store_pre_invariants
totrue
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.
There was a problem hiding this 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
📒 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 documentationThe addition of
bool store_pre_invariants;
to theebpf_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
: LGTMThe addition of the
invariants_to_check
member toRawTestCase
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 implementedThe 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
inRawTestCase
is correctly initialized using theparse_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 fromraw_case
to the newTestCase
, 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
totrue
ensures that pre-invariants are stored. This is necessary for checking invariants at specific labels during the test case execution.
8a8a8fd
to
73a9473
Compare
The PR was rebased. @coderabbitai full review |
@Alan-Jowett: Understood, I will perform a full review of the updated PR. ✅ Actions performedFull review triggered. |
There was a problem hiding this 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
📒 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 documentationThe addition of
bool store_pre_invariants;
to theebpf_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 theTestCase
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
andstd::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 handlingThe new
label_t
constructor correctly parses the inputstd::string_view
to initializefrom
,to
, andstack_frame_prefix
. Exception handling forstd::invalid_argument
andstd::out_of_range
is properly implemented, ensuring robustness against invalid inputs.src/crab_verifier.cpp (1)
165-166
: Confirm thread-local storage usage forsave_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 tosave_pre_invariants
are thread-safe and that its use aligns with the intended concurrency model.src/ebpf_yaml.cpp (1)
130-142
: Functionparse_invariants_to_check
handles YAML parsing correctlyThe
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.
There was a problem hiding this 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
📒 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 ofstore_pre_invariants
optionThe new
store_pre_invariants
boolean member has been added to theebpf_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 theTestCase
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' headerThe 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 tostd::nullopt
. This variable is used to store pre-invariants when thestore_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 storingpre_invariants
insave_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 storespre_invariants
insave_pre_invariants
whenstore_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
tostd::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' functionThe 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' functionThe 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' StructureThe new member
invariants_to_check
is appropriately added to theRawTestCase
struct to store invariants for testing purposes.
151-151
: Initializing 'invariants_to_check' in 'parse_case' FunctionThe
parse_case
function correctly initializes theinvariants_to_check
member by invokingparse_invariants_to_check(case_node)
.
223-225
: Transferring 'invariants_to_check' to 'TestCase'The
read_case
function appropriately transfers theinvariants_to_check
member fromRawTestCase
toTestCase
, ensuring that the invariants are available for test execution.
266-269
: Setting 'store_pre_invariants' Based on Invariants to CheckThe logic correctly sets
test_case.options.store_pre_invariants
totrue
whentest_case.invariants_to_check
is not empty, enabling the storage of pre-invariants necessary for invariant checks.
There was a problem hiding this 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
📒 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
andebpf_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 commentsrc/crab_verifier.cpp (6)
165-172
: Modularize invariant saving logic for maintainabilityThe 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 consistentlyBy 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 functionThe 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 stateResetting
saved_pre_invariants
tostd::nullopt
inebpf_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 checkingThe
ebpf_check_constraints_at_label
function is wrapped in atry-catch
block to handle exceptions derived fromstd::exception
. This ensures that any errors during constraint checking are caught and reported gracefully.
330-341
: Intentional exception propagation for label parsingIn
ebpf_get_invariants_at_label
, constructinglabel_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 intendedSetting
test_case.options.store_pre_invariants
totrue
wheninvariants_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
ConfirmedAfter 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
@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. |
fb3e0ea
to
8dd5ac7
Compare
There was a problem hiding this 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
📒 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
, andcrab/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 documentationThe addition of
bool store_pre_invariants;
to theebpf_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 constructorThe new
label_t
constructor effectively parses the string label and initializes thefrom
,to
, andstack_frame_prefix
members. Exception handling is appropriately included for invalid inputs.src/crab_verifier.cpp (6)
20-20
: Include Statement Added AppropriatelyThe inclusion of
"asm_parse.hpp"
is necessary for exposing the function for parsing linear constraints and is correctly added.
165-172
: Refactored Code Enhances MaintainabilityThe introduction of
saved_pre_invariants
and the helper functionsave_invariants_if_needed
improves code modularity and adheres to the DRY principle, enhancing maintainability.
184-184
: Correct Usage of Helper Function inget_ebpf_report
The call to
save_invariants_if_needed(pre_invariants);
correctly stores pre-invariants when thestore_pre_invariants
option is enabled.
234-234
: Appropriate Invocation of Helper Function in TestingThe use of
save_invariants_if_needed(pre_invariants);
inebpf_analyze_program_for_test
ensures that pre-invariants are stored as needed during testing.
281-282
: Thread-Local State Reset ProperlyResetting
saved_pre_invariants
tostd::nullopt
inebpf_verifier_clear_thread_local_state
ensures that the thread-local state is cleared correctly.
284-328
:ebpf_check_constraints_at_label
Implemented EffectivelyThe 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 ofinvariants_to_check
inRawTestCase
The new member
invariants_to_check
has been added to theRawTestCase
struct. Verify that this member is properly initialized in all instances to prevent potential uninitialized member usage.
151-151
: Confirm correct assignment ofinvariants_to_check
inparse_case
In the
parse_case
function, ensure that the assignment ofinvariants_to_check
correctly populates theRawTestCase
structure. This guarantees that all invariants are accurately captured for the test cases.
223-225
: Verify accurate transfer ofinvariants_to_check
toTestCase
inread_case
The
invariants_to_check
member fromRawTestCase
is assigned toTestCase
. Ensure that this transfer preserves all the invariants without any data loss or corruption.
There was a problem hiding this 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
📒 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-integratedThe 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 3Length 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.cppLength of output: 1279
src/config.hpp (1)
24-25
: LGTM: Well-documented configuration option for pre-invariant storageThe 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:
- Checking constraints at multiple labels (1, 2, 3, -2)
- Verifying both register types and values
- 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 commentsrc/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
: Includeasm_parse.hpp
for constraint parsingThe 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-localsaved_pre_invariants
Declaring
saved_pre_invariants
as athread_local
std::optional
ensures thread safety and correct initialization for storing pre-invariants.
167-171
: Good use of helper functionsave_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 ofsave_invariants_if_needed
Using
save_invariants_if_needed
in bothget_ebpf_report
andebpf_analyze_program_for_test
ensures pre-invariants are stored when needed, promoting code reuse.Also applies to: 234-234
281-282
: Resettingsaved_pre_invariants
in thread-local stateProperly resetting
saved_pre_invariants
tostd::nullopt
prevents stale data from persisting across analyses, ensuring accurate results.
284-328
: Robust error handling inebpf_check_constraints_at_label
The function provides comprehensive error messages and uses a
try-catch
block to handle exceptions derived fromstd::exception
, enhancing reliability and user feedback.
330-341
: Intentional exception propagation inebpf_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 theRawTestCase
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 theparse_case
function ensures that invariants are parsed and included in the test cases.
225-227
: LGTM!Assigning
invariants_to_check
to theTestCase
object inread_case
appropriately passes the invariants to the test execution.
268-271
: LGTM!Conditionally setting
store_pre_invariants
based oninvariants_to_check
is appropriate and ensures that pre-invariants are stored only when needed.
There was a problem hiding this 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
📒 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 ofinvariants_to_check
member toRawTestCase
The new member
invariants_to_check
is appropriately added to theRawTestCase
struct to store invariants from the YAML configuration.
130-143
: Proper parsing and error handling inparse_invariants_to_check
The function
parse_invariants_to_check
correctly processes theinvariants-to-check
YAML node and handles exceptions by throwing astd::runtime_error
with a meaningful message.
153-153
: Integration ofinvariants_to_check
inparse_case
functionThe
invariants_to_check
member is properly initialized in theparse_case
function by callingparse_invariants_to_check(case_node)
.
225-227
: Passinginvariants_to_check
toTestCase
The
invariants_to_check
member is correctly assigned fromraw_case
toTestCase
in theread_case
function, ensuring the invariants are available for testing.
268-271
: Conditional setting ofstore_pre_invariants
By setting
test_case.options.store_pre_invariants = true
only wheninvariants_to_check
is not empty, you ensure pre-invariants are stored only when necessary, avoiding unintended side effects.
282-295
: Invariant checks with exception handlingThe loop over
test_case.invariants_to_check
correctly callsebpf_check_constraints_at_label
for each invariant and handles exceptions appropriately. This ensures that any discrepancies or exceptions are captured inactual_messages
, maintaining test robustness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this 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
📒 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
There was a problem hiding this 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
📒 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 3Length 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 initializedThe 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 15Length 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:
- The positive test case verifies correct constraint checking at each execution step.
- 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 commentsrc/crab_verifier.cpp (3)
165-171
: Good use of a helper function to avoid code duplicationThe 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 stateResetting
saved_pre_invariants
tostd::nullopt
inebpf_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 inebpf_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 ofinvariants_to_check
memberThe new member
invariants_to_check
is correctly added to theRawTestCase
struct, enhancing the test case's ability to handle invariants.
130-143
: Correct implementation ofparse_invariants_to_check
functionThe
parse_invariants_to_check
function effectively parses theinvariants-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 inparse_case
functionThe
invariants_to_check
member is properly initialized usingparse_invariants_to_check(case_node)
within theparse_case
function, ensuring that invariants are correctly parsed and stored for each test case.
230-232
: Correct assignment inread_case
functionThe assignment of
invariants_to_check
fromraw_case
totest_case
in theread_case
function is accurate, maintaining the integrity of the test case data throughout the parsing process.
273-276
: Appropriate conditional setting ofstore_pre_invariants
The condition to set
test_case.options.store_pre_invariants = true
wheninvariants_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 handlingThe 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.
58bbb34
to
75fdf33
Compare
There was a problem hiding this 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
📒 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 parametercrab/interval.hpp
andcrab/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:
- Maintaining identical setup and execution as the positive test case
- Introducing a specific, well-documented invariant mismatch at label 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.
There was a problem hiding this 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
📒 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:
- Initializes all registers to zero
- Performs a sequence of basic operations (assignment and addition)
- 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:
- Uses the same initial setup as the positive test
- Introduces an intentional mismatch in the invariants
- 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.
@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. |
There was a problem hiding this 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
📒 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
:
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.
There was a problem hiding this 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
📒 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.
There was a problem hiding this 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
📒 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
andebpf_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:
- Initial assignment of r1=1
- Assignment of r2=2
- Addition r1+=r2
- 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:
- Uses identical code to the positive test case
- Introduces a specific incorrect invariant at label 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.
There was a problem hiding this 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.
There was a problem hiding this 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
📒 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 inasm_parse.cpp
to parse string constraints intolinear_constraint_t
- It's used by
ebpf_check_constraints_at_label
through theebpf_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
There was a problem hiding this 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
📒 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:
std::stoi
creates temporary strings, which could be avoided usingstd::from_chars
- 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.
There was a problem hiding this 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
📒 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.
Signed-off-by: Alan Jowett <[email protected]>
There was a problem hiding this 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
📒 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
withebpf_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.
Signed-off-by: Alan Jowett <[email protected]>
code: | ||
<start>: | | ||
r1 = 1 | ||
require [r1.type=number, r1.svalue=1, r1.uvalue=r1.svalue] |
There was a problem hiding this comment.
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.
InstructionOrConstraintsSet parse_instruction(const std::string& line, | ||
const std::map<std::string, label_t>& label_name_to_label) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
@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. |
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:
src/asm_parse.hpp
: Exposed existing function to parse linear constraints.src/asm_syntax.hpp
: Extended thelabel_t
struct to support initialization from a string label.src/config.hpp
: Added a new option to store pre-invariants in the verifier options.src/crab_verifier.cpp
: Implemented functions to store pre-invariants and check constraints at specific labels. [1] [2] [3] [4]src/crab_verifier.hpp
: Declared the new function for checking constraints at a label.Test Case Updates:
src/ebpf_yaml.cpp
: Updated YAML parsing to include invariants to check and modified test case execution to validate these invariants. [1] [2] [3] [4] [5]src/ebpf_yaml.hpp
: Added a new field to theTestCase
struct for invariants to check.test-data/add.yaml
: Added a new test case to check concrete state invariants.Summary by CodeRabbit
Release Notes
New Features
label_t
.store_pre_invariants
for managing pre-invariant states during verification.Bug Fixes
Tests
Documentation