Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

ffi: Fix Serializer to invalidate msgpack maps with non-string keys and msgpack arrays with unsupported types. #570

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

Conversation

LinZhihao-723
Copy link
Member

@LinZhihao-723 LinZhihao-723 commented Nov 1, 2024

Description

msgpack allows users to use non-string types for keys in a map (key-value pairs). However, in our key-value pair IR format, we do not allow non-string key types. Before this PR, we don't have checks in our serializer but assuming the inputs keys are always strings. This PR adds validations to the key types to validate only serializable msgpack objects.
Similarly, before this PR, we need to validate whether the msgpack array contains unsupported types such as binary objects. This PR adds checks to invalidate arrays with unsupported types, or any submap with non-string keys. This ensures the serialized unstructured array can always be serialized as a JSON string. Ideally, the array check can be added to PR #465

Validation performed

  • Ensure workflow built
  • Added new unit tests to assert serialization failures on the cases described above; ensure these unit tests passed only with changes introduced in this PR

Summary by CodeRabbit

  • New Features

    • Enhanced serialization for MessagePack data structures, including validation for array and map serialization.
    • Introduced a depth-first search (DFS) method for improved map serialization.
  • Bug Fixes

    • Improved handling of non-string keys in maps to prevent serialization errors.
  • Tests

    • Added new tests to validate serialization failure scenarios with invalid input types.

Copy link
Contributor

coderabbitai bot commented Nov 1, 2024

Walkthrough

The pull request introduces enhancements to the serialization logic for MessagePack data structures in the Serializer class. A new method, is_msgpack_array_serializable, is added to validate MessagePack arrays before serialization. The serialization of maps is refactored to use a depth-first search approach via the new method serialize_msgpack_map_using_dfs, which includes transaction management for error handling. Additionally, tests are updated to cover new scenarios, including the handling of invalid input types, ensuring robust serialization and deserialization processes.

Changes

File Path Change Summary
components/core/src/clp/ffi/ir_stream/Serializer.cpp - Added is_msgpack_array_serializable method for array validation.
- Refactored map serialization to serialize_msgpack_map_using_dfs with DFS logic and transaction management.
- Updated existing serialization logic to incorporate new methods and validation checks.
components/core/src/clp/ffi/ir_stream/Serializer.hpp - Added serialize_msgpack_map_using_dfs method for DFS-based serialization of MessagePack maps.
components/core/tests/test-ir_encoding_methods.cpp - Added unpack_and_assert_serialization_failure template function for testing serialization failures.
- Introduced test case ffi_ir_stream_Serializer_serialize_invalid_msgpack for invalid input scenarios.

Possibly related PRs

