[SERVER-71527] Execution of EPrimBinary leaks memory when operation fails Created: 21/Nov/22  Updated: 29/Oct/23  Resolved: 12/Dec/22

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 6.3.0-rc0

Type: Task Priority: Major - P3
Reporter: Anna Wawrzyniak Assignee: Anna Wawrzyniak
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible
Sprint: QO 2022-12-12, QO 2022-12-26
Participants:

 Description   

Some SBE vm instructions may leak memory if instruction execution throws after operands have been popped from stack, but before the release is called.

Example:

When a division by zero occurs, the Instruction::div will throw without releasing popped operands.

https://github.com/10gen/mongo/blob/master/src/mongo/db/exec/sbe/vm/vm.cpp#L5167

 

As part of the fix, we should inspect other instructions and ensure that they also release the operands in case of execution error.

 

Repro:

TEST_F(SBEPrimBinaryTest, DivMemory) {
    auto& os = gctx->outStream();    auto expr = sbe::makeE<EPrimBinary>(
        EPrimBinary::Op::div,
        sbe::makeE<EPrimBinary>(EPrimBinary::Op::add,
                                makeC(value::makeCopyDecimal(Decimal128(1))),
                                makeC(value::makeCopyDecimal(Decimal128(1)))),
        sbe::makeE<EPrimBinary>(EPrimBinary::Op::sub,
                                makeC(value::makeCopyDecimal(Decimal128(1))),
                                makeC(value::makeCopyDecimal(Decimal128(1)))));
    printInputExpression(os, *expr);    auto compiledExpr = compileExpression(*expr);
    printCompiledExpression(os, *compiledExpr);    executeAndPrintVariation(os, *compiledExpr);
}

==21950==ERROR: LeakSanitizer: detected memory leaksDirect leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x559c483bc262 in operator new[](unsigned long) /data/mci/7a061276a1aa147679600a512115c2c0/toolchain-builder/tmp/build-llvm.sh-UjE/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:109:3
    #1 0x559c483d9262 in mongo::sbe::value::makeCopyDecimal(mongo::Decimal128 const&) /home/ubuntu/mongo/src/mongo/db/exec/sbe/values/value.h:1201:24
    #2 0x559c4e086fee in mongo::sbe::FastTuple<bool, mongo::sbe::value::TypeTags, unsigned long> mongo::sbe::value::genericArithmeticOp<mongo::sbe::value::Subtraction>(mongo::sbe::value::TypeTags, unsigned long, mongo::sbe::value::TypeTags, unsigned long) /home/ubuntu/mongo/src/mongo/db/exec/sbe/values/arith_common.cpp:152:35
    #3 0x559c4d33ef5d in mongo::sbe::vm::ByteCode::runInternal(mongo::sbe::vm::CodeFragment const*, long) /home/ubuntu/mongo/src/mongo/db/exec/sbe/vm/vm.cpp:5345:42
    #4 0x559c4d34d992 in mongo::sbe::vm::ByteCode::run(mongo::sbe::vm::CodeFragment const*) /home/ubuntu/mongo/src/mongo/db/exec/sbe/vm/vm.cpp:6406:9
    #5 0x559c484822d3 in mongo::sbe::EExpressionTestFixture::executeAndPrintVariation(std::ostream&, mongo::sbe::vm::CodeFragment const&) /home/ubuntu/mongo/src/mongo/db/exec/sbe/expression_test_base.h:133:42
    #6 0x559c48511f66 in mongo::sbe::UnitTest_SuiteNameSBEPrimBinaryTestTestNameDivMemory::_doTest() /home/ubuntu/mongo/src/mongo/db/exec/sbe/expressions/sbe_prim_binary_test.cpp:505:5
    #7 0x559c489f35bf in mongo::unittest::Test::run() /home/ubuntu/mongo/src/mongo/unittest/unittest.cpp:244:9
    #8 0x559c4842d0c6 in mongo::sbe::GoldenEExpressionTestFixture::run() /home/ubuntu/mongo/src/mongo/db/exec/sbe/expression_test_base.h:290:15
    #9 0x559c4853955b in mongo::unittest::Test::RegistrationAgent<mongo::sbe::UnitTest_SuiteNameSBEPrimBinaryTestTestNameDivMemory>::RegistrationAgent(mongo::unittest::TestInfo const*)::'lambda'()::operator()() const /home/ubuntu/mongo/src/mongo/unittest/framework.h:344:29
    #10 0x559c489f58ec in mongo::unittest::Suite::run(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) /home/ubuntu/mongo/src/mongo/unittest/unittest.cpp:439:21
    #11 0x559c489f8735 in mongo::unittest::Suite::run(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) /home/ubuntu/mongo/src/mongo/unittest/unittest.cpp:508:26
    #12 0x559c488433bf in main /home/ubuntu/mongo/src/mongo/unittest/unittest_main.cpp:132:19
    #13 0x7fdde6e29c86 in __libc_start_main /build/glibc-uZu3wS/glibc-2.27/csu/../csu/libc-start.c:310 



 Comments   
Comment by Githook User [ 02/Dec/22 ]

Author:

{'name': 'Anna Wawrzyniak', 'email': 'anna.wawrzyniak@mongodb.com', 'username': 'anna-wawrzyniak'}

Message: SERVER-71527 Fix memory leak in sbe vm
Branch: master
https://github.com/mongodb/mongo/commit/6b1381f39315a29215ff347f3c950c1392f71c41

Generated at Thu Feb 08 06:19:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.