From 60b30246cdb04d10dd7dbe55b8f15a66c543a56a Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 22 Jun 2019 19:55:41 +0200 Subject: [PATCH] QgsApplication::init(): fix a use-after-free with PROJ 6 `var = some_string.toUtf8().constData()` results in a use-after-free situation, so make a temporary copy of the string. This resulted in proj.db not being found on my system due to corrupted memory being passed to PROJ. And Valgrind also complained about this: ==11754== Invalid read of size 1 ==11754== at 0x4C31042: strlen (vg_replace_strmem.c:461) ==11754== by 0xA6DE536: std::__cxx11::basic_string, std::allocator >::basic_string(char const*, std::allocator const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==11754== by 0x173E1A1F: _ZN9__gnu_cxx13new_allocatorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9constructIS6_IRKPKcEEEvPT_DpOT0_ (new_allocator.h:120) ==11754== by 0x173E17C1: _ZNSt16allocator_traitsISaINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE9constructIS5_IRKPKcEEEvRS6_PT_DpOT0_ (alloc_traits.h:530) ==11754== by 0x173E184D: void std::vector, std::allocator >, std::allocator, std::allocator > > >::_M_emplace_back_aux(char const* const&) (vector.tcc:416) ==11754== by 0x173E1788: void std::vector, std::allocator >, std::allocator, std::allocator > > >::emplace_back(char const* const&) (vector.tcc:101) ==11754== by 0x173E0D23: internal_proj_context_set_search_paths (open_lib.cpp:133) ==11754== by 0x363A8516: QgsApplication::init(QString) (qgsapplication.cpp:316) ==11754== by 0x363AF666: QgsApplication::initQgis() (qgsapplication.cpp:1171) ==11754== by 0x3D814625: meth_QgsApplication_initQgis (sip_corepart1.cpp:292121) ==11754== by 0x4EA10E: PyCFunction_Call (in /usr/bin/python3.5) ==11754== by 0x536D93: PyEval_EvalFrameEx (in /usr/bin/python3.5) ==11754== Address 0x30aa7348 is 24 bytes inside a block of size 128 free'd ==11754== at 0x4C2EF90: free (vg_replace_malloc.c:540) ==11754== by 0x32FA519A: QTypedArrayData::deallocate(QArrayData*) (qarraydata.h:237) ==11754== by 0x32F9F09A: QByteArray::~QByteArray() (qbytearray.h:462) ==11754== by 0x363A84AE: QgsApplication::init(QString) (qgsapplication.cpp:313) ==11754== by 0x363AF666: QgsApplication::initQgis() (qgsapplication.cpp:1171) ==11754== by 0x3D814625: meth_QgsApplication_initQgis (sip_corepart1.cpp:292121) ==11754== by 0x4EA10E: PyCFunction_Call (in /usr/bin/python3.5) ==11754== by 0x536D93: PyEval_EvalFrameEx (in /usr/bin/python3.5) ==11754== by 0x53FC96: ??? (in /usr/bin/python3.5) ==11754== by 0x53B83E: PyEval_EvalFrameEx (in /usr/bin/python3.5) ==11754== by 0x53FC96: ??? (in /usr/bin/python3.5) ==11754== by 0x5409BE: PyEval_EvalCode (in /usr/bin/python3.5) ==11754== Block was alloc'd at ==11754== at 0x4C301AF: realloc (vg_replace_malloc.c:836) ==11754== by 0x31C05A08: QArrayData::reallocateUnaligned(QArrayData*, unsigned long, unsigned long, QFlags) (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==11754== by 0x31C0834E: QByteArray::reallocData(unsigned int, QFlags) (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==11754== by 0x31C08543: QByteArray::resize(int) (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==11754== by 0x31E406FA: ??? (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==11754== by 0x31C8826F: QString::toUtf8_helper(QString const&) (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==11754== by 0x3507EDA5: QString::toUtf8() const & (qstring.h:516) ==11754== by 0x363A8493: QgsApplication::init(QString) (qgsapplication.cpp:313) ==11754== by 0x363AF666: QgsApplication::initQgis() (qgsapplication.cpp:1171) ==11754== by 0x3D814625: meth_QgsApplication_initQgis (sip_corepart1.cpp:292121) ==11754== by 0x4EA10E: PyCFunction_Call (in /usr/bin/python3.5) ==11754== by 0x536D93: PyEval_EvalFrameEx (in /usr/bin/python3.5) ==11754== --- src/core/qgsapplication.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp index c45294aec2f..9bb30759c61 100644 --- a/src/core/qgsapplication.cpp +++ b/src/core/qgsapplication.cpp @@ -307,12 +307,16 @@ void QgsApplication::init( QString profileFolder ) // append local user-writable folder as a proj search path QStringList currentProjSearchPaths = QgsProjUtils::searchPaths(); currentProjSearchPaths.append( qgisSettingsDirPath() + QStringLiteral( "proj" ) ); - const char **newPaths = new const char *[currentProjSearchPaths.length()]; + char **newPaths = new char *[currentProjSearchPaths.length()]; for ( int i = 0; i < currentProjSearchPaths.count(); ++i ) { - newPaths[i] = currentProjSearchPaths.at( i ).toUtf8().constData(); + newPaths[i] = CPLStrdup( currentProjSearchPaths.at( i ).toUtf8().constData() ); } proj_context_set_search_paths( nullptr, currentProjSearchPaths.count(), newPaths ); + for ( int i = 0; i < currentProjSearchPaths.count(); ++i ) + { + CPLFree( newPaths[i] ); + } delete [] newPaths; #endif