Suggested reviewers

  • davidlion

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Comment on lines +494 to +497
if (msgpack::type::STR != key.type) {
// A map containing non-string keys is not serializable
return false;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This function is split from the previous serialize_msgpack_map to resolve clang-tidy cognitive complexity issue. The only major change is this if-statement.
Some other changes:

  • Using TransactionManager to handle failure recovery
  • Rewrite the code in a way that it has less else block

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
components/core/src/clp/ffi/ir_stream/Serializer.hpp (1)

119-126: Enhance method documentation with more details.

The documentation for serialize_msgpack_map_using_dfs should be expanded to include:

  • The DFS traversal strategy and its benefits
  • Error handling behaviour
  • Validation rules for map keys
  • Any transaction management details

Here's a suggested documentation improvement:

    /**
     * Serializes the given msgpack map using depth-first search (DFS).
+     * 
+     * Uses a depth-first search approach to traverse the msgpack map structure, which:
+     * - Validates that all keys are strings
+     * - Handles nested maps and arrays
+     * - Supports transaction-based error handling
+     * 
     * @param msgpack_map The MessagePack map to serialize
+     * @throws May throw if memory allocation fails during serialization
     * @return Whether the serialization succeeded.
     */
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6a6ce and ec37d35.

📒 Files selected for processing (3)
  • components/core/src/clp/ffi/ir_stream/Serializer.cpp (6 hunks)
  • components/core/src/clp/ffi/ir_stream/Serializer.hpp (1 hunks)
  • components/core/tests/test-ir_encoding_methods.cpp (4 hunks)
🧰 Additional context used
🪛 cppcheck
components/core/src/clp/ffi/ir_stream/Serializer.cpp

[error] 246-246: Syntax Error

(internalAstError)

🔇 Additional comments (8)
components/core/src/clp/ffi/ir_stream/Serializer.hpp (1)

119-126: Consider architectural implications of DFS implementation.

The DFS approach for map serialization suggests a potentially deep recursion stack. Consider:

  1. Adding a maximum depth limit to prevent stack overflow
  2. Documenting memory usage characteristics
  3. Adding stack depth tracking for debugging

Let's check if there are any existing depth limits in the codebase:

components/core/tests/test-ir_encoding_methods.cpp (1)

214-226: Declaration of unpack_and_assert_serialization_failure is correct

The function declaration is clear, well-documented, and follows proper template syntax.

components/core/src/clp/ffi/ir_stream/Serializer.cpp (6)

19-19: Include TransactionManager.hpp is appropriate

The addition of #include "../../TransactionManager.hpp" is necessary for transaction management in the new serialization logic.


149-157: Well-documented declaration of is_msgpack_array_serializable

The function is_msgpack_array_serializable is clearly declared with comprehensive documentation, enhancing code readability and maintainability.


239-241: Proper validation added for MessagePack arrays in serialize_value_array

The check if (false == is_msgpack_array_serializable(val)) ensures that only serializable arrays are processed, preventing potential runtime errors with unsupported types.


345-347: Refactored map serialization logic enhances modularity

The refactoring to use serialize_msgpack_map_using_dfs improves code organisation and modularity, making the serialization process more maintainable.


469-554: Effective implementation of DFS in serialize_msgpack_map_using_dfs

The depth-first search approach for serializing MessagePack maps is well-implemented, with appropriate transaction management via TransactionManager. The checks for non-string keys and unsupported types enhance the robustness of the serialization process.


595-600: Correct addition of explicit template instantiations

The explicit template instantiations for serialize_msgpack_map_using_dfs ensure that the method is properly instantiated for both eight_byte_encoded_variable_t and four_byte_encoded_variable_t, avoiding potential linker errors.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
components/core/tests/test-ir_encoding_methods.cpp (2)

214-225: Consider enhancing function documentation.

The documentation could be more specific about the expected behavior and return value conditions.

Add more details to the documentation:

 /**
  * Unpacks and asserts the serialization of the msgpack bytes fails.
  * @tparam encoded_variable_t
  * @param buffer A buffer containing msgpack byte sequence.
  * @param serializer
- * @return Whether serialization failed with the underlying IR buffer being empty.
+ * @return true if:
+ *         1. The input is a valid msgpack map
+ *         2. Serialization fails as expected
+ *         3. The IR buffer is empty after the failure
+ *         false otherwise
  */

1348-1382: Comprehensive test coverage for invalid msgpack scenarios.

The test cases effectively cover:

  • Maps with non-string keys
  • Nested invalid maps
  • Arrays with invalid types
  • Nested arrays with invalid elements

Consider adding test cases for:

  • Empty maps with non-string keys
  • Maps with mixed valid and invalid keys

Would you like me to help generate additional test cases for these scenarios?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ec37d35 and a28079a.

📒 Files selected for processing (1)
  • components/core/tests/test-ir_encoding_methods.cpp (4 hunks)
🧰 Additional context used
📓 Learnings (1)
components/core/tests/test-ir_encoding_methods.cpp (1)
Learnt from: LinZhihao-723
PR: y-scope/clp#570
File: components/core/tests/test-ir_encoding_methods.cpp:376-399
Timestamp: 2024-11-01T03:26:26.386Z
Learning: In the test code (`components/core/tests/test-ir_encoding_methods.cpp`), exception handling for `msgpack::unpack` can be omitted because the Catch2 testing framework captures exceptions if they occur.
🔇 Additional comments (2)
components/core/tests/test-ir_encoding_methods.cpp (2)

376-399: Implementation looks good!

The function correctly validates serialization failures and buffer state.


1328-1347: Well-structured test setup with reusable validation.

The test case is well-organized with a reusable lambda for common validation logic.

auto const& as_array{curr->via.array};
for (auto const& obj : span{as_array.ptr, as_array.size}) {
switch (obj.type) {
case msgpack::type::BIN:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not necessarily but can we treat it as an Array<number>?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants