summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/hsqldb/HStorageMap.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-02-23 16:39:48 +0100
committerStephan Bergmann <sbergman@redhat.com>2016-02-23 17:05:19 +0100
commit03a271901c39d60e4519e67e258d565ad5e1e085 (patch)
tree18308c560a5b69fb852d09b8039f001ff5882f5c /connectivity/source/drivers/hsqldb/HStorageMap.cxx
parent9610a5aebd3ffdf76bcb734c633b5f88b78ad4dd (diff)
Guard against globally shared UNO ref accessed from wrong UNO env
connectivity/source/drivers/jdbc/jdbc.component has environment="@CPPU_ENV@:affine" to place the com.sun.star.comp.sdbc.JDBCDriver implementation into an affine UNOenvironment. The com.sun.star.sdbcx.comp.hsqldb.Driver implementation (in the normal C++ UNO environment), in ODriverDelegator::connect (connectivity/source/drivers/hsqldb/HDriver.cxx), calls StorageContainer::registerStorage to store an XStorage in a global map, then calls the JDBCDriver (i.e., thread enters the affine environment), which calls via (non-UNO) JNI into hsqldb.jar code, which in turn calls via (non-UNO) JNI into Java_com_sun_star_sdbcx_comp_hsqldb_StorageFileAccess_isStreamElement (connectivity/source/drivers/hsqldb/StorageFileAccess.cxx), which uses StorageContainer::getRegisteredStorage to obtain the XStorage and use it. But that XStorage is the original C++ object, not a proxy that witnesses the mapping between the normal C++ and the affine UNO environment. (And the thread is still in the affine environment, after having passed through the Java stack frames via non-UNO JNI.) That does not necessarily cause any problems immediately (so apparently went unnoticed for quite a while), but when the XStorage-implementation in turn wants to obtain the SimpleLogRing singleton, it would now trigger the std::abort();//TODO in cppuhelper/source/servicemanager.cxx (where the invocation-by-constructor case hasn't yet been implemented for differing environments), when that singleton is changed to use the constructor feature in <https://gerrit.libreoffice.org/#/c/22020/> "tdf#74608: Constructor function for SimpleLogRing singleton." So just do any necessary mapping every time an XStorage stored in the static StorageContainer is accessed. Change-Id: I91a62fd7e1cec29026f70a2c3acdfe051885c0fa
Diffstat (limited to 'connectivity/source/drivers/hsqldb/HStorageMap.cxx')
-rw-r--r--connectivity/source/drivers/hsqldb/HStorageMap.cxx44
1 files changed, 34 insertions, 10 deletions
diff --git a/connectivity/source/drivers/hsqldb/HStorageMap.cxx b/connectivity/source/drivers/hsqldb/HStorageMap.cxx
index afd97ed77eae..334ff2b23970 100644
--- a/connectivity/source/drivers/hsqldb/HStorageMap.cxx
+++ b/connectivity/source/drivers/hsqldb/HStorageMap.cxx
@@ -25,6 +25,7 @@
#include <com/sun/star/lang/DisposedException.hpp>
#include <osl/diagnose.h>
#include <osl/thread.h>
+#include <uno/mapping.hxx>
#include <algorithm>
namespace connectivity
@@ -99,6 +100,28 @@ namespace connectivity
return m_xSeek;
}
+ css::uno::Reference<css::embed::XStorage> StorageData::mapStorage()
+ const
+ {
+ css::uno::Environment env(css::uno::Environment::getCurrent());
+ if (!(env.is() && storageEnvironment.is())) {
+ throw css::uno::RuntimeException("cannot get environments");
+ }
+ if (env.get() == storageEnvironment.get()) {
+ return storage;
+ } else {
+ css::uno::Mapping map(storageEnvironment, env);
+ if (!map.is()) {
+ throw css::uno::RuntimeException("cannot get mapping");
+ }
+ css::uno::Reference<css::embed::XStorage> mapped;
+ map.mapInterface(
+ reinterpret_cast<void **>(&mapped), storage.get(),
+ cppu::UnoType<css::embed::XStorage>::get());
+ return mapped;
+ }
+ }
+
TStorages& lcl_getStorageMap()
{
static TStorages s_aMap;
@@ -170,12 +193,12 @@ namespace connectivity
// check if the storage is already in our map
TStorages::iterator aFind = ::std::find_if(rMap.begin(),rMap.end(),
[&_xStorage] (const TStorages::value_type& storage) {
- return storage.second.storage == _xStorage;
+ return storage.second.mapStorage() == _xStorage;
});
if ( aFind == rMap.end() )
{
- aFind = rMap.insert(TStorages::value_type(lcl_getNextCount(), {_xStorage, _sURL, TStreamMap()})).first;
+ aFind = rMap.insert(TStorages::value_type(lcl_getNextCount(), {_xStorage, css::uno::Environment::getCurrent(), _sURL, TStreamMap()})).first;
}
return aFind->first;
@@ -201,7 +224,7 @@ namespace connectivity
// check if the storage is already in our map
TStorages::iterator aFind = ::std::find_if(rMap.begin(),rMap.end(),
[&_xStorage] (const TStorages::value_type& storage) {
- return storage.second.storage == _xStorage;
+ return storage.second.mapStorage() == _xStorage;
});
if ( aFind != rMap.end() )
@@ -219,10 +242,10 @@ namespace connectivity
{
if ( _xListener.is() )
{
- Reference<XTransactionBroadcaster> xBroad(aFind->second.storage,UNO_QUERY);
+ Reference<XTransactionBroadcaster> xBroad(aFind->second.mapStorage(),UNO_QUERY);
if ( xBroad.is() )
xBroad->removeTransactionListener(_xListener);
- Reference<XTransactedObject> xTrans(aFind->second.storage,UNO_QUERY);
+ Reference<XTransactedObject> xTrans(aFind->second.mapStorage(),UNO_QUERY);
if ( xTrans.is() )
xTrans->commit();
}
@@ -244,8 +267,9 @@ namespace connectivity
if ( aFind != rMap.end() )
{
TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(sKey);
- OSL_ENSURE(aStoragePair.storage.is(),"No Storage available!");
- if ( aStoragePair.storage.is() )
+ auto storage = aStoragePair.mapStorage();
+ OSL_ENSURE(storage.is(),"No Storage available!");
+ if ( storage.is() )
{
OUString sOrgName = StorageContainer::jstring2ustring(env,name);
OUString sName = removeURLPrefix(sOrgName,aStoragePair.url);
@@ -261,7 +285,7 @@ namespace connectivity
{
try
{
- pHelper.reset(new StreamHelper(aStoragePair.storage->openStreamElement(sName,_nMode)));
+ pHelper.reset(new StreamHelper(storage->openStreamElement(sName,_nMode)));
}
catch(const Exception&)
{
@@ -272,7 +296,7 @@ namespace connectivity
bool bIsStream = true;
try
{
- bIsStream = aStoragePair.storage->isStreamElement(sStrippedName);
+ bIsStream = storage->isStreamElement(sStrippedName);
}
catch(const Exception&)
{
@@ -281,7 +305,7 @@ namespace connectivity
if ( !bIsStream )
return pHelper; // readonly file without data stream
}
- pHelper.reset( new StreamHelper(aStoragePair.storage->openStreamElement( sStrippedName, _nMode ) ) );
+ pHelper.reset( new StreamHelper(storage->openStreamElement( sStrippedName, _nMode ) ) );
}
aFind->second.streams.insert(TStreamMap::value_type(sName,pHelper));
}