diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0cbefbc2..7338792d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,6 +30,27 @@ jobs: sudo make install make test + build-linux-sanitizers: + name: build-linux-sanitizers (asan, ubsan) + runs-on: ubuntu-26.04 + steps: + - name: install-deps + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends cmake g++ libcppunit-dev libgnutls28-dev libgsasl-dev libicu-dev make pkg-config + - name: clone-vmime + uses: actions/checkout@v4 + - name: buildall + env: + ASAN_OPTIONS: detect_leaks=1 + LSAN_OPTIONS: suppressions=${{ github.workspace }}/tests/lsan.supp + UBSAN_OPTIONS: print_stacktrace=1 + run: | + set -ex + cmake . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" -DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=address,undefined" -DVMIME_SENDMAIL_PATH:STRING="/usr/sbin/sendmail" -DVMIME_HAVE_TLS_SUPPORT:BOOL=ON -DVMIME_TLS_SUPPORT_LIB:STRING=gnutls -DVMIME_CHARSETCONV_LIB:STRING=icu -DVMIME_BUILD_TESTS=ON -DVMIME_BUILD_SAMPLES=OFF + make "-j$(nproc)" + ctest --output-on-failure + build-cygwin: name: build-cygwin (openssl, iconv) runs-on: windows-latest diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index 4c239dbe..0ea2d4de 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -4767,8 +4767,7 @@ class VMIME_EXPORT IMAPParser : public object { template TYPE* get(string& line, size_t* currentPos) { - component* resp = new TYPE; - return internalGet (resp, line, currentPos); + return internalGet (std::unique_ptr (new TYPE), line, currentPos); } /** Parse a token which takes 2 arguments and advance. @@ -4788,14 +4787,13 @@ class VMIME_EXPORT IMAPParser : public object { template TYPE* getWithArgs(string& line, size_t* currentPos, ARG1_TYPE arg1, ARG2_TYPE arg2) { - component* resp = new TYPE(arg1, arg2); - return internalGet (resp, line, currentPos); + return internalGet (std::unique_ptr (new TYPE(arg1, arg2)), line, currentPos); } private: template - TYPE* internalGet(component* resp, string& line, size_t* currentPos) { + TYPE* internalGet(std::unique_ptr resp, string& line, size_t* currentPos) { const size_t oldPos = *currentPos; @@ -4803,12 +4801,10 @@ class VMIME_EXPORT IMAPParser : public object { *currentPos = oldPos; - delete resp; - return NULL; } - return static_cast (resp); + return resp.release(); } const string lastLine() const { diff --git a/tests/lsan.supp b/tests/lsan.supp new file mode 100644 index 00000000..30440dcd --- /dev/null +++ b/tests/lsan.supp @@ -0,0 +1,4 @@ +# LeakSanitizer suppressions for leaks in third-party libraries + +# Buffer allocated by glibc in newlocale(), called by std::locale and libp11-kit +leak:newlocale diff --git a/tests/net/imap/IMAPParserTest.cpp b/tests/net/imap/IMAPParserTest.cpp index dab31e2b..e671fee3 100644 --- a/tests/net/imap/IMAPParserTest.cpp +++ b/tests/net/imap/IMAPParserTest.cpp @@ -81,7 +81,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(vmime::make_shared ()); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); } } @@ -113,7 +113,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(toh); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); ++(*tag); @@ -158,7 +158,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(vmime::make_shared ()); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); } } @@ -181,7 +181,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setSocket(socket); parser->setTimeoutHandler(toh); - VASSERT_NO_THROW("parse", parser->readResponse(*tag)); + VASSERT_NO_THROW("parse", std::unique_ptr (parser->readResponse(*tag))); } // Support for NIL boundary, for mail.ru IMAP server: @@ -218,7 +218,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(vmime::make_shared ()); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); } } @@ -253,7 +253,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(vmime::make_shared ()); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); } } @@ -373,7 +373,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) parser->setTimeoutHandler(toh); parser->setStrict(false); - VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + VASSERT_NO_THROW("non-strict mode", std::unique_ptr (parser->readResponse(*tag))); } }