-
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
Minor updates to move the code to more const-correct #756
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request introduces various modifications across multiple files, primarily focusing on enhancing code clarity and safety through the use of Changes
Possibly related PRs
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.
CLI11 is not part of this project.
Thanks for the PR! Just fix the minor comments, and remember to sign-off your commits ( |
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
🧹 Outside diff range comments (3)
src/crab_utils/stats.cpp (1)
Line range hint
33-81
: Well-structured const-correctness improvementsThe changes consistently apply const-correctness throughout the file, improving code safety and clarity. The modifications follow a systematic approach:
- Method-level const qualifiers where appropriate
- Local variables marked const when they shouldn't be modified
- Consistent application across similar patterns
This enhances maintainability by making immutability guarantees explicit.
src/crab/add_bottom.hpp (1)
Line range hint
1-248
: Consider additional const-correctness improvements across the class.The codebase demonstrates good const-correctness practices, but there are opportunities for further improvements:
- Consider adding const overloads for operators where appropriate
- Review assignment operations for potential const-qualification of internal operations
This would further align with the PR's objective of enhancing const-correctness across the codebase.
src/crab_utils/adapt_sgraph.hpp (1)
Line range hint
1-516
: Consider additional improvements to const-correctness and exception specifications.While the current changes improve const-correctness, there are additional opportunities for enhancement:
- Consider marking more member variables as const where appropriate
- Consider adding noexcept specifications to methods that don't throw exceptions
- Consider simplifying the empty iterator pattern using std::optional
Example improvements:
// Add noexcept to methods that don't throw [[nodiscard]] bool is_empty() const noexcept { return edge_count == 0; } // Mark member variables const where appropriate class edge_const_iter { const smap_t::elt_iter_t it; const std::vector<Weight>* const ws; // ... };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
📒 Files selected for processing (10)
- src/asm_ostream.cpp (1 hunks)
- src/assertions.cpp (3 hunks)
- src/crab/add_bottom.hpp (1 hunks)
- src/crab/interval.hpp (1 hunks)
- src/crab/linear_expression.hpp (2 hunks)
- src/crab_utils/adapt_sgraph.hpp (2 hunks)
- src/crab_utils/stats.cpp (2 hunks)
- src/crab_utils/stats.hpp (1 hunks)
- src/main/memsize_windows.hpp (1 hunks)
- src/main/utils.hpp (1 hunks)
🔇 Additional comments (12)
src/main/utils.hpp (1)
6-6
: LGTM! Good const-correctness improvements.The addition of
const
qualifiers tobegin
andend
clock variables is a good practice as these values should not be modified after initialization. This change enhances code safety while maintaining the original functionality.Also applies to: 10-10
src/main/memsize_windows.hpp (1)
12-12
: LGTM! Good const-correctness improvement.The addition of
const
to theok
variable is appropriate as the value is only assigned once and used as a read-only flag in the ternary operation. This change improves code safety while maintaining the original functionality.src/crab_utils/stats.hpp (1)
27-27
: LGTM! Appropriate const qualification added.The change to make
toSeconds()
const-qualified is correct and consistent with the method's likely behavior of only reading class state, similar to other const methods likegetTimeElapsed()
andPrint()
.Let's verify the implementation is consistent:
✅ Verification successful
Const-correctness implementation verified and correct
The implementation in
src/crab_utils/stats.cpp
perfectly matches the const declaration. The method only performs a read-only calculation using another const methodgetTimeElapsed()
and returns the result, with no state modification.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the toSeconds implementation in cpp file matches the const declaration # Test: Search for the toSeconds implementation ast-grep --pattern 'double Stopwatch::toSeconds() const { $$$ }'Length of output: 68
Script:
#!/bin/bash # Let's try a broader search to find the implementation file and verify the const-correctness # First, find the implementation file fd "stats.cpp" # Then search for toSeconds implementation with ripgrep for more flexibility rg "Stopwatch::toSeconds" -A 5Length of output: 389
src/crab_utils/stats.cpp (2)
33-35
: LGTM: Appropriate const qualifier additionThe const qualifier for
total_us
is a good addition as it clearly indicates the value should not be modified after calculation.
81-81
: LGTM: Appropriate const qualifier additionThe const qualifier for the
time
variable is correct as it's used only for calculations and should not be modified after initialization.src/crab/linear_expression.hpp (2)
28-28
: LGTM: Appropriate const-qualification of iteratorThe addition of
const
to the iterator is correct as it's used only for lookup operations within a const method.
158-158
: LGTM: Proper const-qualification of constant termThe addition of
const
to theconstant
variable is appropriate as it's only used for comparison and output operations.src/assertions.cpp (2)
45-45
: LGTM: Improved const-correctnessThe change to accept
IncrementLoopCounter
by const reference aligns with the PR's objective and follows good C++ practices by avoiding unnecessary copying.
172-173
: Verify the intentional behavior change in stack pointer offset checkThe condition change from
offset + static_cast<int>(width.v) > 0
to>= 0
makes the check more strict by including zero as an invalid offset. This appears to be a behavioral change that goes beyond the PR's stated objective of "const-correctness" improvements.Please confirm if this change is intentional and if it has been properly tested with existing eBPF programs.
Let's verify the impact:
src/crab_utils/adapt_sgraph.hpp (2)
5-5
: LGTM: Explicit header inclusion for assert statements.Good practice to explicitly include the
<cassert>
header as it's used throughout the code.
Line range hint
420-424
: LGTM: Enhanced const-correctness in lookup method.The change to make
idx
const-qualified is a good improvement that aligns with const-correctness principles without affecting the behavior.src/crab/interval.hpp (1)
178-179
: LGTM! The const qualifiers enhance code safety.The addition of
const
qualifiers tolb
andub
variables is appropriate since these values are not modified after initialization. This change:
- Aligns with the PR's const-correctness objectives
- Follows C++ best practices
- Addresses the previous review suggestions
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
🧹 Outside diff range comments (5)
src/crab_utils/stats.hpp (1)
Line range hint
27-64
: Consider documenting thread safety guaranteesWhile the const-correctness improvements are good, it would be helpful to document the thread safety guarantees of these classes, especially given the use of
thread_local
storage. This would help users of these classes understand any synchronization requirements.Consider adding documentation comments that specify:
- Thread safety guarantees for each class
- Any synchronization requirements when accessing stats across threads
- Lifetime management of the thread_local storage
src/crab/fwd_analyzer.cpp (1)
Line range hint
89-91
: Consider marking accessor methods as const.Since these methods only read from member variables without modifying state, they should be marked as const:
- ebpf_domain_t get_pre(const label_t& node) { return _pre.at(node); } + ebpf_domain_t get_pre(const label_t& node) const { return _pre.at(node); } - ebpf_domain_t get_post(const label_t& node) { return _post.at(node); } + ebpf_domain_t get_post(const label_t& node) const { return _post.at(node); }src/crab/split_dbm.hpp (1)
Inconsistent const-correctness found in related class
The verification revealed an inconsistency in
src/crab/add_bottom.hpp
where a similarassign
method is using pass-by-value for the optional parameter. This should also be updated to use const reference for consistency:
src/crab/add_bottom.hpp
: Changevoid assign(std::optional<variable_t> x, ...)
tovoid assign(const std::optional<variable_t>& x, ...)
🔗 Analysis chain
Line range hint
229-233
: LGTM! Good const-correctness improvement.The change to accept
const std::optional<variable_t>&
instead ofstd::optional<variable_t>
is a good improvement that:
- Aligns with the PR's const-correctness objectives
- Avoids unnecessary copying of the optional parameter
- Follows modern C++ best practices
Let's verify that there are no call sites relying on implicit conversions:
Let me analyze the search results:
Direct calls with
std::optional
:
- Found one occurrence in
src/crab/add_bottom.hpp
that uses pass-by-value, which is the old style.Potential implicit conversions:
- Most matches are unrelated (different
assign
functions)- The relevant calls in
src/crab/split_dbm.cpp
and related files use direct variable access or explicitstd::optional
constructionLet's verify the implementation in
add_bottom.hpp
to ensure consistency:🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for direct calls to assign with std::optional rg "assign\s*\(\s*std::optional" # Search for potential implicit conversions to std::optional rg "assign\s*\(\s*[^s][^t][^d].*\)" --type cppLength of output: 8874
Script:
#!/bin/bash # Get the context of the assign method in add_bottom.hpp rg -A 5 "void assign.*std::optional.*variable_t.*" src/crab/add_bottom.hppLength of output: 214
src/crab/wto.cpp (1)
Line range hint
1-286
: Consider addressing these const-correctness opportunities.While reviewing the file, I noticed several opportunities to improve const-correctness that would better align with the PR's objectives:
- The
print_visitor
class methods could be marked as const:- void operator()(const label_t& label) { o << label; } + void operator()(const label_t& label) const { o << label; }
- The
wto_builder_t
private methods could specify const for parameters that aren't modified:- void push_successors(const label_t& vertex, wto_partition_t& partition, - const std::weak_ptr<wto_cycle_t>& containing_cycle); + void push_successors(const label_t& vertex, wto_partition_t& partition, + const std::weak_ptr<wto_cycle_t>& containing_cycle) const;
- The
wto_nesting_t::operator>
could be simplified and made more const-correct:- const size_t this_size = this->_heads.size(); - const size_t other_size = nesting._heads.size(); + auto this_size = std::size(_heads); + auto other_size = std::size(nesting._heads);Would you like me to identify more opportunities for const-correctness improvements?
src/test/ebpf_yaml.cpp (1)
Line range hint
1-424
: Consider additional const-correctness improvements in future PRsWhile the current changes effectively implement move semantics, there are opportunities for further const-correctness improvements in future PRs:
- Functions that don't modify their parameters could return by value instead of const reference
- Member functions that don't modify object state could be marked const
- Local variables that aren't modified after initialization could be marked const
These suggestions are outside the scope of the current PR but could be valuable future improvements.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
📒 Files selected for processing (19)
- src/asm_files.cpp (3 hunks)
- src/asm_ostream.cpp (4 hunks)
- src/asm_unmarshal.cpp (2 hunks)
- src/assertions.cpp (4 hunks)
- src/crab/array_domain.cpp (4 hunks)
- src/crab/bitset_domain.cpp (2 hunks)
- src/crab/cfg.hpp (6 hunks)
- src/crab/fwd_analyzer.cpp (2 hunks)
- src/crab/split_dbm.cpp (3 hunks)
- src/crab/split_dbm.hpp (1 hunks)
- src/crab/var_factory.cpp (2 hunks)
- src/crab/variable.hpp (1 hunks)
- src/crab/wto.cpp (2 hunks)
- src/crab_utils/adapt_sgraph.hpp (6 hunks)
- src/crab_utils/stats.cpp (3 hunks)
- src/crab_utils/stats.hpp (2 hunks)
- src/string_constraints.hpp (1 hunks)
- src/test/ebpf_yaml.cpp (2 hunks)
- src/test/test_verify.cpp (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/crab/split_dbm.cpp (1)
Learnt from: elazarg PR: vbpf/ebpf-verifier#689 File: src/crab/split_dbm.cpp:910-910 Timestamp: 2024-09-26T00:57:58.072Z Learning: Avoid suggesting changes that are unrelated to the current PR.
🔇 Additional comments (54)
src/crab_utils/stats.hpp (2)
27-27
: LGTM: Appropriate const qualification addedMaking
toSeconds()
const is the correct choice as it's a getter method that doesn't modify the object's state. This change improves const-correctness and maintains consistency with other const methods in the class.
64-64
: LGTM: Efficient parameter passing with move semanticsTaking the name parameter by value is a good modern C++ practice that enables move semantics. This can be more efficient than const reference when the string will be stored as a member variable.
Let's verify the typical usage patterns to ensure this change is optimal:
✅ Verification successful
Change to pass-by-value is optimal for the usage patterns
The verification shows that ScopedCrabStats is consistently constructed with string literals (e.g., "SplitDBM.copy", "SplitDBM.apply"). Taking the parameter by value is the most efficient approach here since:
- String literals are temporary values that can benefit from move semantics
- The uniform usage pattern with literals means there's no performance penalty from copying existing strings
- The implementation correctly moves the parameter into the member variable
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check how ScopedCrabStats is typically constructed to verify the parameter passing choice is optimal # Look for string literal usage vs variable usage # Search for ScopedCrabStats constructor calls rg -A 2 "ScopedCrabStats\("Length of output: 621
Script:
#!/bin/bash # Search for actual instantiations of ScopedCrabStats in the codebase rg -B 1 -A 1 "ScopedCrabStats\s+\w+" --type cppLength of output: 2430
src/crab/bitset_domain.cpp (2)
5-6
: LGTM: Necessary includes added in correct order.The added includes for
<set>
and<string>
are required for the types used in the implementation and are properly placed after system headers.
63-64
: LGTM: Appropriate use of move semantics.The use of
std::move
here is correct and efficient, as it avoids unnecessary copying of theresult
set when constructing thestring_invariant
.Let's verify that
string_invariant
properly supports move semantics:✅ Verification successful
Move semantics are properly implemented in string_invariant
The
string_invariant
class insrc/string_constraints.hpp
fully supports move semantics with:
- Move constructor:
string_invariant(string_invariant&& inv) = default
- Move assignment:
string_invariant& operator=(string_invariant&& inv) = default
- Constructor taking movable set:
string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv))
The use of
std::move
in the reviewed code is safe and efficient.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify string_invariant's move semantics implementation # Expected: Find move constructor/assignment operator declarations # Search for string_invariant class definition and its move semantics ast-grep --pattern 'struct string_invariant { $$$ string_invariant(string_invariant&& $_) $_; $$$ }'Length of output: 109
Script:
#!/bin/bash # Let's try a broader search for string_invariant definition and its members rg -A 20 "struct string_invariant"Length of output: 1271
Script:
#!/bin/bash # Also search for string_invariant in header files specifically fd -e h -e hpp --exec rg -A 20 "struct string_invariant" {}Length of output: 731
Script:
#!/bin/bash # Search for any move-related implementation rg "string_invariant.*&&"Length of output: 313
Script:
#!/bin/bash # Look for the actual implementation file fd "string_invariant"Length of output: 21
src/string_constraints.hpp (2)
24-25
: LGTM! Good implementation of move semanticsProperly implements the rule of five by adding defaulted move operations alongside existing copy operations. This enables efficient transfer of resources when needed.
20-25
: Verify move semantics usage in the codebaseLet's verify that the new move semantics are being utilized effectively across the codebase.
✅ Verification successful
Move semantics are properly utilized across the codebase
The verification shows that move semantics are being effectively used:
- Move constructors are used when returning from functions in multiple files (e.g.
split_dbm.cpp
,bitset_domain.cpp
,ebpf_yaml.cpp
)std::move
is correctly applied when constructing from rvalue sets and in return statements- The class provides both copy and move operations, allowing callers to choose the most efficient approach
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for potential places where move semantics could be used with string_invariant # Look for string_invariant return values and construction rg -l "string_invariant" | xargs rg "string_invariant.*return|return.*string_invariant|string_invariant\([^)]*\)" -A 2 # Look for places where std::move is used with string_invariant rg "std::move.*string_invariant|string_invariant.*std::move" -A 2Length of output: 3943
src/crab/variable.hpp (1)
38-41
: Verify the impact of return type change on callers.The change from
std::string
toconst std::string&
could affect code that:
- Relies on getting a copy of the string
- Uses
auto
without reference- Passes the result to functions expecting non-const references
Let's verify the usage patterns:
✅ Verification successful
Based on the search results, I can now generate the final response:
Return type change from
std::string
toconst std::string&
appears safeThe codebase analysis shows that
name()
is used in ways that are compatible with the return type change:
- All usages are in read-only contexts (string comparisons, error messages, concatenations)
- No instances found of storing the result in non-reference
auto
variables- No calls to functions that would require non-const references
- String operations create new strings rather than modifying the returned value
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check how the name() method is used in the codebase # Look for direct calls to name() echo "=== Direct calls to name() ===" rg -l "\.name\(\)" | xargs rg -A 2 "\.name\(\)" # Look for auto declarations that might need & echo "=== Auto declarations with name() ===" rg "auto.*=.*name\(\)" # Look for function calls that might expect non-const string& echo "=== Potential function calls with name() result ===" rg "(\w+)\(.*name\(\).*\)"Length of output: 7288
src/crab_utils/stats.cpp (3)
33-35
: LGTM: Appropriate const qualificationThe addition of
const
tototal_us
is correct as the value is computed once and shouldn't be modified afterward. This change aligns well with const-correctness principles.
78-78
: LGTM: Good const qualification for time variableThe addition of
const
to thetime
variable is appropriate as it's only used for calculations and shouldn't be modified after initialization.
130-130
: LGTM: Efficient string parameter handlingThe constructor now takes the string parameter by value and uses
std::move
, which is an optimization that allows for efficient transfer of the string into the member variable. This is a modern C++ best practice for string parameters that will be stored in the class.src/crab/var_factory.cpp (2)
151-151
: LGTM: String formatting improvementThe string concatenation format change makes the output more concise while maintaining readability.
169-169
: LGTM: Improved efficiency with const referenceGood optimization to avoid unnecessary string copy by using const reference. This change aligns well with the PR's const-correctness goals and modern C++ best practices.
src/crab/fwd_analyzer.cpp (1)
131-131
: LGTM: Minor optimization using emplace_back.The change from
push_back
toemplace_back
is safe and aligns with modern C++ practices. While the performance benefit is minimal in this case (since we're dealing with simplelabel_t
values), the change is consistent with the PR's goal of code improvements.src/crab/wto.cpp (1)
166-166
:⚠️ Potential issueConsider reverting this change as it doesn't align with PR objectives.
The change from
push_back
toemplace_back
is an optimization for construction, but since we're dealing with an already constructed vertex, it doesn't provide meaningful benefits. More importantly, this change doesn't contribute to the PR's stated goal of improving const-correctness.- cycle->_components.emplace_back(vertex); + cycle->_components.push_back(vertex);Likely invalid or redundant comment.
src/assertions.cpp (3)
45-48
: LGTM: Improved const-correctnessThe change to use
const&
prevents unnecessary copying and aligns with the PR's objective of enhancing const-correctness.
246-247
: LGTM: Improved documentation clarityThe added comment clearly documents the type requirements for binary operations, enhancing code maintainability.
172-173
: Verify the stack boundary check modificationThe condition change from
> 0
to>= 0
makes the stack boundary check more strict by including zero offset. This could potentially affect existing programs that rely on accessing the last byte of the stack.Please confirm if this is an intentional security enhancement. Let's verify the impact:
✅ Verification successful
Stack boundary check modification is correct and intentional
The change from
> 0
to>= 0
is a proper security enhancement that prevents accessing memory at the stack boundary. The verification shows:
- The stack pointer (R10) is initialized with
EBPF_STACK_SIZE
as the base offset- Stack accesses are validated to be within
-EBPF_STACK_SIZE
to0
(exclusive)- The codebase consistently treats the stack range as
[base-EBPF_STACK_SIZE, base)
, where accessing the byte at offset 0 would be out of boundsThis is consistent with standard stack layout where the stack grows downward from the base pointer, and accessing the byte at offset 0 would be beyond the stack's allocated space.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for tests or examples that might be affected by this change rg -l "R10" --type cpp --type c | xargs rg -l "stack" # Look for any related discussions or comments about stack boundary checks rg -i "stack.*boundary|stack.*access|stack.*offset" --type mdLength of output: 159
Script:
#!/bin/bash # Let's examine the actual implementation and context around stack boundary checks rg -B 5 -A 5 "EBPF_STACK_SIZE" src/assertions.cpp # Look for related test cases rg -B 5 -A 5 "stack.*offset|stack.*bound" src/test # Check the implementation in ebpf_domain.cpp for related stack checks rg -B 5 -A 5 "R10.*stack|stack.*offset" src/crab/ebpf_domain.cpp # Look for any constants or definitions related to stack rg "EBPF_STACK_SIZE" --type cpp --type hpp --type hLength of output: 17162
src/crab_utils/adapt_sgraph.hpp (5)
5-5
: LGTM: Explicit include of required header.The addition of
<cassert>
header makes the dependency explicit, which is good practice for header hygiene.
361-361
: LGTM: Improved const-correctness in loop variable.The addition of
const
qualifier to the loop variablek
correctly indicates that the key is not modified during iteration.
373-373
: LGTM: Improved const-correctness in loop variable.The addition of
const
qualifier to the loop variablev
correctly indicates that the vertex id is not modified during iteration.
420-420
: LGTM: Consistent application of const-correctness to lookup results.The addition of
const
qualifier to theidx
variables across multiple methods correctly indicates that these lookup results are not modified after retrieval.Also applies to: 429-429, 452-452, 460-460
468-471
: Verify the implications of const qualification in operator<<.While adding
const
qualifiers improves const-correctness, there's a comment suggesting thatg
cannot be marked const for complicated reasons. This seems to contradict the const qualification being added.Let's verify if there are any const-related issues in the implementation:
✅ Verification successful
The const qualification in operator<< is correct and safe
The implementation is consistent with const-correctness:
- Both
verts()
ande_succs()
are marked withconst
qualifiers and return const ranges- The operator only reads from the graph without modifications
- The old comment about const-ness appears to be outdated and no longer relevant
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if there are any non-const method calls on g within operator<< # Look for method calls on g within operator<< ast-grep --pattern 'operator<<(std::ostream& $_, const AdaptGraph& $_) { $$$ $_.e_succs($_) $$$ }' # Look for the comment about const-ness to understand the context rg "cannot be marked const for complicated reasons" -A 5Length of output: 628
Script:
#!/bin/bash # Let's check the implementation of verts() and e_succs() methods to understand if they modify the graph ast-grep --pattern 'class AdaptGraph { $$$ verts() { $$$ } $$$ }' ast-grep --pattern 'class AdaptGraph { $$$ e_succs($_) { $$$ } $$$ }' # Also check if there are any other method calls on g within operator<< rg "g\." --type cpp -A 2 src/crab_utils/adapt_sgraph.hpp | grep -A 2 "operator<<"Length of output: 247
Script:
#!/bin/bash # Let's try a different approach to find the methods and their usage # Search for the entire operator<< implementation rg "operator<<.*AdaptGraph" -A 20 src/crab_utils/adapt_sgraph.hpp # Search for verts() and e_succs() method declarations rg "verts\(\)" --type cpp src/crab_utils/adapt_sgraph.hpp -B 2 -A 2 rg "e_succs\(" --type cpp src/crab_utils/adapt_sgraph.hpp -B 2 -A 2Length of output: 1966
src/test/ebpf_yaml.cpp (2)
88-92
: LGTM: Efficient use of move semanticsThe changes optimize memory usage by avoiding unnecessary copying when constructing the
string_invariant
. Usingstd::move
here is appropriate asres
is no longer needed after the return statement.
313-313
: LGTM: Consistent use of move semanticsThe change optimizes memory usage by using move semantics, consistent with the approach used in
read_invariant
. This is a good practice asmore
is not needed after the return statement.src/asm_ostream.cpp (3)
Line range hint
443-453
: LGTM! Well-structured output operator implementation.The implementation is const-correct and provides a clear, consistent format for EbpfMapDescriptor fields.
Line range hint
498-508
: LGTM! Improved output formatting.The whitespace changes enhance readability while maintaining consistent formatting.
302-302
:⚠️ Potential issueFix potential undefined behavior with INT_MIN
Using
std::abs
onaccess.offset
can lead to undefined behavior if the value is INT_MIN (-2147483648), as its absolute value cannot be represented in a 32-bit int.Consider one of these solutions:
- const int offset = std::abs(access.offset); // what about INT_MIN? + const int64_t offset = std::abs(static_cast<int64_t>(access.offset));Or handle INT_MIN explicitly:
- const int offset = std::abs(access.offset); // what about INT_MIN? + const int offset = (access.offset == INT_MIN) + ? INT_MAX + : std::abs(access.offset);Likely invalid or redundant comment.
src/crab/cfg.hpp (6)
18-18
: LGTM: Explicit header inclusion.Making the
<utility>
header inclusion explicit is good practice since the code directly usesstd::move
andstd::pair
.
66-66
: LGTM: Performance optimization using emplace_back.Using
emplace_back
instead ofpush_back
is more efficient as it constructs the element in-place, avoiding unnecessary copies.
69-69
: LGTM: Efficient move semantics.Using
std::move
for the label parameter avoids unnecessary copying, improving performance.
342-342
: LGTM: Improved const-correctness in loop.Using a const reference for the loop variable prevents accidental modifications and avoids unnecessary copying of the pair objects.
377-377
: LGTM: Consistent use of emplace_back.Using
emplace_back
maintains consistency with other container modifications and potentially improves performance through in-place construction.
Line range hint
528-533
: LGTM: Enhanced const-correctness for iterators.Adding const qualifiers to the iterator variables prevents accidental modifications and aligns with the PR's goal of improving const-correctness.
Also applies to: 537-542
src/asm_files.cpp (4)
268-268
: LGTM: Efficient in-place constructionThe use of
emplace_back
with direct member initialization is more efficient than constructing a temporary object.
426-427
: LGTM: Efficient string handlingGood use of move semantics to avoid unnecessary string copies, both when setting the target function name and when storing the relocation data.
439-439
: LGTM: Consistent move semanticsAppropriate use of move semantics for error message strings, consistent with the codebase's approach to string handling.
443-443
: LGTM: Efficient program data handlingAppropriate use of move semantics when storing the program data, which avoids copying potentially large instruction vectors and associated metadata.
src/crab/array_domain.cpp (4)
5-5
: LGTM: Appropriate header inclusion.The addition of
<cassert>
header is correct as the code uses assert statements throughout the implementation.
498-498
: LGTM: Proper const-qualification in range-based for loop.Adding
const
qualifier to the vector reference in the range-based for loop is a good practice as it prevents accidental modifications to the vector elements while iterating.
349-351
: LGTM: Performance optimization using emplace_back.The change from
push_back
toemplace_back
is a good optimization as it constructs elements in-place, avoiding unnecessary copies. This is aligned with modern C++ best practices.
718-718
: 🧹 Nitpick (assertive)Consider adding const qualifier.
The
cell_t
objectc
is not modified after creation. Consider adding theconst
qualifier to maintain consistency with the const-correctness improvements:- const cell_t c = offset_map.mk_cell(o, size); + const cell_t const c = offset_map.mk_cell(o, size);Likely invalid or redundant comment.
src/asm_unmarshal.cpp (2)
508-508
: LGTM! Performance improvement using emplace_back.The change from
push_back
toemplace_back
is a good optimization that constructs theArgSingle
object directly in the vector's memory, avoiding unnecessary copies.
541-542
: LGTM! Performance improvement using emplace_back.Similar to the previous change, using
emplace_back
here is a good optimization for constructingArgPair
objects directly in the vector's memory, avoiding unnecessary copies.src/test/test_verify.cpp (1)
504-504
: LGTM! Good test coverage for bpf-to-bpf calls.The test case complements the preceding rejection test by verifying the successful case where a subprogram can be called from the main program, providing good coverage for both positive and negative scenarios of bpf-to-bpf calls.
src/crab/split_dbm.cpp (10)
3-6
: Appropriate inclusion of<cassert>
and<optional>
headersThe addition of
<cassert>
and<optional>
headers is essential for assertions and utilizingstd::optional
, enhancing code robustness.
Line range hint
30-36
: Improvedtry_at
function withstd::optional
The
try_at
function now returns anstd::optional<vert_id>
, which enhances safety by explicitly handling cases where a variable is not found in the map.
Line range hint
39-48
: Correct handling of optional values inget_vert
methodThe
get_vert
method correctly checks thestd::optional
returned bytry_at
and handles the creation of new vertices when needed, ensuring consistent vertex management.
Line range hint
94-129
: Refineddiffcsts_of_assign
method signatureUpdating
diffcsts_of_assign
to separate lower and upper bounds into different vectors improves clarity and aligns with best practices for function parameter design.
Line range hint
295-349
: Enhanced error handling inadd_linear_leq
methodThe modifications in processing lower and upper bounds, especially handling unbounded variables, strengthen the method’s robustness against edge cases.
Line range hint
367-399
: Improved bounds strengthening inadd_univar_disequation
Adding checks for finite bounds and strengthening lower and upper bounds as appropriate enhances the method's correctness and reliability.
Line range hint
511-515
: Consistent use ofstd::optional
in comparison operationsThe comparisons involving
std::optional
values in theoperator<=
method are correctly implemented, ensuring accurate and safe comparisons.
Line range hint
678-706
: Proper handling of overflow inassign
methodThe checks for potential overflows using
convert_NtoW_overflow
before assigning values prevent unintended behavior, enhancing the method’s safety.
Line range hint
791-798
: Accurate handling ofEQUALS_ZERO
constraintsThe logic for processing
EQUALS_ZERO
constraints ensures that both the constraint and its negation are correctly handled, maintaining the domain's consistency.
1205-1207
: Comprehensive set representation into_set
methodThe method accurately represents the set of invariants, efficiently handling both interval constraints and difference constraints, which improves debugging and analysis.
|
||
explicit string_invariant(std::set<std::string> inv) : maybe_inv(std::move(inv)) {}; | ||
string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv)) {}; |
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.
🧹 Nitpick (assertive)
LGTM! Consider adding documentation
Good use of move semantics to avoid unnecessary copying. Consider adding a brief comment explaining that this constructor takes ownership of the passed set.
+ /// Takes ownership of the provided set of strings
string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv)) {};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv)) {}; | |
/// Takes ownership of the provided set of strings | |
string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv)) {}; |
// callers can take a copy if they need it | ||
[[nodiscard]] | ||
std::string name() const { | ||
const std::string& name() const { | ||
return names->at(_id); |
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.
🧹 Nitpick (assertive)
LGTM! Good performance optimization.
The change from returning std::string
to const std::string&
is a good optimization that avoids unnecessary string copies while maintaining safety through thread-local storage.
Consider expanding the comment to be more explicit about lifetime guarantees:
- // callers can take a copy if they need it
+ // Returns a reference to a thread-local string. The reference is valid for the thread's lifetime.
+ // Callers should take a copy if they need to store or pass the string across threads.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// callers can take a copy if they need it | |
[[nodiscard]] | |
std::string name() const { | |
const std::string& name() const { | |
return names->at(_id); | |
// Returns a reference to a thread-local string. The reference is valid for the thread's lifetime. | |
// Callers should take a copy if they need to store or pass the string across threads. | |
[[nodiscard]] | |
const std::string& name() const { | |
return names->at(_id); |
…ble string copies.
Co-authored-by: Elazar Gershuni <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Keith Horton <[email protected]>
Signed-off-by: Keith Horton <[email protected]>
Signed-off-by: Keith Horton <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
4512d57
to
d722b89
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
🧹 Outside diff range comments (4)
src/crab/add_bottom.hpp (1)
Line range hint
112-117
: Consider additional const-correctness improvements in operator&.While the current change is good, there are additional opportunities to enhance const-correctness:
- The dereferencing operations could be made more explicit about const-correctness
- The method parameters could be marked as references to const
Consider this implementation:
- AddBottom operator&(const AddBottom& o) const { + [[nodiscard]] + AddBottom operator&(const AddBottom& o) const { if (!dom || !o.dom) { return bottom(); } - if (const auto res = (*dom).meet(*o.dom)) { + if (const auto res = dom->meet(o.dom)) { return AddBottom(*res); } return bottom(); }The changes:
- Added [[nodiscard]] to enforce proper handling of the return value
- Simplified pointer dereferencing using -> operator
- Maintained const-correctness throughout the chain
src/crab/linear_expression.hpp (1)
Line range hint
158-164
: LGTM with minor suggestions for modernization.The addition of
const
is appropriate. Consider these optional improvements:
- Use
const auto
for type deduction consistency- Simplify the constant output logic
Consider this modern C++ style refactor:
- const number_t constant = expression.constant_term(); - if (constant < 0) { - o << constant; - } else if (constant > 0) { - o << " + " << constant; - } + const auto constant = expression.constant_term(); + if (constant != 0) { + o << (constant > 0 ? " + " : "") << constant; + }src/crab/wto.cpp (1)
Line range hint
1-324
: Suggest additional const-correctness improvements.Since this PR focuses on const-correctness, here are some additional improvements that could be made:
- The
partition
parameter inpush_successors
,start_visit
, andcontinue_visit
methods could be passed by const reference if it's not modified within these methods.- Consider marking appropriate member functions as
const
where they don't modify object state.Would you like me to provide specific suggestions for these const-correctness improvements?
src/asm_ostream.cpp (1)
Line range hint
443-453
: Consider improving the output format for better readabilityWhile the implementation is functionally correct, the output format could be enhanced for better readability. Consider using newlines and indentation for multi-line output.
-std::ostream& operator<<(std::ostream& o, const EbpfMapDescriptor& desc) { - return o << "(" - << "original_fd = " << desc.original_fd << ", " - << "inner_map_fd = " << desc.inner_map_fd << ", " - << "type = " << desc.type << ", " - << "max_entries = " << desc.max_entries << ", " - << "value_size = " << desc.value_size << ", " - << "key_size = " << desc.key_size << ")"; -} +std::ostream& operator<<(std::ostream& o, const EbpfMapDescriptor& desc) { + return o << "{\n" + << " original_fd: " << desc.original_fd << "\n" + << " inner_map_fd: " << desc.inner_map_fd << "\n" + << " type: " << desc.type << "\n" + << " max_entries: " << desc.max_entries << "\n" + << " value_size: " << desc.value_size << "\n" + << " key_size: " << desc.key_size << "\n" + << "}"; +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
📒 Files selected for processing (24)
src/asm_files.cpp
(2 hunks)src/asm_ostream.cpp
(4 hunks)src/asm_unmarshal.cpp
(1 hunks)src/assertions.cpp
(3 hunks)src/crab/add_bottom.hpp
(1 hunks)src/crab/array_domain.cpp
(4 hunks)src/crab/bitset_domain.cpp
(2 hunks)src/crab/cfg.hpp
(6 hunks)src/crab/fwd_analyzer.cpp
(2 hunks)src/crab/interval.hpp
(1 hunks)src/crab/linear_expression.hpp
(2 hunks)src/crab/split_dbm.cpp
(3 hunks)src/crab/split_dbm.hpp
(1 hunks)src/crab/var_factory.cpp
(2 hunks)src/crab/variable.hpp
(1 hunks)src/crab/wto.cpp
(1 hunks)src/crab_utils/adapt_sgraph.hpp
(6 hunks)src/crab_utils/stats.cpp
(3 hunks)src/crab_utils/stats.hpp
(2 hunks)src/main/memsize_windows.hpp
(1 hunks)src/main/utils.hpp
(1 hunks)src/string_constraints.hpp
(1 hunks)src/test/ebpf_yaml.cpp
(2 hunks)src/test/test_verify.cpp
(1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/crab/split_dbm.cpp (1)
Learnt from: elazarg
PR: vbpf/ebpf-verifier#689
File: src/crab/split_dbm.cpp:910-910
Timestamp: 2024-09-26T00:57:58.072Z
Learning: Avoid suggesting changes that are unrelated to the current PR.
🔇 Additional comments (56)
src/main/utils.hpp (2)
6-6
: LGTM! Appropriate const usage.
Making begin
const is correct as it should remain immutable after capturing the start time.
10-10
: LGTM! Appropriate const usage.
Making end
const is correct as it should remain immutable after capturing the end time.
src/main/memsize_windows.hpp (1)
12-12
: LGTM! Good const-correctness improvement.
Making ok
const is a positive change as it:
- Prevents accidental modification
- Clearly communicates that the value is only assigned once
- Enables potential compiler optimizations
src/crab_utils/stats.hpp (1)
27-27
: LGTM! Good const-correctness improvement.
Adding const qualification to toSeconds()
is appropriate as time conversion shouldn't modify the stopwatch's state.
src/crab/bitset_domain.cpp (2)
5-6
: LGTM! Explicit header includes improve code clarity.
Making the dependencies on <set>
and <string>
explicit rather than relying on indirect inclusion through other headers is good practice.
63-64
: Verify move semantics support in string_invariant.
The use of std::move
is a good optimization to prevent unnecessary copying. However, we should verify that string_invariant
properly supports move semantics.
Let's verify the string_invariant implementation:
✅ Verification successful
Based on the results, I can generate the final response as we have sufficient information about the string_invariant
implementation.
Move semantics are properly supported in string_invariant
The class correctly implements all necessary move semantics:
- Has explicitly defaulted move constructor:
string_invariant(string_invariant&& inv) = default
- Has explicitly defaulted move assignment:
string_invariant& operator=(string_invariant&& inv) = default
- Constructor taking
std::set<std::string>&&
usesstd::move
:string_invariant(std::set<std::string>&& inv) : maybe_inv(std::move(inv))
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if string_invariant properly implements move semantics
# Look for move constructor/assignment operator declarations
rg -A 5 "string_invariant\(" "src/"
# Look for potential copy operations that could be moved
ast-grep --pattern 'string_invariant{$_}'
Length of output: 1303
src/string_constraints.hpp (2)
19-19
: LGTM! Efficient move semantics implementation
The constructor correctly implements move semantics, which aligns with the PR's const-correctness objectives while improving efficiency by avoiding unnecessary copying.
23-24
: LGTM! Well-implemented move operations
The explicit declaration of move operations completes the rule of five, making the class's behavior clear and consistent. The defaulted implementations are appropriate since the member types (std::optional and std::set) already handle resource management correctly.
src/crab/variable.hpp (2)
Line range hint 1-89
: LGTM! Good const-correctness practices.
The class demonstrates proper const-correctness:
- Methods are appropriately marked const
- [[nodiscard]] is used effectively
- Thread safety is maintained through thread-local storage
38-41
: Verify the lifetime management of the returned reference.
The method safely returns a reference to thread-local storage. However, we should verify that callers don't store this reference beyond the immediate scope.
✅ Verification successful
Based on the search results, I can now provide a definitive response:
No lifetime issues found with the returned reference.
The codebase analysis shows safe usage of the name()
method's returned reference:
- No storage of the reference in class members or global variables
- No storage in containers
- The reference is only used for immediate operations like string comparisons, concatenations, or as temporary values
- The thread-local storage ensures the referenced string outlives any usage within the same thread
The most common usages are:
- Direct string operations (e.g.,
name().empty()
,name().substr()
) - Immediate comparisons (e.g.,
if(name() == other)
) - Temporary value in string concatenations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential lifetime issues with stored references to name()
# Look for assignments of name() result to class members or global variables
ast-grep --pattern 'class $_ {
$$$
const std::string& $_ = $$.name();
$$$
}'
# Look for storage in containers
rg -l "std::.*<.*string&.*>" | xargs -r rg "name()"
Length of output: 138
Script:
#!/bin/bash
# Let's try a different approach to find potential lifetime issues
# Look for variable assignments involving name()
rg -A 2 "name\(\)" --type cpp
# Look for any storage of references to strings in the codebase
rg "const\s+std::string\s*&" --type cpp
# Look specifically for assignments from name()
ast-grep --pattern 'const std::string& $_ = $$.name()'
# Check if name() is used in any container operations
rg "push_back|emplace_back|insert.*name\(\)" --type cpp
Length of output: 65838
src/crab_utils/stats.cpp (3)
33-35
: LGTM: Appropriate const qualifier addition
The const
qualifier for total_us
is well-placed as the variable should not be modified after initialization.
78-78
: LGTM: Good const qualifier addition
The const
qualifier for time
is appropriate as the value is only used for calculations and should not be modified.
Line range hint 130-137
: Verify if move semantics change aligns with PR scope
While the change to use move semantics is a good optimization, it seems to go beyond the stated PR objective of improving const-correctness. The implementation itself is correct and follows best practices, but consider whether this change should be part of a separate PR focused on move semantics optimizations.
If you decide to keep this change, the implementation is correct as it:
- Takes the name parameter by value
- Uses std::move to transfer ownership efficiently
- Avoids unnecessary copying
src/crab/add_bottom.hpp (2)
113-116
: LGTM! The const addition improves safety.
The addition of const
to the res
variable is appropriate as it's not modified after initialization. This change aligns well with the PR's objective of improving const-correctness.
113-113
: Verify const-correctness of the meet operation.
Let's verify that the meet operation in the underlying SplitDBM type maintains const-correctness throughout the call chain.
✅ Verification successful
Let me check the implementation details of the meet operation to verify its const-correctness.
The meet operation maintains proper const-correctness
The implementation in SplitDBM
is const-correct:
- The method is declared as
const
:meet(const SplitDBM& o) const
- It takes its argument by const reference:
const SplitDBM& o
- The usage in the original code
(*dom).meet(*o.dom)
correctly calls this const method
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for meet operation implementation in SplitDBM
ast-grep --pattern 'class SplitDBM {
$$$
meet($$$) {
$$$
}
$$$
}'
# Also check for any other meet implementations that might be relevant
rg -p "std::optional.*meet.*\(" --type cpp
Length of output: 304
Script:
#!/bin/bash
# Get the implementation details of meet operation
rg -p -B 2 -A 10 "std::optional<SplitDBM> SplitDBM::meet" src/crab/split_dbm.cpp
# Check if there are any other meet operations in the inheritance chain
ast-grep --pattern 'class $_: $$ {
$$$
meet($$$) {
$$$
}
$$$
}'
Length of output: 524
src/crab/var_factory.cpp (2)
151-151
: LGTM: Improved string formatting
The removal of whitespace between "s" and "[" results in cleaner output formatting.
169-169
: LGTM: Enhanced const-correctness with reference
The change from value to reference type avoids unnecessary string copying while maintaining const-correctness. This aligns well with the PR's objectives.
Let's verify the return type of the name() method to ensure it's safe to store its result by reference:
✅ Verification successful
From the search results, I found the relevant information in src/crab/variable.hpp
:
[[nodiscard]]
const std::string& name() const {
return names->at(_id);
}
This shows that name()
returns a const reference to a string stored in a shared names
container, which is exactly what we want to verify. The reference is safe to store since it points to a string in a shared container that outlives the local usage.
✓ Change is safe and improves performance
The change from value to reference type is safe because type_variable.name()
returns a const reference to a string stored in a shared container. This avoids unnecessary string copying while maintaining const-correctness.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the declaration of name() method in variable.hpp
ast-grep --pattern 'class variable_t {
$$$
$ret_type name() $qual {
$$$
}
$$$
}'
Length of output: 94
Script:
#!/bin/bash
# Let's try a broader search for the name() method and type_variable's type
# First, find files that might contain the definition
fd -e hpp -e cpp -e h | xargs rg "name\(\)" -B2 -A2
# Also search for type_variable's declaration
rg "type_variable" -B2 -A2
Length of output: 40421
src/crab/linear_expression.hpp (1)
28-28
: LGTM: Appropriate use of const auto for iterator.
The change enhances const-correctness without impacting performance, while following modern C++ best practices.
src/crab/fwd_analyzer.cpp (3)
3-6
: LGTM! Explicit header inclusions improve code clarity.
Making the dependencies on <memory>
and <vector>
explicit is good practice, as these headers are required for std::shared_ptr
and std::vector
usage in the code.
131-131
: LGTM! Good optimization using emplace_back.
Using emplace_back
instead of push_back
is a good optimization that constructs elements in-place, avoiding unnecessary copies. This change aligns with modern C++ best practices.
Line range hint 1-240
: Verify test coverage for the forward analyzer.
Given the complexity of the forward analysis algorithm and its critical role in eBPF verification, it would be good to verify that the existing test suite adequately covers the modified code paths.
✅ Verification successful
Test coverage for forward analyzer appears adequate.
Based on the extensive test suite shown in test_verify.cpp
, the forward analyzer is thoroughly tested through:
- Comprehensive testing across multiple real-world eBPF programs from various projects (Cilium, Linux, OVS, Suricata, etc.)
- Tests covering both successful and failing verification cases
- Explicit testing of cycle handling through WTO (Weak Topological Ordering) tests in
test_wto.cpp
- Multi-threading test cases specifically for the analyzer
- Integration tests verifying the analyzer's results through
run_forward_analyzer
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check test coverage for the forward analyzer implementation
# Look for test files related to the forward analyzer
echo "Searching for related test files..."
fd -e cpp -e hpp test_ | rg -l "fwd_analyzer"
# Look for specific test cases covering cycle handling
echo "Searching for cycle-related test cases..."
rg -A 5 "run_forward_analyzer.*cycle"
Length of output: 259
Script:
#!/bin/bash
# Let's try a broader search for tests and usage patterns
# Look for test files in the entire codebase
echo "=== Looking for test files ==="
fd -t f "test.*\.(cpp|hpp)$"
# Search for any references to forward analyzer in tests
echo -e "\n=== Searching for forward analyzer references ==="
rg -l "forward.*analy[sz]"
# Look for test cases or usage of the analyzer
echo -e "\n=== Searching for analyzer usage patterns ==="
rg -l "run_forward_analyzer"
# Search for any CFG cycle related tests
echo -e "\n=== Searching for cycle-related tests ==="
rg "cfg.*cycle|cycle.*cfg" -A 3
Length of output: 1046
Script:
#!/bin/bash
# Let's examine the test_wto.cpp and test_verify.cpp files since they are most likely to contain relevant tests
echo "=== Checking test_wto.cpp for cycle handling tests ==="
cat src/test/test_wto.cpp
echo -e "\n=== Checking test_verify.cpp for analyzer usage ==="
cat src/test/test_verify.cpp
echo -e "\n=== Looking for analyzer usage in crab_verifier.cpp ==="
rg -A 5 "run_forward_analyzer" src/crab_verifier.cpp
Length of output: 41290
src/crab/split_dbm.hpp (1)
Line range hint 229-233
: LGTM! Good performance optimization.
The change to accept const std::optional<variable_t>&
instead of std::optional<variable_t>
by value is a good improvement. This prevents unnecessary copying of the optional parameter while maintaining the same behavior, which is particularly beneficial when variable_t
is a non-trivial type.
src/crab/wto.cpp (1)
166-166
:
Consider reverting this change as it doesn't align with PR objectives.
The change from push_back
to emplace_back
here doesn't contribute to const-correctness, which is the stated objective of this PR. Additionally, since we're dealing with an already constructed vertex
object, emplace_back
provides no meaningful optimization over push_back
.
Apply this diff to maintain consistency with the PR's focus on const-correctness:
- cycle->_components.emplace_back(vertex);
+ cycle->_components.push_back(vertex);
This is similar to the feedback provided in previous reviews where similar emplace_back
changes were reverted.
src/assertions.cpp (2)
45-45
: LGTM: Improved const-correctness
The change to accept IncrementLoopCounter
by const reference instead of by value is a good improvement that aligns with modern C++ best practices and the PR's objective of enhancing const-correctness.
197-198
: Verify the stricter stack boundary check
The condition change from > 0
to >= 0
makes the stack boundary check stricter by preventing access exactly at the stack boundary. While this is potentially more secure, we should verify that this change doesn't break existing valid eBPF programs.
Let's check for any test cases or existing programs that might be affected:
✅ Verification successful
Based on the search results, I can now provide a conclusive response about the stack boundary check change:
Stack boundary change is correct and intentional
The stricter condition >= 0
for stack boundary checking is the right approach because:
- The eBPF stack is defined as exactly 512 bytes (EBPF_STACK_SIZE)
- R10 is the dedicated stack pointer register
- Stack access is done via negative offsets from R10, where valid accesses must be within [-512, 0)
- The change prevents accessing byte at offset 0, which would be outside the valid stack range
The codebase consistently treats stack access at boundary (offset 0) as invalid:
asm_unmarshal.cpp
already had this check:inst.offset + opcode_to_width(inst.opcode) > 0 || inst.offset < -EBPF_STACK_SIZE
- Test cases in
test-data/stack.yaml
verify various stack access patterns but none rely on boundary access - The change aligns with how other eBPF verifiers handle stack bounds
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Look for test cases that might be affected by the stricter stack boundary check
# Search for test cases involving stack access at boundary
rg -l "R10" --type cpp test/
rg -l "EBPF_STACK_SIZE" --type cpp test/
# Search for any stack-related test assertions
ast-grep --pattern 'ASSERT$$$stack$$$'
Length of output: 202
Script:
#!/bin/bash
# Let's try searching in the entire repository for test files and stack-related patterns
# Find test files
fd -e cpp -e c -e h test
# Search for R10 register usage
rg "R10" -A 3 -B 3
# Search for stack size constant
rg "EBPF_STACK_SIZE"
# Search for stack-related test cases or assertions
rg -i "stack.*test|test.*stack"
Length of output: 16224
src/crab_utils/adapt_sgraph.hpp (6)
5-5
: LGTM: Good addition of missing header.
The addition of <cassert>
header is appropriate as the code uses assert statements.
361-361
: LGTM: Appropriate const qualification.
The addition of const
to the loop variable is correct as it's only used for reading.
373-373
: LGTM: Appropriate const qualification.
The addition of const
to the loop variable is correct as it's only used for reading.
420-420
: LGTM: Good use of const auto.
The use of const auto
for the idx
variable is appropriate as it's only used for reading and maintains the optional pattern correctly.
Also applies to: 429-429
452-452
: LGTM: Good use of const auto.
The use of const auto
for the idx
variable is appropriate as it's only used for reading and maintains the optional pattern correctly.
Also applies to: 460-460
468-471
: Verify the const qualification of parameter g.
While adding const
to the loop variable is correct, there's a comment suggesting that g
cannot be marked const "for complicated reasons". Please verify that making the parameter const doesn't cause any issues in practice.
src/crab/interval.hpp (1)
178-179
: LGTM: Const-correctness improvement
The addition of const
qualifiers to lb
and ub
variables is appropriate as these values should not be modified after initialization. This change aligns with the PR's objective of improving const-correctness.
src/test/ebpf_yaml.cpp (2)
88-92
: LGTM: Effective use of move semantics
The change optimizes memory usage by moving the set into the string_invariant
constructor instead of copying it, which is appropriate since res
is a local variable that won't be used after the return statement.
318-318
: LGTM: Consistent application of move semantics
The change optimizes the return statement by moving the set into the string_invariant
constructor, consistent with modern C++ best practices and the changes made to read_invariant
.
src/asm_ostream.cpp (2)
302-302
: Previous comment about INT_MIN undefined behavior is still applicable
Line range hint 498-507
: LGTM! Improved formatting enhances readability
The spacing changes around "goto" and commas make the output more readable while maintaining the existing functionality.
src/crab/cfg.hpp (6)
66-66
: LGTM: Efficient use of emplace_back
The change from push_back
to emplace_back
is a good optimization that avoids unnecessary copying of the instruction.
69-69
: LGTM: Proper use of move semantics
Using std::move
for the label parameter optimizes the constructor by avoiding unnecessary copying.
342-342
: LGTM: Enhanced const-correctness
Making the loop variable const is appropriate as the pair elements are not modified within the loop.
377-377
: LGTM: Consistent use of emplace_back
Using emplace_back
here maintains consistency with other container operations and provides better performance.
Line range hint 528-533
: LGTM: Proper const qualification
Making the iterator const is appropriate as it's not modified after initialization.
Line range hint 537-542
: LGTM: Consistent const qualification
The const iterator in the const member function maintains const-correctness throughout.
src/asm_files.cpp (3)
426-427
: LGTM! Good use of move semantics.
The use of std::move
here optimizes memory usage by avoiding unnecessary string copying when constructing the function_relocation
struct.
439-439
: LGTM! Efficient string handling.
Good use of std::move
to avoid copying the error message string when adding it to the vector.
443-443
: LGTM! Proper use of move semantics.
Using emplace_back
with std::move
is the right approach here as it avoids unnecessary copying of the program object.
src/crab/array_domain.cpp (4)
5-5
: LGTM: Adding header
The addition of the header is appropriate as the codebase uses assertions for runtime checks.
349-351
: LGTM: Optimized vector operations
The change from push_back
to emplace_back
is a good optimization. emplace_back
constructs elements in-place, potentially avoiding unnecessary copies and moves.
498-498
: LGTM: Improved const-correctness for vector
Adding const qualifier to the vector and loop variable prevents accidental modifications and clearly communicates intent.
718-718
: LGTM: Added const qualifier to cell_t
The const qualifier for the cell_t variable is appropriate as it's not modified after creation.
src/asm_unmarshal.cpp (1)
542-542
: LGTM: Clean constructor parameter passing
The modification correctly passes the can_be_zero
parameter to the ArgPair
constructor, maintaining the same functionality while making the code more explicit and clearer.
src/test/test_verify.cpp (1)
504-504
: LGTM! Test case addition is well-placed and follows the established pattern.
The new test case complements the preceding rejection test, creating a comprehensive verification of both successful and failing scenarios for subprogram invocation.
✅ Verification successful
Test case addition is correctly structured and positioned
The verification confirms that:
- The test case is properly placed in a sequence of related tests, following a rejection test for
plus1
and preceding other build-related tests - The TEST_PROGRAM macro is correctly used, matching the established pattern in the codebase
- The test follows the same structure as other similar tests (e.g., prog_array.o tests) that verify individual program functions
- The test case is appropriately commented to explain its purpose
The test addition maintains the file's organization and contributes to comprehensive test coverage by verifying successful subprogram invocation scenarios.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the test file structure and related tests
# Test: Check if bpf2bpf.o exists and contains both test functions
fd -t f "bpf2bpf.o" -x readelf -s {} | rg -A 2 "func|plus1"
Length of output: 61
Script:
#!/bin/bash
# Let's first check if the test file exists and examine its content around line 504
rg -A 5 -B 5 "TEST_PROGRAM.*bpf2bpf\.o.*func" src/test/test_verify.cpp
# Let's also check for any related test files or object files
fd "bpf2bpf"
# Check the test macro definition
rg "TEST_PROGRAM" src/test/test_verify.cpp --context 2
Length of output: 2231
src/crab/split_dbm.cpp (5)
3-4
: Appropriate inclusion of necessary headers
The addition of <cassert>
and <optional>
provides the necessary declarations for assert
and std::optional
, respectively. This supports the enhancements made for const-correctness and modern C++ practices.
Also applies to: 6-6
Line range hint 13-17
: Introduction of try_at
function with std::optional
The new try_at
function effectively utilizes std::optional
to handle situations where a variable is not found in the vertex map. This improves safety and adheres to const-correctness principles.
Line range hint 19-32
: Refactoring get_vert
to utilize try_at
Updating the get_vert
method to use try_at
simplifies the code and enhances readability. This change aligns with the goal of increasing const-correctness in the codebase.
791-791
: Consistent logging of contradictions
Adding the logging statement CRAB_LOG("zones-split", std::cout << " ~~> _|_" << "\n");
ensures that contradictions are logged consistently throughout the code, aiding in debugging and maintaining code quality.
1205-1205
: Optimizing return statement with move semantics
Using std::move
in return string_invariant{std::move(result)};
efficiently transfers ownership of result
, avoiding unnecessary copies and improving performance.
|
||
const auto& res = f(); | ||
|
||
clock_t end = clock(); | ||
const clock_t end = clock(); | ||
|
||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; |
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.
🧹 Nitpick (assertive)
Consider making elapsed_secs
const for consistency.
Since elapsed_secs
is not modified after its initialization, it could also be declared as const for complete const-correctness.
- double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
+ const double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; | |
const double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; |
@@ -61,7 +61,7 @@ class ScopedCrabStats { | |||
std::string m_name; | |||
|
|||
public: | |||
explicit ScopedCrabStats(const std::string& name, bool reset = false); | |||
explicit ScopedCrabStats(std::string name, bool reset = false); |
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.
🧹 Nitpick (assertive)
LGTM! Modern C++ move semantics pattern.
Taking name
by value instead of const reference is a good modern C++ pattern when the parameter will be stored as a member. This enables both copy and move semantics, allowing the compiler to optimize based on the caller's context.
This pattern is particularly efficient when:
- The parameter is passed as an lvalue: One copy is made (same as with const reference)
- The parameter is passed as an rvalue: Zero copies are made due to move semantics
} else { | ||
bound_t lb = x._lb < _lb ? ts.get_prev(x._lb) : _lb; | ||
bound_t ub = _ub < x._ub ? ts.get_next(x._ub) : _ub; | ||
const bound_t lb = x._lb < _lb ? ts.get_prev(x._lb) : _lb; | ||
const bound_t ub = _ub < x._ub ? ts.get_next(x._ub) : _ub; | ||
return interval_t{lb, ub}; | ||
} | ||
} |
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.
🛠️ Refactor suggestion
Consider additional const-correctness improvements
While making local variables const is good, there are additional opportunities to improve const-correctness and efficiency:
- The method should be marked
const
since it doesn't modify the object's state - Parameter
x
could be passed by const reference to avoid copying
- interval_t widening_thresholds(interval_t x, const Thresholds& ts) {
+ interval_t widening_thresholds(const interval_t& x, const Thresholds& ts) const {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
} else { | |
bound_t lb = x._lb < _lb ? ts.get_prev(x._lb) : _lb; | |
bound_t ub = _ub < x._ub ? ts.get_next(x._ub) : _ub; | |
const bound_t lb = x._lb < _lb ? ts.get_prev(x._lb) : _lb; | |
const bound_t ub = _ub < x._ub ? ts.get_next(x._ub) : _ub; | |
return interval_t{lb, ub}; | |
} | |
} | |
} else { | |
const bound_t lb = x._lb < _lb ? ts.get_prev(x._lb) : _lb; | |
const bound_t ub = _ub < x._ub ? ts.get_next(x._ub) : _ub; | |
return interval_t{lb, ub}; | |
} | |
} |
Signed-off-by: Keith Horton <[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: 0
🧹 Outside diff range comments (1)
src/assertions.cpp (1)
Line range hint
1-324
: Consider additional const-correctness improvementsWhile reviewing the file, I noticed several opportunities for further const-correctness improvements:
- The
explicate
method could be marked as[[nodiscard]] const
- Several
std::get_if
calls could use const pointers since they're only used for type checkingWould you like me to provide specific examples of these potential improvements?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
📒 Files selected for processing (1)
src/assertions.cpp
(3 hunks)
🔇 Additional comments (2)
src/assertions.cpp (2)
197-198
: LGTM: Improved code documentation
The added comment clarifies the purpose of this validation block, making the code more maintainable. The condition correctly validates stack access bounds to prevent buffer overflows and underflows.
45-48
: LGTM: Improved const-correctness
The change from pass-by-value to pass-by-const-reference is a good improvement for efficiency. However, I notice this appears to be an unimplemented case that always asserts false - is this intentional?
Let's check if this is an expected unimplemented case:
✅ Verification successful
The assert(false)
is an intentional pattern for unhandled cases
The assert(false)
pattern appears consistently across both assertions.cpp
and asm_marshal.cpp
in similar contexts:
- As default cases in switch statements for unhandled operations
- In visitor pattern implementations for specific types (Undefined, Assert, IncrementLoopCounter)
- Always followed by
return {}
as a fallback
This is a common C++ pattern to mark unimplemented or intentionally unsupported cases, making the code fail fast during development/testing rather than silently continuing with undefined behavior.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar assert(false) patterns in operator() methods
rg -U "operator\(\).*\{[^}]*assert\(false\)" src/
Length of output: 534
Script:
#!/bin/bash
# Let's check the context around these assert(false) cases to understand the pattern
rg -B 2 -A 2 "assert\(false\)" src/assertions.cpp src/asm_marshal.cpp
Length of output: 2231
This PR does all sorts of unrelated changes - adding comments, adding consts, using move()... Can you split it up to several focused PRs? |
Using code scanning tools, found a few places to update the code to move to greater const-correctness.
Summary by CodeRabbit
Bug Fixes
AssertExtractor
class.New Features
EbpfMapDescriptor
instances, enhancing detail visibility.EbpfMapDescriptor
objects.string_invariant
objects through move semantics.SplitDBM
class.Refactor
const
in multiple classes for improved code clarity and safety.emplace_back
for better performance.Chores
SplitDBM
class.