summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew Paroski <drew.paroski@mongodb.com>2021-12-27 20:46:32 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-28 21:49:45 +0000
commit6888896c6ee5a38f6648647e8a7d288d286f44ad (patch)
treeb54677e3b0b0ffc93ef8106b498e731641fdccb9
parent073d0a252ed3e820e685fe227779400881df17bf (diff)
downloadmongo-6888896c6ee5a38f6648647e8a7d288d286f44ad.tar.gz
SERVER-62146 [SBE] Fix use-after-free bug with $arrayElemAt, $first, and $last
(cherry picked from commit 168086cae37581eeaa7513bfa3976cf554ffc79a) (cherry picked from commit e7234e51120edcc9bd67f0e0890c48b27df39397)
-rw-r--r--src/mongo/db/query/sbe_stage_builder_expression.cpp27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp
index ee06018885f..4eb3537b626 100644
--- a/src/mongo/db/query/sbe_stage_builder_expression.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp
@@ -271,8 +271,14 @@ void buildArrayAccessByConstantIndex(ExpressionVisitorContext* context,
int32_t index) {
context->ensureArity(1);
- auto array = context->popExpr();
-
+ // It's important that we project the array to a slot here. If we didn't do this, then the
+ // view of the array element could potentially outlive the array itself (which could result
+ // in use-after-free bugs).
+ auto [arraySlot, stage] = projectEvalExpr(context->popEvalExpr(),
+ context->extractCurrentEvalStage(),
+ context->planNodeId,
+ context->state.slotIdGenerator);
+ auto array = makeVariable(arraySlot);
auto frameId = context->state.frameId();
auto binds = sbe::makeEs(std::move(array));
sbe::EVariable arrayRef{frameId, 0};
@@ -288,8 +294,8 @@ void buildArrayAccessByConstantIndex(ExpressionVisitorContext* context,
exprName + " argument must be an array")},
makeFunction("getElement", arrayRef.clone(), std::move(indexExpr)));
- context->pushExpr(
- sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(resultExpr)));
+ context->pushExpr(sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(resultExpr)),
+ std::move(stage));
}
/**
@@ -887,7 +893,15 @@ public:
_context->ensureArity(2);
auto index = _context->popExpr();
- auto array = _context->popExpr();
+
+ // It's important that we project the array to a slot here. If we didn't do this, then the
+ // view of the array element could potentially outlive the array itself (which could result
+ // in use-after-free bugs).
+ auto [arraySlot, stage] = projectEvalExpr(_context->popEvalExpr(),
+ _context->extractCurrentEvalStage(),
+ _context->planNodeId,
+ _context->state.slotIdGenerator);
+ auto array = makeVariable(arraySlot);
auto frameId = _context->state.frameId();
auto binds = sbe::makeEs(std::move(array), std::move(index));
@@ -928,7 +942,8 @@ public:
makeFunction("getElement", arrayRef.clone(), std::move(int32Index)));
_context->pushExpr(
- sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(arrayElemAtExpr)));
+ sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(arrayElemAtExpr)),
+ std::move(stage));
}
void visit(const ExpressionFirst* expr) final {
buildArrayAccessByConstantIndex(_context, expr->getOpName(), 0);