A range-for over a member of a temporary reads freed memory
Symptom#
Clang warns, and the loop sees wrong or missing elements:
warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
The code looked like this:
for
if return e;
In the observed case the loop did not find an element that the container did hold, and four doctest cases failed with REQUIRE( e ) is NOT correct!.
The same bug can give no warning at all. With simdjson, this loop compiled clean and passed every normal test, but AddressSanitizer stopped it:
for
ERROR: AddressSanitizer: stack-use-after-scope ... in simdjson::internal::tape_ref::usable() const
Cause#
A range-for keeps alive only the object that the range expression returns directly. Here that is a reference into a temporary: the std::vector that manifest() returned, or the simdjson_result<dom::array> that get_array() returned (value_unsafe() on an rvalue result returns a reference into it). The temporary is destroyed at the end of the full expression, before the loop runs, so the loop reads freed memory. Lifetime extension does not reach through a member access, at() or value_unsafe().
Fix#
Store the temporary in a named local first, then loop over the member:
const auto manifest = ix.;
for
if return e;
const simdjson::dom::array arr = v..;
for
C++23 extends the lifetime of temporaries in the range initializer (P2718), but do not rely on it in C++20 code. Treat -Wdangling-gsl as an error to fix, not as noise, and search for the pattern (for (.*:.*value_unsafe())) because the compiler does not always warn.
Evidence#
- Clang on macOS (Apple clang, C++20) printed the warning for the manifest loop in
tests/utilities/plugins/test_plugin_index_extension.cpp(dftracer-utils). With the loop as written, 4 of 5 test cases failed atREQUIRE( e ); with the named local all 5 passed and the warning was gone. - The simdjson loop was in the duql evaluator's
any()check and inappend_canonical_json(src/dftracer/utils/json/canonical.cpp), in dftracer-utils. No compiler warning; the asan-ubsan build ofduql/test_evaluatorandduql/test_differentialfailed with stack-use-after-scope. After binding the array or object to a named local, the same tests passed under ASan and UBSan (2026-09-28).