Bug Summary

File:home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx
Warning:line 1001, column 31
Array access results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lbenv.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D CPPU_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifdef DISABLE_DYNLOADING
21#include <config_java.h>
22#endif
23
24#include <cppu/EnvDcp.hxx>
25
26#include <sal/log.hxx>
27#include <osl/diagnose.h>
28#include <osl/interlck.h>
29#include <osl/mutex.hxx>
30#include <osl/module.hxx>
31#include <osl/process.h>
32#include <rtl/process.h>
33#include <rtl/string.hxx>
34#include <rtl/ustring.hxx>
35#include <rtl/ustrbuf.hxx>
36#include <rtl/instance.hxx>
37#include <typelib/typedescription.h>
38#include <uno/dispatcher.h>
39#include <uno/environment.h>
40#include <uno/lbnames.h>
41#include "prim.hxx"
42#include "loadmodule.hxx"
43
44#include <unordered_map>
45#include <vector>
46#include <stdio.h>
47
48
49namespace
50{
51
52
53bool td_equals( typelib_InterfaceTypeDescription const * pTD1,
54 typelib_InterfaceTypeDescription const * pTD2 )
55{
56 return (pTD1 == pTD2 ||
57 (pTD1->aBase.pTypeName->length == pTD2->aBase.pTypeName->length &&
58 ::rtl_ustr_compare(
59 pTD1->aBase.pTypeName->buffer,
60 pTD2->aBase.pTypeName->buffer ) == 0));
61}
62
63struct uno_DefaultEnvironment;
64
65
66struct InterfaceEntry
67{
68 sal_Int32 refCount;
69 void * pInterface;
70 uno_freeProxyFunc fpFreeProxy;
71 typelib_InterfaceTypeDescription * pTypeDescr;
72};
73
74struct ObjectEntry
75{
76 OUString oid;
77 sal_Int32 nRef;
78 std::vector< InterfaceEntry > aInterfaces;
79 bool mixedObject;
80
81 explicit ObjectEntry( const OUString & rOId_ );
82
83 void append(
84 uno_DefaultEnvironment * pEnv,
85 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
86 uno_freeProxyFunc fpFreeProxy );
87 InterfaceEntry * find(
88 typelib_InterfaceTypeDescription * pTypeDescr );
89 sal_Int32 find( void const * iface_ptr, std::size_t pos ) const;
90};
91
92
93struct FctPtrHash
94{
95 std::size_t operator () ( const void * pKey ) const
96 { return reinterpret_cast< std::size_t>( pKey ); }
97};
98
99
100// mapping from environment name to environment
101typedef std::unordered_map<
102 OUString, uno_Environment * > OUString2EnvironmentMap;
103
104// mapping from ptr to object entry
105typedef std::unordered_map<
106 void *, ObjectEntry *, FctPtrHash > Ptr2ObjectMap;
107// mapping from oid to object entry
108typedef std::unordered_map<
109 OUString, ObjectEntry * > OId2ObjectMap;
110
111struct EnvironmentsData
112{
113 ::osl::Mutex mutex;
114 OUString2EnvironmentMap aName2EnvMap;
115
116 EnvironmentsData() : isDisposing(false) {}
117 ~EnvironmentsData();
118
119 void getEnvironment(
120 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
121 void registerEnvironment( uno_Environment ** ppEnv );
122 void getRegisteredEnvironments(
123 uno_Environment *** pppEnvs, sal_Int32 * pnLen,
124 uno_memAlloc memAlloc, const OUString & rEnvDcp );
125
126 bool isDisposing;
127};
128
129struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
130
131struct uno_DefaultEnvironment : public uno_ExtEnvironment
132{
133 sal_Int32 nRef;
134 sal_Int32 nWeakRef;
135
136 ::osl::Mutex mutex;
137 Ptr2ObjectMap aPtr2ObjectMap;
138 OId2ObjectMap aOId2ObjectMap;
139
140 uno_DefaultEnvironment(
141 const OUString & rEnvDcp_, void * pContext_ );
142 ~uno_DefaultEnvironment();
143};
144
145
146ObjectEntry::ObjectEntry( OUString const & rOId_ )
147 : oid( rOId_ ),
148 nRef( 0 ),
149 mixedObject( false )
150{
151 aInterfaces.reserve( 2 );
152}
153
154
155void ObjectEntry::append(
156 uno_DefaultEnvironment * pEnv,
157 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
158 uno_freeProxyFunc fpFreeProxy )
159{
160 InterfaceEntry aNewEntry;
161 if (! fpFreeProxy)
162 (*pEnv->acquireInterface)( pEnv, pInterface );
163 aNewEntry.refCount = 1;
164 aNewEntry.pInterface = pInterface;
165 aNewEntry.fpFreeProxy = fpFreeProxy;
166 typelib_typedescription_acquire( &pTypeDescr->aBase );
167 aNewEntry.pTypeDescr = pTypeDescr;
168
169 std::pair< Ptr2ObjectMap::iterator, bool > i(
170 pEnv->aPtr2ObjectMap.emplace( pInterface, this ) );
171 SAL_WARN_IF(do { if (true && (!i.second && (find(pInterface
, 0) == -1 || i.first->second != this))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "map already contains "
<< i.first->second << " != " << this <<
" for " << pInterface) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "map already contains " << i.first->second
<< " != " << this << " for " << pInterface
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
172 !i.second && (find(pInterface, 0) == -1 || i.first->second != this),do { if (true && (!i.second && (find(pInterface
, 0) == -1 || i.first->second != this))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "map already contains "
<< i.first->second << " != " << this <<
" for " << pInterface) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "map already contains " << i.first->second
<< " != " << this << " for " << pInterface
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
173 "cppu",do { if (true && (!i.second && (find(pInterface
, 0) == -1 || i.first->second != this))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "map already contains "
<< i.first->second << " != " << this <<
" for " << pInterface) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "map already contains " << i.first->second
<< " != " << this << " for " << pInterface
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
174 "map already contains " << i.first->second << " != " << this << " for "do { if (true && (!i.second && (find(pInterface
, 0) == -1 || i.first->second != this))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "map already contains "
<< i.first->second << " != " << this <<
" for " << pInterface) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "map already contains " << i.first->second
<< " != " << this << " for " << pInterface
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
175 << pInterface)do { if (true && (!i.second && (find(pInterface
, 0) == -1 || i.first->second != this))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "map already contains "
<< i.first->second << " != " << this <<
" for " << pInterface) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "map already contains " << i.first->second
<< " != " << this << " for " << pInterface
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "map already contains " << i.first
->second << " != " << this << " for " <<
pInterface), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "map already contains " <<
i.first->second << " != " << this << " for "
<< pInterface; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "175" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
176 aInterfaces.push_back( aNewEntry );
177}
178
179
180InterfaceEntry * ObjectEntry::find(
181 typelib_InterfaceTypeDescription * pTypeDescr_ )
182{
183 OSL_ASSERT( ! aInterfaces.empty() )do { if (true && (!(! aInterfaces.empty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "183" ": "), "OSL_ASSERT: %s", "! aInterfaces.empty()");
} } while (false)
;
184 if (aInterfaces.empty())
185 return nullptr;
186
187 // shortcut common case:
188 OUString const & type_name =
189 OUString::unacquired( &pTypeDescr_->aBase.pTypeName );
190 if ( type_name == "com.sun.star.uno.XInterface" )
191 {
192 return aInterfaces.data();
193 }
194
195 std::size_t nSize = aInterfaces.size();
196 for ( std::size_t nPos = 0; nPos < nSize; ++nPos )
197 {
198 typelib_InterfaceTypeDescription * pITD =
199 aInterfaces[ nPos ].pTypeDescr;
200 while (pITD)
201 {
202 if (td_equals( pITD, pTypeDescr_ ))
203 return &aInterfaces[ nPos ];
204 pITD = pITD->pBaseTypeDescription;
205 }
206 }
207 return nullptr;
208}
209
210
211sal_Int32 ObjectEntry::find(
212 void const * iface_ptr, std::size_t pos ) const
213{
214 std::size_t size = aInterfaces.size();
215 for ( ; pos < size; ++pos )
216 {
217 if (aInterfaces[ pos ].pInterface == iface_ptr)
218 return pos;
219 }
220 return -1;
221}
222
223extern "C"
224{
225
226
227static void defenv_registerInterface(
228 uno_ExtEnvironment * pEnv, void ** ppInterface,
229 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
230{
231 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" )do { if (true && (!(pEnv && ppInterface &&
pOId && pTypeDescr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "231" ": "), "%s", "### null ptr!"); } } while (false)
;
232 OUString const & rOId = OUString::unacquired( &pOId );
233
234 uno_DefaultEnvironment * that =
235 static_cast< uno_DefaultEnvironment * >( pEnv );
236 ::osl::ClearableMutexGuard guard( that->mutex );
237
238 // try to insert dummy 0:
239 std::pair<OId2ObjectMap::iterator, bool> const insertion(
240 that->aOId2ObjectMap.emplace( rOId, nullptr ) );
241 if (insertion.second)
242 {
243 ObjectEntry * pOEntry = new ObjectEntry( rOId );
244 insertion.first->second = pOEntry;
245 ++pOEntry->nRef; // another register call on object
246 pOEntry->append( that, *ppInterface, pTypeDescr, nullptr );
247 }
248 else // object entry exists
249 {
250 ObjectEntry * pOEntry = insertion.first->second;
251 ++pOEntry->nRef; // another register call on object
252 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
253
254 if (pIEntry) // type entry exists
255 {
256 ++pIEntry->refCount;
257 if (pIEntry->pInterface != *ppInterface)
258 {
259 void * pInterface = pIEntry->pInterface;
260 (*pEnv->acquireInterface)( pEnv, pInterface );
261 guard.clear();
262 (*pEnv->releaseInterface)( pEnv, *ppInterface );
263 *ppInterface = pInterface;
264 }
265 }
266 else
267 {
268 pOEntry->append( that, *ppInterface, pTypeDescr, nullptr );
269 }
270 }
271}
272
273
274static void defenv_registerProxyInterface(
275 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
276 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
277{
278 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,do { if (true && (!(pEnv && ppInterface &&
pOId && pTypeDescr && freeProxy))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "279" ": "), "%s", "### null ptr!"); } } while (false)
279 "### null ptr!" )do { if (true && (!(pEnv && ppInterface &&
pOId && pTypeDescr && freeProxy))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "279" ": "), "%s", "### null ptr!"); } } while (false)
;
280 OUString const & rOId = OUString::unacquired( &pOId );
281
282 uno_DefaultEnvironment * that =
283 static_cast< uno_DefaultEnvironment * >( pEnv );
284 ::osl::ClearableMutexGuard guard( that->mutex );
285
286 // try to insert dummy 0:
287 std::pair<OId2ObjectMap::iterator, bool> const insertion(
288 that->aOId2ObjectMap.emplace( rOId, nullptr ) );
289 if (insertion.second)
290 {
291 ObjectEntry * pOEntry = new ObjectEntry( rOId );
292 insertion.first->second = pOEntry;
293 ++pOEntry->nRef; // another register call on object
294 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
295 }
296 else // object entry exists
297 {
298 ObjectEntry * pOEntry = insertion.first->second;
299
300 // first registration was an original, then registerProxyInterface():
301 pOEntry->mixedObject |=
302 (!pOEntry->aInterfaces.empty() &&
303 pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr);
304
305 ++pOEntry->nRef; // another register call on object
306 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
307
308 if (pIEntry) // type entry exists
309 {
310 if (pIEntry->pInterface == *ppInterface)
311 {
312 ++pIEntry->refCount;
313 }
314 else
315 {
316 void * pInterface = pIEntry->pInterface;
317 (*pEnv->acquireInterface)( pEnv, pInterface );
318 --pOEntry->nRef; // manual revoke of proxy to be freed
319 guard.clear();
320 (*freeProxy)( pEnv, *ppInterface );
321 *ppInterface = pInterface;
322 }
323 }
324 else
325 {
326 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
327 }
328 }
329}
330
331
332static void s_stub_defenv_revokeInterface(va_list * pParam)
333{
334 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *)__builtin_va_arg(*pParam, uno_ExtEnvironment *);
335 void * pInterface = va_arg(*pParam, void *)__builtin_va_arg(*pParam, void *);
336
337 OSL_ENSURE( pEnv && pInterface, "### null ptr!" )do { if (true && (!(pEnv && pInterface))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "337" ": "), "%s", "### null ptr!"); } } while (false)
;
338 uno_DefaultEnvironment * that =
339 static_cast< uno_DefaultEnvironment * >( pEnv );
340 ::osl::ClearableMutexGuard guard( that->mutex );
341
342 Ptr2ObjectMap::const_iterator const iFind(
343 that->aPtr2ObjectMap.find( pInterface ) );
344 OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() )do { if (true && (!(iFind != that->aPtr2ObjectMap.
end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "344" ": "), "OSL_ASSERT: %s", "iFind != that->aPtr2ObjectMap.end()"
); } } while (false)
;
345 ObjectEntry * pOEntry = iFind->second;
346 if (! --pOEntry->nRef)
347 {
348 // cleanup maps
349 that->aOId2ObjectMap.erase( pOEntry->oid );
350 sal_Int32 nPos;
351 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
352 {
353 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
354 }
355
356 // the last proxy interface of the environment might kill this
357 // environment, because of releasing its language binding!!!
358 guard.clear();
359
360 // release interfaces
361 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
362 {
363 InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
364 typelib_typedescription_release( &rEntry.pTypeDescr->aBase );
365 if (rEntry.fpFreeProxy) // is proxy or used interface?
366 {
367 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
368 }
369 else
370 {
371 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
372 }
373 }
374
375 delete pOEntry;
376 }
377 else if (pOEntry->mixedObject)
378 {
379 OSL_ASSERT( !pOEntry->aInterfaces.empty() &&do { if (true && (!(!pOEntry->aInterfaces.empty() &&
pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "380" ": "), "OSL_ASSERT: %s", "!pOEntry->aInterfaces.empty() && pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr"
); } } while (false)
380 pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr )do { if (true && (!(!pOEntry->aInterfaces.empty() &&
pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "380" ": "), "OSL_ASSERT: %s", "!pOEntry->aInterfaces.empty() && pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr"
); } } while (false)
;
381
382 sal_Int32 index = pOEntry->find( pInterface, 1 );
383 OSL_ASSERT( index > 0 )do { if (true && (!(index > 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "383" ": "), "OSL_ASSERT: %s", "index > 0"); } } while
(false)
;
384 if (index > 0)
385 {
386 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
387 OSL_ASSERT( entry.pInterface == pInterface )do { if (true && (!(entry.pInterface == pInterface)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "387" ": "), "OSL_ASSERT: %s", "entry.pInterface == pInterface"
); } } while (false)
;
388 if (entry.fpFreeProxy != nullptr)
389 {
390 --entry.refCount;
391 if (entry.refCount == 0)
392 {
393 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
394 typelib_TypeDescription * pTypeDescr =
395 reinterpret_cast< typelib_TypeDescription * >(
396 entry.pTypeDescr );
397
398 pOEntry->aInterfaces.erase(
399 pOEntry->aInterfaces.begin() + index );
400 if (pOEntry->find( pInterface, index ) < 0)
401 {
402 // proxy ptr not registered for another interface:
403 // remove from ptr map
404 std::size_t erased =
405 that->aPtr2ObjectMap.erase( pInterface );
406 OSL_ASSERT( erased == 1 )do { if (true && (!(erased == 1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "406" ": "), "OSL_ASSERT: %s", "erased == 1"); } } while
(false)
;
407 }
408
409 guard.clear();
410
411 typelib_typedescription_release( pTypeDescr );
412 (*fpFreeProxy)( pEnv, pInterface );
413 }
414 }
415 }
416 }
417}
418
419static void defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
420{
421 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
422}
423
424
425static void defenv_getObjectIdentifier(
426 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
427{
428 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" )do { if (true && (!(pEnv && ppOId && pInterface
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "428" ": "), "%s", "### null ptr!"); } } while (false)
;
429 if (*ppOId)
430 {
431 ::rtl_uString_release( *ppOId );
432 *ppOId = nullptr;
433 }
434
435 uno_DefaultEnvironment * that =
436 static_cast< uno_DefaultEnvironment * >( pEnv );
437 ::osl::ClearableMutexGuard guard( that->mutex );
438
439 Ptr2ObjectMap::const_iterator const iFind(
440 that->aPtr2ObjectMap.find( pInterface ) );
441 if (iFind == that->aPtr2ObjectMap.end())
442 {
443 guard.clear();
444 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
445 }
446 else
447 {
448 rtl_uString * hstr = iFind->second->oid.pData;
449 rtl_uString_acquire( hstr );
450 *ppOId = hstr;
451 }
452}
453
454
455static void defenv_getRegisteredInterface(
456 uno_ExtEnvironment * pEnv, void ** ppInterface,
457 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
458{
459 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" )do { if (true && (!(pEnv && ppInterface &&
pOId && pTypeDescr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "459" ": "), "%s", "### null ptr!"); } } while (false)
;
460 if (*ppInterface)
461 {
462 (*pEnv->releaseInterface)( pEnv, *ppInterface );
463 *ppInterface = nullptr;
464 }
465
466 OUString const & rOId = OUString::unacquired( &pOId );
467 uno_DefaultEnvironment * that =
468 static_cast< uno_DefaultEnvironment * >( pEnv );
469 ::osl::MutexGuard guard( that->mutex );
470
471 OId2ObjectMap::const_iterator const iFind
472 ( that->aOId2ObjectMap.find( rOId ) );
473 if (iFind != that->aOId2ObjectMap.end())
474 {
475 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
476 if (pIEntry)
477 {
478 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
479 *ppInterface = pIEntry->pInterface;
480 }
481 }
482}
483
484
485static void defenv_getRegisteredInterfaces(
486 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
487 uno_memAlloc memAlloc )
488{
489 assert(pEnv && pppInterfaces && pnLen && memAlloc && "### null ptr!")(static_cast <bool> (pEnv && pppInterfaces &&
pnLen && memAlloc && "### null ptr!") ? void
(0) : __assert_fail ("pEnv && pppInterfaces && pnLen && memAlloc && \"### null ptr!\""
, "/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
, 489, __extension__ __PRETTY_FUNCTION__))
;
490 uno_DefaultEnvironment * that =
491 static_cast< uno_DefaultEnvironment * >( pEnv );
492 ::osl::MutexGuard guard( that->mutex );
493
494 sal_Int32 nLen = that->aPtr2ObjectMap.size();
495 sal_Int32 nPos = 0;
496 void ** ppInterfaces = static_cast<void **>((*memAlloc)( nLen * sizeof (void *) ));
497
498 for (const auto& rEntry : that->aPtr2ObjectMap)
499 {
500 ppInterfaces[nPos] = rEntry.first;
501 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos] );
502 nPos++;
503 }
504
505 *pppInterfaces = ppInterfaces;
506 *pnLen = nLen;
507}
508
509
510static void defenv_acquire( uno_Environment * pEnv )
511{
512 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
513 osl_atomic_increment( &that->nWeakRef )__sync_add_and_fetch((&that->nWeakRef), 1);
514 osl_atomic_increment( &that->nRef )__sync_add_and_fetch((&that->nRef), 1);
515}
516
517
518static void defenv_release( uno_Environment * pEnv )
519{
520 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
521 if (! osl_atomic_decrement( &that->nRef )__sync_sub_and_fetch((&that->nRef), 1))
522 {
523 // invoke dispose callback
524 if (pEnv->environmentDisposing)
525 {
526 (*pEnv->environmentDisposing)( pEnv );
527 }
528
529 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" )do { if (true && (!(that->aOId2ObjectMap.empty()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "529" ": "), "%s", "### object entries left!"); } } while
(false)
;
530 }
531 // free memory if no weak refs left
532 if (! osl_atomic_decrement( &that->nWeakRef )__sync_sub_and_fetch((&that->nWeakRef), 1))
533 {
534 delete that;
535 }
536}
537
538
539static void defenv_acquireWeak( uno_Environment * pEnv )
540{
541 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
542 osl_atomic_increment( &that->nWeakRef )__sync_add_and_fetch((&that->nWeakRef), 1);
543}
544
545
546static void defenv_releaseWeak( uno_Environment * pEnv )
547{
548 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
549 if (! osl_atomic_decrement( &that->nWeakRef )__sync_sub_and_fetch((&that->nWeakRef), 1))
550 {
551 delete that;
552 }
553}
554
555
556static void defenv_harden(
557 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
558{
559 if (*ppHardEnv)
560 {
561 (*(*ppHardEnv)->release)( *ppHardEnv );
562 *ppHardEnv = nullptr;
563 }
564
565 EnvironmentsData & rData = theEnvironmentsData::get();
566
567 if (rData.isDisposing)
568 return;
569
570 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
571 {
572 ::osl::MutexGuard guard( rData.mutex );
573 if (1 == osl_atomic_increment( &that->nRef )__sync_add_and_fetch((&that->nRef), 1)) // is dead
574 {
575 that->nRef = 0;
576 return;
577 }
578 }
579 osl_atomic_increment( &that->nWeakRef )__sync_add_and_fetch((&that->nWeakRef), 1);
580 *ppHardEnv = pEnv;
581}
582
583
584static void defenv_dispose( SAL_UNUSED_PARAMETER__attribute__ ((unused)) uno_Environment * )
585{
586}
587}
588
589
590uno_DefaultEnvironment::uno_DefaultEnvironment(
591 const OUString & rEnvDcp_, void * pContext_ )
592 : nRef( 0 ),
593 nWeakRef( 0 )
594{
595 uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
596 that->pReserved = nullptr;
597 // functions
598 that->acquire = defenv_acquire;
599 that->release = defenv_release;
600 that->acquireWeak = defenv_acquireWeak;
601 that->releaseWeak = defenv_releaseWeak;
602 that->harden = defenv_harden;
603 that->dispose = defenv_dispose;
604 that->pExtEnv = this;
605 // identifier
606 ::rtl_uString_acquire( rEnvDcp_.pData );
607 that->pTypeName = rEnvDcp_.pData;
608 that->pContext = pContext_;
609
610 // will be late initialized
611 that->environmentDisposing = nullptr;
612
613 uno_ExtEnvironment::registerInterface = defenv_registerInterface;
614 uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
615 uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
616 uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
617 uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
618 uno_ExtEnvironment::getRegisteredInterfaces =
619 defenv_getRegisteredInterfaces;
620
621}
622
623
624uno_DefaultEnvironment::~uno_DefaultEnvironment()
625{
626 ::rtl_uString_release( aBase.pTypeName );
627}
628
629
630void writeLine(
631 void * stream, const char * pLine, const char * pFilter )
632{
633 if (pFilter && *pFilter)
634 {
635 // lookup pFilter in pLine
636 while (*pLine)
637 {
638 if (*pLine == *pFilter)
639 {
640 sal_Int32 nPos = 1;
641 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
642 {
643 ++nPos;
644 }
645 if (! pFilter[nPos])
646 {
647 if (stream)
648 {
649 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
650 }
651 else
652 {
653 SAL_WARN("cppu", pLine )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << pLine) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "653" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << pLine), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << pLine; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "653" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << pLine) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "653" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << pLine), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << pLine; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "653" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
654 }
655 }
656 }
657 ++pLine;
658 }
659 }
660 else
661 {
662 if (stream)
663 {
664 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
665 }
666 else
667 {
668 fprintf( stderrstderr, "%s\n", pLine );
669 }
670 }
671}
672
673
674void writeLine(
675 void * stream, const OUString & rLine, const char * pFilter )
676{
677 OString aLine( OUStringToOString(
678 rLine, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)) ) );
679 writeLine( stream, aLine.getStr(), pFilter );
680}
681
682}
683
684extern "C" void SAL_CALL uno_dumpEnvironment(
685 void * stream, uno_Environment * pEnv, const char * pFilter )
686 SAL_THROW_EXTERN_C()throw ()
687{
688 OSL_ENSURE( pEnv, "### null ptr!" )do { if (true && (!(pEnv))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "688" ": "), "%s", "### null ptr!"); } } while (false)
;
689 OUStringBuffer buf;
690
691 if (! pEnv->pExtEnv)
692 {
693 writeLine( stream, "###################################"
694 "###########################################", pFilter );
695 buf.append( "environment: " );
696 buf.append( pEnv->pTypeName );
697 writeLine( stream, buf.makeStringAndClear(), pFilter );
698 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
699 return;
700 }
701
702 writeLine( stream, "########################################"
703 "######################################", pFilter );
704 buf.append( "environment dump: " );
705 buf.append( pEnv->pTypeName );
706 writeLine( stream, buf.makeStringAndClear(), pFilter );
707
708 uno_DefaultEnvironment * that =
709 reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
710 ::osl::MutexGuard guard( that->mutex );
711
712 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
713 for (const auto& rEntry : that->aOId2ObjectMap)
714 {
715 ObjectEntry * pOEntry = rEntry.second;
716
717 buf.append( "+ " );
718 if (pOEntry->mixedObject)
719 buf.append( "mixed " );
720 buf.append( "object entry: nRef=" );
721 buf.append( pOEntry->nRef );
722 buf.append( "; oid=\"" );
723 buf.append( pOEntry->oid );
724 buf.append( '\"' );
725 writeLine( stream, buf.makeStringAndClear(), pFilter );
726
727 for ( std::size_t nPos = 0;
728 nPos < pOEntry->aInterfaces.size(); ++nPos )
729 {
730 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
731
732 buf.append( " - " );
733 buf.append( rIEntry.pTypeDescr->aBase.pTypeName );
734 if (rIEntry.fpFreeProxy)
735 {
736 buf.append( "; proxy free=0x" );
737 buf.append(
738 reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
739 }
740 else
741 {
742 buf.append( "; original" );
743 }
744 buf.append( "; ptr=0x" );
745 buf.append(
746 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
747
748 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
749 {
750 std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
751 if (erased != 1)
752 {
753 buf.append( " (ptr not found in map!)" );
754 }
755 }
756 writeLine( stream, buf.makeStringAndClear(), pFilter );
757 }
758 }
759 if (! ptr2obj.empty())
760 writeLine( stream, "ptr map inconsistency!!!", pFilter );
761 writeLine( stream, "#####################################"
762 "#########################################", pFilter );
763}
764
765
766extern "C" void SAL_CALL uno_dumpEnvironmentByName(
767 void * stream, rtl_uString * pEnvDcp, const char * pFilter )
768 SAL_THROW_EXTERN_C()throw ()
769{
770 uno_Environment * pEnv = nullptr;
771 uno_getEnvironment( &pEnv, pEnvDcp, nullptr );
772 if (pEnv)
773 {
774 ::uno_dumpEnvironment( stream, pEnv, pFilter );
775 (*pEnv->release)( pEnv );
776 }
777 else
778 {
779 writeLine(
780 stream, "environment \"" + OUString::unacquired(&pEnvDcp) + "\" does not exist!",
781 pFilter );
782 }
783}
784
785namespace
786{
787 class makeOIdPart
788 {
789 private:
790 OUString m_sOidPart;
791 public:
792 makeOIdPart()
793 {
794 OUStringBuffer aRet( 64 );
795 aRet.append( "];" );
796 // pid
797 oslProcessInfo info;
798 info.Size = sizeof(oslProcessInfo);
799 if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER0x0001, &info ) ==
800 osl_Process_E_None)
801 {
802 aRet.append( static_cast<sal_Int64>(info.Ident), 16 );
803 }
804 else
805 {
806 aRet.append( "unknown process id" );
807 }
808 // good guid
809 sal_uInt8 ar[16];
810 ::rtl_getGlobalProcessId( ar );
811 aRet.append( ';' );
812 for (unsigned char i : ar)
813 aRet.append( static_cast<sal_Int32>(i), 16 );
814
815 m_sOidPart = aRet.makeStringAndClear();
816 }
817 const OUString& getOIdPart() const { return m_sOidPart; }
818 };
819
820 class theStaticOIdPart : public rtl::Static<makeOIdPart, theStaticOIdPart> {};
821
822const OUString & unoenv_getStaticOIdPart()
823{
824 return theStaticOIdPart::get().getOIdPart();
825}
826
827}
828
829extern "C"
830{
831
832
833static void unoenv_computeObjectIdentifier(
834 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
835{
836 assert(pEnv && ppOId && pInterface && "### null ptr!")(static_cast <bool> (pEnv && ppOId && pInterface
&& "### null ptr!") ? void (0) : __assert_fail ("pEnv && ppOId && pInterface && \"### null ptr!\""
, "/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
, 836, __extension__ __PRETTY_FUNCTION__))
;
837 if (*ppOId)
838 {
839 ::rtl_uString_release( *ppOId );
840 *ppOId = nullptr;
841 }
842
843 uno_Interface * pUnoI = static_cast<uno_Interface *>(
844 ::cppu::binuno_queryInterface(
845 pInterface, *typelib_static_type_getByTypeClass(
846 typelib_TypeClass_INTERFACE ) ));
847 if (nullptr == pUnoI)
848 return;
849
850 (*pUnoI->release)( pUnoI );
851 // interface
852 OUStringBuffer oid( 64 );
853 oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
854 oid.append( ';' );
855 // environment[context]
856 oid.append( pEnv->aBase.pTypeName );
857 oid.append( '[' );
858 oid.append( reinterpret_cast< sal_Int64 >(
859 reinterpret_cast<
860 uno_Environment * >(pEnv)->pContext ), 16 );
861 // process;good guid
862 oid.append( unoenv_getStaticOIdPart() );
863 OUString aStr( oid.makeStringAndClear() );
864 *ppOId = aStr.pData;
865 ::rtl_uString_acquire( *ppOId );
866}
867
868
869static void unoenv_acquireInterface(
870 SAL_UNUSED_PARAMETER__attribute__ ((unused)) uno_ExtEnvironment *, void * pUnoI_ )
871{
872 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
873 (*pUnoI->acquire)( pUnoI );
874}
875
876
877static void unoenv_releaseInterface(
878 SAL_UNUSED_PARAMETER__attribute__ ((unused)) uno_ExtEnvironment *, void * pUnoI_ )
879{
880 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
881 (*pUnoI->release)( pUnoI );
882}
883}
884
885namespace {
886
887EnvironmentsData::~EnvironmentsData()
888{
889 ::osl::MutexGuard guard( mutex );
890 isDisposing = true;
891
892 for ( const auto& rEntry : aName2EnvMap )
893 {
894 uno_Environment * pWeak = rEntry.second;
895 uno_Environment * pHard = nullptr;
896 (*pWeak->harden)( &pHard, pWeak );
897 (*pWeak->releaseWeak)( pWeak );
898
899 if (pHard)
900 {
901 (*pHard->dispose)( pHard ); // send explicit dispose
902 (*pHard->release)( pHard );
903 }
904 }
905}
906
907
908void EnvironmentsData::getEnvironment(
909 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
910{
911 if (*ppEnv)
912 {
913 (*(*ppEnv)->release)( *ppEnv );
914 *ppEnv = nullptr;
915 }
916
917 OUString aKey = OUString::number( reinterpret_cast< sal_IntPtr >(pContext) ) + rEnvDcp;
918
919 // try to find registered mapping
920 OUString2EnvironmentMap::const_iterator const iFind(
921 aName2EnvMap.find( aKey ) );
922 if (iFind != aName2EnvMap.end())
923 {
924 uno_Environment * pWeak = iFind->second;
925 (*pWeak->harden)( ppEnv, pWeak );
926 }
927}
928
929
930void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
931{
932 OSL_ENSURE( ppEnv, "### null ptr!" )do { if (true && (!(ppEnv))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "932" ": "), "%s", "### null ptr!"); } } while (false)
;
933 uno_Environment * pEnv = *ppEnv;
934
935 OUString aKey =
936 OUString::number( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) +
937 OUString::unacquired(&pEnv->pTypeName);
938
939 // try to find registered environment
940 OUString2EnvironmentMap::const_iterator const iFind(
941 aName2EnvMap.find( aKey ) );
942 if (iFind == aName2EnvMap.end())
943 {
944 (*pEnv->acquireWeak)( pEnv );
945 std::pair< OUString2EnvironmentMap::iterator, bool > insertion (
946 aName2EnvMap.emplace( aKey, pEnv ) );
947 SAL_WARN_IF( !insertion.second, "cppu", "key " << aKey << " already in env map" )do { if (true && (!insertion.second)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "key " <<
aKey << " already in env map") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "947" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "key " << aKey << " already in env map"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "key " << aKey << " already in env map"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu")
, ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "947" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "key " << aKey << " already in env map"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu"
), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "947" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "key " << aKey << " already in env map"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "key " << aKey << " already in env map"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppu")
, ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "947" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
948 }
949 else
950 {
951 uno_Environment * pHard = nullptr;
952 uno_Environment * pWeak = iFind->second;
953 (*pWeak->harden)( &pHard, pWeak );
954 if (pHard)
955 {
956 (*pEnv->release)( pEnv );
957 *ppEnv = pHard;
958 }
959 else // registered one is dead
960 {
961 (*pWeak->releaseWeak)( pWeak );
962 (*pEnv->acquireWeak)( pEnv );
963 aName2EnvMap[ aKey ] = pEnv;
964 }
965 }
966}
967
968
969void EnvironmentsData::getRegisteredEnvironments(
970 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
971 const OUString & rEnvDcp )
972{
973 assert(pppEnvs && pnLen && memAlloc && "### null ptr!")(static_cast <bool> (pppEnvs && pnLen &&
memAlloc && "### null ptr!") ? void (0) : __assert_fail
("pppEnvs && pnLen && memAlloc && \"### null ptr!\""
, "/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
, 973, __extension__ __PRETTY_FUNCTION__))
;
4
Assuming 'pppEnvs' is non-null
5
Assuming 'pnLen' is non-null
6
Assuming 'memAlloc' is non-null
7
'?' condition is true
974
975 // max size
976 std::vector<uno_Environment*> aFounds(aName2EnvMap.size());
977 sal_Int32 nSize = 0;
978
979 // find matching environment
980 for ( const auto& rEntry : aName2EnvMap )
981 {
982 uno_Environment * pWeak = rEntry.second;
983 if (rEnvDcp.isEmpty() ||
8
Taking true branch
984 rEnvDcp == pWeak->pTypeName )
985 {
986 aFounds[nSize] = nullptr;
987 (*pWeak->harden)( &aFounds[nSize], pWeak );
988 if (aFounds[nSize])
9
Assuming the condition is true
10
Taking true branch
989 ++nSize;
990 }
991 }
992
993 *pnLen = nSize;
994 if (nSize
10.1
'nSize' is 1
)
11
Taking true branch
995 {
996 *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
12
Assigning value
997 sizeof (uno_Environment *) * nSize ));
998 OSL_ASSERT( *pppEnvs )do { if (true && (!(*pppEnvs))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "998" ": "), "OSL_ASSERT: %s", "*pppEnvs"); } } while (false
)
;
13
Assuming the condition is true
14
Taking true branch
15
Loop condition is false. Exiting loop
999 while (nSize--)
16
Loop condition is true. Entering loop body
1000 {
1001 (*pppEnvs)[nSize] = aFounds[nSize];
17
Array access results in a null pointer dereference
1002 }
1003 }
1004 else
1005 {
1006 *pppEnvs = nullptr;
1007 }
1008}
1009
1010bool loadEnv(OUString const & cLibStem,
1011 uno_Environment * pEnv)
1012{
1013#ifdef DISABLE_DYNLOADING
1014 uno_initEnvironmentFunc fpInit;
1015
1016 if ( cLibStem == CPPU_CURRENT_LANGUAGE_BINDING_NAME"gcc3" "_uno" )
1017 fpInit = CPPU_ENV_uno_initEnvironment;
1018#if HAVE_FEATURE_JAVA
1019 else if ( cLibStem == "java_uno" )
1020 fpInit = java_uno_initEnvironment;
1021#endif
1022 else
1023 {
1024 SAL_INFO("cppu", ": Unhandled env: " << cLibStem)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "cppu")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << ": Unhandled env: " << cLibStem) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "1024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << ": Unhandled env: " << cLibStem
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< ": Unhandled env: " << cLibStem; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "1024" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << ": Unhandled env: " << cLibStem) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "1024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << ": Unhandled env: " << cLibStem
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< ": Unhandled env: " << cLibStem; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cppu"), ("/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
":" "1024" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1025 return false;
1026 }
1027#else
1028 // late init with some code from matching uno language binding
1029 // will be unloaded by environment
1030 osl::Module aMod;
1031 try {
1032 bool bMod = cppu::detail::loadModule(aMod, cLibStem);
1033 if (!bMod)
1034 return false;
1035 }
1036 catch(...) {
1037 // Catch everything and convert to return false
1038 return false;
1039 }
1040
1041
1042 uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(UNO_INIT_ENVIRONMENT"uno_initEnvironment"));
1043
1044 if (!fpInit)
1045 return false;
1046
1047 aMod.release();
1048#endif
1049
1050 (*fpInit)( pEnv ); // init of environment
1051 return true;
1052}
1053
1054}
1055
1056extern "C"
1057{
1058
1059
1060static uno_Environment * initDefaultEnvironment(
1061 const OUString & rEnvDcp, void * pContext )
1062{
1063 // coverity[leaked_storage : FALSE] - lifetime is controlled by acquire()/release() calls
1064 uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
1065 (*pEnv->acquire)( pEnv );
1066
1067 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1068
1069 // create default environment
1070 if ( envTypeName == UNO_LB_UNO"uno" )
1071 {
1072 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
1073 that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1074 that->acquireInterface = unoenv_acquireInterface;
1075 that->releaseInterface = unoenv_releaseInterface;
1076
1077 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1078 if (!envPurpose.isEmpty())
1079 {
1080 OUString libStem(
1081 envPurpose.copy(envPurpose.lastIndexOf(':') + 1) + "_uno_uno");
1082 if(!loadEnv(libStem, pEnv))
1083 {
1084 pEnv->release(pEnv);
1085 return nullptr;
1086 }
1087 }
1088 }
1089 else
1090 {
1091 // late init with some code from matching uno language binding
1092 OUString aStr( envTypeName + "_uno" );
1093
1094 if (!loadEnv(aStr, pEnv))
1095 {
1096 pEnv->release(pEnv);
1097 return nullptr;
1098 }
1099 }
1100
1101 return pEnv;
1102}
1103
1104
1105void SAL_CALL uno_createEnvironment(
1106 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1107 SAL_THROW_EXTERN_C()throw ()
1108{
1109 assert(ppEnv && "### null ptr!")(static_cast <bool> (ppEnv && "### null ptr!") ?
void (0) : __assert_fail ("ppEnv && \"### null ptr!\""
, "/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
, 1109, __extension__ __PRETTY_FUNCTION__))
;
1110 if (*ppEnv)
1111 (*(*ppEnv)->release)( *ppEnv );
1112
1113 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1114 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1115}
1116
1117void SAL_CALL uno_getEnvironment(
1118 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1119 SAL_THROW_EXTERN_C()throw ()
1120{
1121 assert(ppEnv && "### null ptr!")(static_cast <bool> (ppEnv && "### null ptr!") ?
void (0) : __assert_fail ("ppEnv && \"### null ptr!\""
, "/home/maarten/src/libreoffice/core/cppu/source/uno/lbenv.cxx"
, 1121, __extension__ __PRETTY_FUNCTION__))
;
1122 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1123
1124 EnvironmentsData & rData = theEnvironmentsData::get();
1125
1126 ::osl::MutexGuard guard( rData.mutex );
1127 rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1128 if (! *ppEnv)
1129 {
1130 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1131 if (*ppEnv)
1132 {
1133 // register new environment:
1134 rData.registerEnvironment( ppEnv );
1135 }
1136 }
1137}
1138
1139void SAL_CALL uno_getRegisteredEnvironments(
1140 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1141 rtl_uString * pEnvDcp )
1142 SAL_THROW_EXTERN_C()throw ()
1143{
1144 EnvironmentsData & rData = theEnvironmentsData::get();
1145
1146 ::osl::MutexGuard guard( rData.mutex );
1147 rData.getRegisteredEnvironments(
3
Calling 'EnvironmentsData::getRegisteredEnvironments'
1148 pppEnvs, pnLen, memAlloc,
1149 (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1
Assuming 'pEnvDcp' is null
2
'?' condition is false
1150}
1151
1152} // extern "C"
1153
1154/* vim:set shiftwidth=4 softtabstop=4 expandtab: */