[Bug] BE UT coredump: Bad cast from IdentityWrapperExpr* to VSlotRef* due to uninitialized _node_type
- Dominant language
- Java
- Stars
- 15.9k
- Forks
- 3.9k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 520
Description
### Search before asking
- [X] I had searched in the [issues](https://github.com/apache/doris/issues) and found no similar issues.
### Version
master (trunk)
### What's Wrong?
BE unit test `RuntimeFilterPartitionPrunerTest.ProjectedBoundariesPreserveOpenRangeBounds` coredumps with:
```
F20260607 15:48:06.595517 53695 status.h:472] Bad cast from type:doris::IdentityWrapperExpr* to doris::VSlotRef*
*** Check failure stack trace: ***
@ 0x560338957138 doris::Status::FatalError<>()
@ 0x56033a2b421e assert_cast<>()
@ 0x56033f7942ab doris::ParsedPartitionBoundaries::get_or_compute_projected_boundaries()
@ 0x56033a19cd1d doris::RuntimeFilterPartitionPrunerTest_ProjectedBoundariesPreserveOpenRangeBounds_Test::TestBody()
```
### What You Expected?
UT should pass without coredump.
### How to Reproduce?
1. Build BE with `-DCMAKE_BUILD_TYPE=DEBUG` on x86
2. Run `bash run-be-ut.sh`
3. Observe coredump at `RuntimeFilterPartitionPrunerTest.ProjectedBoundariesPreserveOpenRangeBounds`
### Root Cause
`VExpr::VExpr(DataTypePtr, bool)` constructor does not initialize `_node_type` member variable when `is_slotref=false`:
```cpp
VExpr::VExpr(DataTypePtr type, bool is_slotref)
: _opcode(TExprOpcode::INVALID_OPCODE),
_data_type(get_data_type_with_default_argument(type)) {
if (is_slotref) {
_node_type = TExprNodeType::SLOT_REF;
}
// is_slotref=false: _node_type is UNINITIALIZED!
}
```
`_node_type` has no in-class default initializer (`vexpr.h:429`):
```cpp
TExprNodeType::type _node_type; // no default value
```
When `is_slotref=false`, `_node_type` contains an uninitialized stack residual value. If this residual value happens to equal `TExprNodeType::SLOT_REF`, `is_slot_ref()` incorrectly returns `true`, causing `assert_cast` to fail.
This is undefined behavior (UB) and is non-deterministic across build types, compiler versions, and call paths. It is more likely to manifest under DEBUG (`-O0`) due to raw stack layout.
### Fix
Initialize `_node_type` in the constructor initializer list:
```cpp
VExpr::VExpr(DataTypePtr type, bool is_slotref)
: _node_type(is_slotref ? TExprNodeType::SLOT_REF : TExprNodeType::INVALID_OPCODE),
_opcode(TExprOpcode::INVALID_OPCODE),
_data_type(get_data_type_with_default_argument(type)) {}
```
### Are you willing to submit PR?
- [X] Yes I am willing to submit a PR!
Contributor guide
Assessment
This issue has not been assessed yet.