File: | cppu/source/uno/cascade_mapping.cxx |
Location: | line 150, column 9 |
Description: | Access to field 'releaseInterface' results in a dereference of a null pointer (loaded from variable 'env') |
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 | #include "osl/interlck.h" | |||
21 | #include "rtl/ustring.hxx" | |||
22 | #include "uno/environment.hxx" | |||
23 | #include "uno/mapping.hxx" | |||
24 | #include "uno/dispatcher.h" | |||
25 | ||||
26 | #include "cppu/EnvDcp.hxx" | |||
27 | ||||
28 | ||||
29 | #ifdef LOG_LIFECYLE_MediatorMapping | |||
30 | # include <iostream> | |||
31 | # define LOG_LIFECYLE_MediatorMapping_emit(x) x | |||
32 | ||||
33 | #else | |||
34 | # define LOG_LIFECYLE_MediatorMapping_emit(x) | |||
35 | ||||
36 | #endif | |||
37 | ||||
38 | ||||
39 | using namespace com::sun::star; | |||
40 | ||||
41 | class MediatorMapping : public uno_Mapping | |||
42 | { | |||
43 | oslInterlockedCount m_refCount; | |||
44 | ||||
45 | uno::Mapping m_from2uno; | |||
46 | uno::Mapping m_uno2to; | |||
47 | ||||
48 | uno::Environment m_from; | |||
49 | uno::Environment m_interm; | |||
50 | uno::Environment m_to; | |||
51 | ||||
52 | public: | |||
53 | void acquire(void); | |||
54 | void release(void); | |||
55 | ||||
56 | void mapInterface(void ** ppOut, | |||
57 | void * pInterface, | |||
58 | typelib_InterfaceTypeDescription * pInterfaceTypeDescr); | |||
59 | MediatorMapping(uno_Environment * pFrom, | |||
60 | uno_Environment * pInterm, | |||
61 | uno_Environment * pTo); | |||
62 | ~MediatorMapping(); | |||
63 | }; | |||
64 | ||||
65 | extern "C" { | |||
66 | static void SAL_CALL s_acquire(uno_Mapping * mapping) | |||
67 | { | |||
68 | MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); | |||
69 | pMediatorMapping->acquire(); | |||
70 | } | |||
71 | ||||
72 | static void SAL_CALL s_release(uno_Mapping * mapping) | |||
73 | { | |||
74 | MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); | |||
75 | pMediatorMapping->release(); | |||
76 | } | |||
77 | ||||
78 | static void SAL_CALL s_mapInterface( | |||
79 | uno_Mapping * mapping, | |||
80 | void ** ppOut, | |||
81 | void * pInterface, | |||
82 | typelib_InterfaceTypeDescription * pInterfaceTypeDescr) | |||
83 | { | |||
84 | MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); | |||
85 | pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr); | |||
86 | } | |||
87 | } | |||
88 | ||||
89 | MediatorMapping::MediatorMapping(uno_Environment * pFrom, | |||
90 | uno_Environment * pInterm, | |||
91 | uno_Environment * pTo) | |||
92 | : m_refCount(0), | |||
93 | m_from2uno(pFrom, pInterm), | |||
94 | m_uno2to (pInterm, pTo), | |||
95 | m_from (pFrom), | |||
96 | m_interm (pInterm), | |||
97 | m_to (pTo) | |||
98 | { | |||
99 | LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); | |||
100 | ||||
101 | if (!m_from2uno.get() || !m_uno2to.get()) | |||
102 | abort(); | |||
103 | ||||
104 | uno_Mapping::acquire = s_acquire; | |||
105 | uno_Mapping::release = s_release; | |||
106 | uno_Mapping::mapInterface = s_mapInterface; | |||
107 | } | |||
108 | ||||
109 | MediatorMapping::~MediatorMapping() | |||
110 | { | |||
111 | LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); | |||
112 | } | |||
113 | ||||
114 | void MediatorMapping::acquire(void) | |||
115 | { | |||
116 | LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); | |||
117 | ||||
118 | osl_incrementInterlockedCount(&m_refCount); | |||
119 | } | |||
120 | ||||
121 | void MediatorMapping::release(void) | |||
122 | { | |||
123 | LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); | |||
124 | ||||
125 | if (osl_decrementInterlockedCount(&m_refCount) == 0) | |||
126 | { | |||
127 | ::uno_revokeMapping(this); | |||
128 | } | |||
129 | } | |||
130 | ||||
131 | extern "C" { static void s_mapInterface_v(va_list * pParam) | |||
132 | { | |||
133 | void ** ppOut = va_arg(*pParam, void **)__builtin_va_arg(*pParam, void **); | |||
134 | void * pInterface = va_arg(*pParam, void *)__builtin_va_arg(*pParam, void *); | |||
135 | typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *)__builtin_va_arg(*pParam, typelib_InterfaceTypeDescription *); | |||
136 | uno_Mapping * pMapping = va_arg(*pParam, uno_Mapping *)__builtin_va_arg(*pParam, uno_Mapping *); | |||
137 | ||||
138 | pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr); | |||
139 | }} | |||
140 | ||||
141 | void MediatorMapping::mapInterface( | |||
142 | void ** ppOut, | |||
143 | void * pInterface, | |||
144 | typelib_InterfaceTypeDescription * pInterfaceTypeDescr) | |||
145 | { | |||
146 | if (*ppOut != 0) | |||
| ||||
147 | { | |||
148 | uno_ExtEnvironment * env = m_to.get()->pExtEnv; | |||
149 | OSL_ASSERT( env != 0 )do { if (true && (!(env != 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/cppu/source/uno/cascade_mapping.cxx" ":" "149" ": "), "OSL_ASSERT: %s", "env != 0"); } } while (false ); | |||
150 | env->releaseInterface( env, *ppOut ); | |||
| ||||
151 | *ppOut = NULL__null; | |||
152 | } | |||
153 | ||||
154 | void * ret = 0; | |||
155 | uno_Interface * pUnoI = 0; | |||
156 | ||||
157 | m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get()); | |||
158 | ||||
159 | m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr); | |||
160 | ||||
161 | if (pUnoI) | |||
162 | m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI); | |||
163 | ||||
164 | *ppOut = ret; | |||
165 | } | |||
166 | ||||
167 | extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping) | |||
168 | SAL_THROW_EXTERN_C()throw () | |||
169 | { | |||
170 | delete static_cast<MediatorMapping *>(pMapping); | |||
171 | }} | |||
172 | ||||
173 | ||||
174 | ||||
175 | static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) | |||
176 | { | |||
177 | sal_Int32 nIndex1 = 0; | |||
178 | sal_Int32 nIndex2 = 0; | |||
179 | sal_Int32 sim = 0; | |||
180 | ||||
181 | rtl::OUString token1; | |||
182 | rtl::OUString token2; | |||
183 | ||||
184 | do | |||
185 | { | |||
186 | token1 = str1.getToken(0, ':', nIndex1); | |||
187 | token2 = str2.getToken(0, ':', nIndex2); | |||
188 | ||||
189 | if (token1.equals(token2)) | |||
190 | sim += token1.getLength() + 1; | |||
191 | } | |||
192 | while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); | |||
193 | ||||
194 | rtl::OUString result; | |||
195 | ||||
196 | if (sim) | |||
197 | result = str1.copy(0, sim - 1); | |||
198 | ||||
199 | return result; | |||
200 | } | |||
201 | ||||
202 | // rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi")); | |||
203 | // rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def")); | |||
204 | // rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc")); | |||
205 | // rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM("")); | |||
206 | ||||
207 | // rtl::OUString pref; | |||
208 | ||||
209 | // pref = getPrefix(str1, str1); | |||
210 | // pref = getPrefix(str1, str2); | |||
211 | // pref = getPrefix(str1, str3); | |||
212 | // pref = getPrefix(str1, str4); | |||
213 | ||||
214 | // pref = getPrefix(str2, str1); | |||
215 | // pref = getPrefix(str3, str1); | |||
216 | // pref = getPrefix(str4, str1); | |||
217 | ||||
218 | ||||
219 | void getCascadeMapping(uno_Mapping ** ppMapping, | |||
220 | uno_Environment * pFrom, | |||
221 | uno_Environment * pTo, | |||
222 | rtl_uString * pAddPurpose) | |||
223 | { | |||
224 | if (pAddPurpose && pAddPurpose->length) | |||
225 | return; | |||
226 | ||||
227 | rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)(&("uno")[0]), ((sal_Int32)((sizeof ("uno") / sizeof (("uno" )[0]))-1)), (((rtl_TextEncoding) 11))); | |||
228 | ||||
229 | rtl::OUString from_envType = cppu::EnvDcp::getTypeName(pFrom->pTypeName); | |||
230 | rtl::OUString to_envType = cppu::EnvDcp::getTypeName(pTo->pTypeName); | |||
231 | rtl::OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName); | |||
232 | rtl::OUString to_envPurpose = cppu::EnvDcp::getPurpose(pTo->pTypeName); | |||
233 | ||||
234 | #ifdef LOG_CALLING_named_purpose_getMapping | |||
235 | rtl::OString s_from_name = rtl::OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | |||
236 | rtl::OString s_to_name = rtl::OUStringToOString(pTo->pTypeName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | |||
237 | ||||
238 | std::cerr << __FUNCTION__ << " - creating mediation "; | |||
239 | std::cerr << "pFrom: " << s_from_name.getStr(); | |||
240 | std::cerr <<" pTo: " << s_to_name.getStr() << std::endl; | |||
241 | #endif | |||
242 | ||||
243 | if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla | |||
244 | return; | |||
245 | ||||
246 | // reaching this point means, we need a mediated mapping!!! | |||
247 | // we generall mediate via uno[:free] | |||
248 | uno_Environment * pInterm = NULL__null; | |||
249 | ||||
250 | // chained uno -> uno | |||
251 | if (from_envType == uno_envType && to_envType == uno_envType) | |||
252 | { | |||
253 | rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); | |||
254 | ||||
255 | rtl::OUString uno_envDcp = uno_envType; | |||
256 | uno_envDcp += purpose; | |||
257 | ||||
258 | // direct mapping possible? | |||
259 | // uno:bla-->uno:bla:blubb | |||
260 | if (from_envPurpose.equals(purpose)) | |||
261 | { | |||
262 | rtl::OUString rest = to_envPurpose.copy(purpose.getLength()); | |||
263 | ||||
264 | sal_Int32 index = rest.indexOf(':', 1); | |||
265 | if (index == -1) | |||
266 | { | |||
267 | uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); | |||
268 | return; | |||
269 | } | |||
270 | ||||
271 | uno_envDcp += rest.copy(0, index); | |||
272 | } | |||
273 | else if (to_envPurpose.equals(purpose)) | |||
274 | { | |||
275 | rtl::OUString rest = from_envPurpose.copy(purpose.getLength()); | |||
276 | ||||
277 | sal_Int32 index = rest.indexOf(':', 1); | |||
278 | if (index == -1) | |||
279 | { | |||
280 | uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); | |||
281 | return; | |||
282 | } | |||
283 | ||||
284 | uno_envDcp += rest.copy(0, index); | |||
285 | } | |||
286 | ||||
287 | uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL__null); | |||
288 | } | |||
289 | else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ? | |||
290 | // mediate via uno:purpose(fromEnv) | |||
291 | { | |||
292 | rtl::OUString envDcp = uno_envType; | |||
293 | ||||
294 | envDcp += from_envPurpose; | |||
295 | uno_getEnvironment(&pInterm, envDcp.pData, NULL__null); | |||
296 | } | |||
297 | else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>? | |||
298 | // mediate via uno(context) | |||
299 | { | |||
300 | rtl::OUString envDcp = uno_envType; | |||
301 | ||||
302 | envDcp += to_envPurpose; | |||
303 | uno_getEnvironment(&pInterm, envDcp.pData, NULL__null); | |||
304 | } | |||
305 | else // everything else | |||
306 | // mediate via uno:purpose | |||
307 | { | |||
308 | rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); | |||
309 | ||||
310 | rtl::OUString uno_envDcp = uno_envType; | |||
311 | uno_envDcp += purpose; | |||
312 | ||||
313 | uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL__null); | |||
314 | } | |||
315 | ||||
316 | uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo); | |||
317 | pInterm->release(pInterm); | |||
318 | ||||
319 | ||||
320 | pMapping->acquire(pMapping); | |||
321 | ||||
322 | ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose); | |||
323 | ||||
324 | if (*ppMapping) | |||
325 | (*ppMapping)->release(*ppMapping); | |||
326 | ||||
327 | *ppMapping = pMapping; | |||
328 | } | |||
329 | ||||
330 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |