fix(cpp): remove UB when reading unset builder vertex id#892
fix(cpp): remove UB when reading unset builder vertex id#892Sober7135 wants to merge 2 commits intoapache:mainfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #892 +/- ##
============================================
+ Coverage 79.81% 79.87% +0.05%
Complexity 615 615
============================================
Files 93 93
Lines 10296 10296
Branches 1055 1055
============================================
+ Hits 8218 8224 +6
+ Misses 1838 1832 -6
Partials 240 240
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes undefined behavior in the C++ high-level builder API by ensuring builder::Vertex IDs are never read uninitialized, and updates C++/Python tests to reflect the new semantics (ID presence is independent from “emptiness”, which now refers to property payload).
Changes:
- Change
builder::Vertex::id_tostd::optional<IdType>and addHasId(); makeGetId()fail when unset. - Remove redundant
empty_state frombuilder::Vertexand deriveEmpty()fromproperties_.empty(). - Add/adjust C++ and Python tests covering unset IDs,
SetId(), and the updatedEmpty()behavior.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
cpp/src/graphar/high-level/vertices_builder.h |
Switch vertex id storage to std::optional, add HasId(), and redefine Empty() based on property payload. |
cpp/test/test_builder.cc |
Add C++ coverage for unset-id behavior and updated Empty() semantics. |
python/test/test_high_level_api.py |
Add Python coverage for unset-id behavior and updated Empty() semantics. |
python/src/bindings/high_level_binding.cc |
Trivial formatting/line-number-only diff at file end. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| IdType GetId() const { return id_.value(); } | ||
|
|
There was a problem hiding this comment.
GetId() currently calls id_.value(), which throws std::bad_optional_access with an unhelpful default message when the id is unset (this also propagates as a generic runtime error in the Python bindings). Consider checking HasId() and throwing a more descriptive exception (or providing a non-throwing accessor) so users get a clear failure reason.
| * The id is absent until explicitly set or assigned by VerticesBuilder. | ||
| * | ||
| * @return The id of the vertex. |
There was a problem hiding this comment.
The new doc comment says the id may be “assigned by VerticesBuilder”, but it doesn’t clarify whether that id is relative to the builder (0..N-1) or includes start_vertex_index_. Since AddVertex(..., index=-1) assigns vertices_.size() today, consider clarifying this wording to avoid misleading API users about what id they will observe.
| with pytest.raises(Exception): | ||
| empty_vertex.GetId() | ||
| empty_vertex.SetId(42) |
There was a problem hiding this comment.
The test uses with pytest.raises(Exception) for GetId() on an unset id, which is very broad and can hide unrelated failures. It would be more robust to assert the specific exception type raised by the binding (and ideally match the message) so the test only passes for the intended behavior.
|
I agree this works! please note copilot's comment, thank you~ |
|
It seems that Because incubator-graphar/cpp/src/graphar/high-level/vertices_builder.h Lines 329 to 346 in 080a2f6 This is strange and misleading. |
Reason for this PR
#846
What changes are included in this PR?
builder::Vertexid asstd::optional<IdType>instead of an uninitialized scalarGetId()fail explicitly when the id is unset, instead of reading uninitialized memoryempty_flag frombuilder::VertexEmpty()fromproperties_.empty()so vertex emptiness is no longer tracked by redundant mutable stateSetId()/ constructor-initialized id behaviorEmpty()behavior after removing the storedempty_fieldAre these changes tested?
Yes
Are there any user-facing changes?
Yes