-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Execution
-
ALL
-
v8.3
-
QE 2026-03-30, QE 2026-03-16, QE 2026-03-02, QE 2026-02-16
-
None
-
None
-
None
-
None
-
None
-
None
-
None
ExpressionContext use-after-free bug: https://github.com/brian-mongodb/mongodb_chain?tab=readme-ov-file
Bug B: ExpressionContext Use-After-Free
Root Cause
Expression stores a raw pointer to its ExpressionContext (src/mongo/db/pipeline/expression.h:424: ExpressionContext* const _expCtx), not an intrusive_ptr. When $unionWith clones a sub-pipeline, it uses copyForSubPipeline(...) to create a new ExpressionContext for the clone (src/mongo/db/pipeline/document_source_union_with.cpp:112). However, some stage copy constructors shallow-copy Expression objects whose _expCtx still points to the original ExpressionContext. When the original pipeline is destroyed, the ExpressionContext is freed, leaving dangling pointers in the cloned expressions.
Bug sites (both unfixed as of 8.2.x):
$lookup copy ctor: _letVariables(original._letVariables) - src/mongo/db/pipeline/document_source_lookup.cpp:426
$graphLookup copy ctor: _startWith(original._startWith) - src/mongo/db/pipeline/document_source_graph_lookup.cpp:853
The bug triggers during sharded pipeline dispatch (the clone path via ShardServerProcessInterface clones the pipeline for targeting: src/mongo/db/pipeline/sharded_agg_helpers.cpp:1769). A doubly-nested $unionWith is required: the inner $unionWith's clone creates a new ExpressionContext for the sub-pipeline, but the $lookup expressions still reference the outer (freed) ExpressionContext.
- related to
-
SERVER-88439 Use after free in DocumentSourceLookup::clone
-
- Closed
-
-
SERVER-119491 Refactor cloneUsingNewExpCtx in Expression
-
- Open
-