fix(hgraph): add null check in GetVectorByInnerId to prevent crash during Tune#1761
Hidden character warning
fix(hgraph): add null check in GetVectorByInnerId to prevent crash during Tune#1761LHT129 wants to merge 1 commit intoantgroup:mainfrom
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request resolves a critical segmentation fault in the HGraph algorithm. The issue stemmed from an incorrect sequence of operations during the Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request addresses a SIGSEGV crash in HGraph::Tune by adding null checks for high_precise_codes_ and raw_vector_ within the HGraph::GetVectorByInnerId function. This prevents dereferencing null pointers when use_reorder_ is true but high_precise_codes_ has not yet been initialized. A new test case, HGraph Tune with ignore_reorder, has been added to validate the fix. The reviewer suggests improving the readability of the codes selection logic in GetVectorByInnerId by using an if-else if-else structure and recommends applying similar null checks to CalcDistanceById to prevent potential crashes in related code paths.
src/algorithm/hgraph.cpp
Outdated
| auto codes = (use_reorder_ and high_precise_codes_ != nullptr) ? high_precise_codes_ | ||
| : basic_flatten_codes_; | ||
| codes = (create_new_raw_vector_ and raw_vector_ != nullptr) ? raw_vector_ : codes; |
There was a problem hiding this comment.
While the added null checks fix the crash, the logic for selecting codes can be made more readable and less error-prone by avoiding the overwrite pattern. A single if-else if-else block would clarify the priority of which codes implementation to use.
This makes the code easier to understand and maintain.
Additionally, similar potentially unsafe logic exists in CalcDistanceById (lines 1486-1492 and 1500-1506) where high_precise_codes_ or raw_vector_ could be assigned without a null check. It would be beneficial to apply a similar fix in those locations as well to prevent potential crashes.
FlattenInterfacePtr codes;
if (create_new_raw_vector_ and raw_vector_ != nullptr) {
codes = raw_vector_;
} else if (use_reorder_ and high_precise_codes_ != nullptr) {
codes = high_precise_codes_;
} else {
codes = basic_flatten_codes_;
}There was a problem hiding this comment.
Pull request overview
Fixes a crash in HGraph::GetVectorByInnerId during Tune when transitioning to reorder mode before high_precise_codes_ is initialized, and adds a regression test for the ignore_reorder Tune scenario.
Changes:
- Add nullptr-aware selection of code storage in
GetVectorByInnerIdto avoid dereferencinghigh_precise_codes_/raw_vector_when unset. - Add a unit test covering
Tunewithuse_reorder=true+ignore_reorder=true. - Add planning/task markdown files documenting the fix approach.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/algorithm/hgraph.cpp |
Prevents null dereference by falling back to basic codes/raw vectors only when available. |
tests/test_hgraph.cpp |
Adds a regression test for Tune with ignore_reorder and validates search behavior afterwards. |
plan.md |
Documents analysis and implementation plan for the crash fix. |
TASK.md |
Points to a local task file path used during development. |
Comments suppressed due to low confidence (1)
TASK.md:1
- This file hard-codes an absolute local filesystem path, which is not portable and can leak developer environment details into the repo. Suggest removing
TASK.mdfrom the PR, or replacing it with a repo-relative reference (or a short description) that works for all contributors.
| auto origin_size = vsag::Options::Instance().block_size_limit(); | ||
| auto size = 1024 * 1024 * 2; | ||
| vsag::Options::Instance().set_block_size_limit(size); |
There was a problem hiding this comment.
set_block_size_limit(origin_size) will not run if a REQUIRE(...) fails (Catch2 aborts the test case immediately), which can leak global state into subsequent tests and cause cascading failures. Use an RAII guard (e.g., a small local struct with destructor, or a scope-exit helper) to restore block_size_limit regardless of assertion outcomes.
| auto tune_result = index->Tune(param2, true); | ||
| REQUIRE(tune_result.has_value()); | ||
| REQUIRE(tune_result.value()); |
There was a problem hiding this comment.
set_block_size_limit(origin_size) will not run if a REQUIRE(...) fails (Catch2 aborts the test case immediately), which can leak global state into subsequent tests and cause cascading failures. Use an RAII guard (e.g., a small local struct with destructor, or a scope-exit helper) to restore block_size_limit regardless of assertion outcomes.
| auto search_param = fmt::format(fixtures::search_param_tmp, 200, false); | ||
| HGraphTestIndex::TestGeneral(index, dataset, search_param, 0.7); | ||
|
|
||
| vsag::Options::Instance().set_block_size_limit(origin_size); |
There was a problem hiding this comment.
set_block_size_limit(origin_size) will not run if a REQUIRE(...) fails (Catch2 aborts the test case immediately), which can leak global state into subsequent tests and cause cascading failures. Use an RAII guard (e.g., a small local struct with destructor, or a scope-exit helper) to restore block_size_limit regardless of assertion outcomes.
plan.md
Outdated
| - hgraph.cpp:520-630 (Tune 函数) | ||
| - hgraph.cpp:2071-2080 (GetVectorByInnerId 函数) | ||
| - **关联Issue**: https://github.com/antgroup/vsag/issues/1760 | ||
| - **原始任务**: /home/tianlan.lht/code/workspace/agent-hive/tasks/in_progress/2026-03-26-修复-hgraph-tune-时-getvectorbyinnerid-崩溃.md No newline at end of file |
There was a problem hiding this comment.
plan.md includes an absolute local path under “原始任务”, which has the same portability and information disclosure concerns as TASK.md. Remove the absolute path or replace it with a repo-relative location (or omit it entirely).
| - **原始任务**: /home/tianlan.lht/code/workspace/agent-hive/tasks/in_progress/2026-03-26-修复-hgraph-tune-时-getvectorbyinnerid-崩溃.md | |
| - **原始任务**: tasks/in_progress/2026-03-26-修复-hgraph-tune-时-getvectorbyinnerid-崩溃.md |
src/algorithm/hgraph.cpp
Outdated
| auto codes = (use_reorder_ and high_precise_codes_ != nullptr) ? high_precise_codes_ | ||
| : basic_flatten_codes_; | ||
| codes = (create_new_raw_vector_ and raw_vector_ != nullptr) ? raw_vector_ : codes; |
There was a problem hiding this comment.
The code uses the alternative token and instead of the more commonly used && in C++ codebases; if the surrounding file/project consistently uses &&, switching to && here will improve consistency and reduce surprise for readers/tools.
| auto codes = (use_reorder_ and high_precise_codes_ != nullptr) ? high_precise_codes_ | |
| : basic_flatten_codes_; | |
| codes = (create_new_raw_vector_ and raw_vector_ != nullptr) ? raw_vector_ : codes; | |
| auto codes = (use_reorder_ && high_precise_codes_ != nullptr) ? high_precise_codes_ | |
| : basic_flatten_codes_; | |
| codes = (create_new_raw_vector_ && raw_vector_ != nullptr) ? raw_vector_ : codes; |
a66a9ff to
bc1ccf6
Compare
2480a76 to
5c881b4
Compare
| auto origin_size = vsag::Options::Instance().block_size_limit(); | ||
| auto size = 1024 * 1024 * 2; | ||
| vsag::Options::Instance().set_block_size_limit(size); | ||
|
|
There was a problem hiding this comment.
The test mutates a global singleton option (block_size_limit) and restores it only at the end of the test. If any REQUIRE(...) before line 1062 fails, the restore line will not run, potentially leaking global state into subsequent tests and causing flaky failures. Prefer an RAII guard (scope-exit / destructor-based restorer) that resets block_size_limit even on early returns/assert failures.
| bool need_enable_reorder = false; | ||
| if (not use_reorder_ and inner_parameter->use_reorder) { | ||
| // [case 4] assign new precise_code | ||
| use_reorder_ = true; | ||
| need_enable_reorder = true; |
There was a problem hiding this comment.
The PR description says null checks were added in GetVectorByInnerId for high_precise_codes_ and raw_vector_, but the provided diff only shows deferring use_reorder_ enabling in Tune(...) (plus a test). If null checks are part of the intended fix, they appear to be missing from this change set; otherwise, please update the PR title/description to match the actual fix.
| REQUIRE(search_result.value()->GetDim() > 0); | ||
|
|
There was a problem hiding this comment.
The final assertion GetDim() > 0 is very weak for validating the post-tune search path, and it may pass even if the result shape/top-k is incorrect. Consider asserting more specific invariants such as returned topk == 5, NumElements == 1 (if applicable in this API), and/or that returned IDs fall within GetMinAndMaxId() range. This makes the regression test more robust and easier to diagnose when it fails.
| REQUIRE(search_result.value()->GetDim() > 0); | |
| auto result = search_result.value(); | |
| // Validate that the search result has the expected shape and IDs. | |
| REQUIRE(result->GetDim() == 5); | |
| REQUIRE(result->GetNumElements() == 1); | |
| auto id_range = base_range.value(); | |
| auto* ids = result->GetIds(); | |
| REQUIRE(ids != nullptr); | |
| for (int64_t i = 0; i < result->GetDim(); ++i) { | |
| REQUIRE(ids[i] >= id_range.first); | |
| REQUIRE(ids[i] <= id_range.second); | |
| } |
5c881b4 to
fead75d
Compare
fead75d to
2b29f12
Compare
- Delay use_reorder_ assignment until after high_precise_codes_ is populated - Add null check for high_precise_codes_ and raw_vector_ in GetVectorByInnerId - Add unit test for Tune with ignore_reorder scenario - Sync param->use_reorder when enabling reorder in Tune Fixes antgroup#1760 Signed-off-by: LHT129 <tianlan.lht@antgroup.com>
2b29f12 to
af7f4cc
Compare
| @@ -616,6 +617,11 @@ HGraph::Tune(const std::string& parameters, bool disable_future_tuning) { | |||
| high_precise_codes_ = | |||
| tune_and_rebuild(is_tune_precise_code, high_precise_codes_, new_precise_code); | |||
|
|
|||
| if (need_enable_reorder) { | |||
| use_reorder_ = true; | |||
| param->use_reorder = true; | |||
| } | |||
There was a problem hiding this comment.
The PR description mentions adding null checks in HGraph::GetVectorByInnerId for high_precise_codes_/raw_vector_, but the change here only defers setting use_reorder_ until after high_precise_codes_ is rebuilt. If the intent is defensive hardening beyond this Tune transition, please either (a) add the promised null checks in GetVectorByInnerId (and define the expected fallback/error behavior), or (b) update the PR description to match the actual fix.
Summary
This PR fixes a crash bug in HGraph::GetVectorByInnerId when Tune transitions from no-reorder to reorder mode. The crash occurs because
use_reorder_is set to true beforehigh_precise_codes_is populated, leading to a null pointer dereference.Changes
high_precise_codes_before using it in GetVectorByInnerIdraw_vector_before using it in GetVectorByInnerIdRoot Cause
When Tune transitions from no-reorder to reorder mode:
use_reorder_is set to true (line 576)use_reorder_to select codes (line 2072)high_precise_codes_is still nullptr, accessing it causes SIGSEGVTesting
Related Issues
Fixes #1760
Checklist