ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Critical - P2
    • None
    • Affects Version/s: None
    • Component/s: None
    • DB Integration & Observability
    • ALL
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      hasUnsourcedSetVariableStage() (added in SERVER-131820) treats a $setVariableFromSubPipeline stage whose sub-pipeline is empty as sourced. An empty sub-pipeline has no initial cursor source, so when the shards return no metadata cursors the tassert 13182000 invariant is bypassed and execution later dereferences a null pointer.

      Mechanism

      The helper added in SERVER-131820 is:

      if (subPipeline && !subPipeline->empty() &&
          subPipeline->front()->constraints(...).requiresInputDocSource) {
          return true;
      }
      

      Because of the !subPipeline->empty() guard, an empty sub-pipeline returns false ("sourced").

      If a query references $$SEARCH_META (requiresSearchMetaCursor = true) and planShardedSearch returns an empty metaPipeline (mergingPipeline: []), a DocumentSourceSetVariableFromSubPipeline with an empty sub-pipeline is attached. If the shards then return only unlabeled cursors, injectMetaCursor() is not called and the sub-pipeline stays empty. tassert 13182000 then passes, and execution dereferences a null pointer:
      * v8.0: DocumentSourceSetVariableFromSubPipeline::doGetNext() -- _subPipeline->peekFront()->constraints()
      * v9.0/v8.3: SetVariableFromSubPipelineStage::doGetNext() -- same
      Pipeline::peekFront() returns nullptr when the pipeline is empty.

      Reachability

      Requires all of: (a) the user pipeline references $$SEARCH_META, (b) mongot returns an empty metaPipeline, (c) the shards return unlabeled cursors (no metadata cursors). It is not known whether (b) occurs in production; if mongot never returns an empty metaPipeline for a SEARCH_META-referencing query, this path is dead code.

      Fix

      Treat an empty sub-pipeline as unsourced:

      if (subPipeline && (subPipeline->empty() ||
              subPipeline->front()->constraints(...).requiresInputDocSource)) {
          return true;
      }
      

      This cannot cause false positives: injectMetaCursor() prepends a $mergeCursors source, so a legitimately-sourced sub-pipeline is never empty at the check.

      Affected versions

      Introduced by SERVER-131820 on master and backported to v9.0 (BACKPORT-29973), v8.3 (BACKPORT-29974), and v8.0 (BACKPORT-29975).

            Assignee:
            Unassigned
            Reporter:
            Mariano Shaar
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: