Description
ReadFromGlutenStorageKafka stores its column_names as a reference member:
// cpp-ch/local-engine/Storages/Kafka/ReadFromGlutenStorageKafka.h:52
const Names & column_names;
initialized from the constructor's const Names & column_names_ parameter (ReadFromGlutenStorageKafka.cpp:53). The sole construction site binds it to a local that goes out of scope before the step runs:
// cpp-ch/local-engine/Parser/RelParsers/StreamKafkaRelParser.cpp:102-107
Names names = header->getNames();
auto source = std::make_unique<ReadFromGlutenStorageKafka>(
names, header, getContext(), topics, partition, start_offset, end_offset, poll_timeout_ms, group_id, brokers);
steps.emplace_back(source.get());
query_plan->addStep(std::move(source)); // the step outlives `names`
names is destroyed when parse() returns, but the step (and its column_names reference) lives on in the query plan and runs later in initializePipeline. The reference dangles.
Impact
Latent today: column_names is never actually dereferenced — it is stored in the constructor but read nowhere (makePipe/initializePipeline/createKafkaSettings don't touch it; the Kafka source derives its schema from output_header instead). So it is a harmless-but-real dangling reference and a footgun: any future read of column_names would touch freed memory.
Fix
Either make it an owning value member — Names column_names; (drop the &) so it copies at construction — or remove the unused member entirely (and drop the now-unused column_names_ constructor parameter). Given it has no readers, removing it is the cleaner option.
Notes
Pre-existing; not introduced by the Substrait-0.98 rebase (#12597) — surfaced while reviewing this file for the Kafka ExtensionTable remodel (#12841). By contrast the sibling topics member is stored by value (Names topics;), so only column_names is affected.
Description
ReadFromGlutenStorageKafkastores itscolumn_namesas a reference member:initialized from the constructor's
const Names & column_names_parameter (ReadFromGlutenStorageKafka.cpp:53). The sole construction site binds it to a local that goes out of scope before the step runs:namesis destroyed whenparse()returns, but the step (and itscolumn_namesreference) lives on in the query plan and runs later ininitializePipeline. The reference dangles.Impact
Latent today:
column_namesis never actually dereferenced — it is stored in the constructor but read nowhere (makePipe/initializePipeline/createKafkaSettingsdon't touch it; the Kafka source derives its schema fromoutput_headerinstead). So it is a harmless-but-real dangling reference and a footgun: any future read ofcolumn_nameswould touch freed memory.Fix
Either make it an owning value member —
Names column_names;(drop the&) so it copies at construction — or remove the unused member entirely (and drop the now-unusedcolumn_names_constructor parameter). Given it has no readers, removing it is the cleaner option.Notes
Pre-existing; not introduced by the Substrait-0.98 rebase (#12597) — surfaced while reviewing this file for the Kafka
ExtensionTableremodel (#12841). By contrast the siblingtopicsmember is stored by value (Names topics;), so onlycolumn_namesis affected.