Bug Summary

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')

Annotated Source Code

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
39using namespace com::sun::star;
40
41class 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
52public:
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
65extern "C" {
66static void SAL_CALL s_acquire(uno_Mapping * mapping)
67{
68 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
69 pMediatorMapping->acquire();
70}
71
72static void SAL_CALL s_release(uno_Mapping * mapping)
73{
74 MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
75 pMediatorMapping->release();
76}
77
78static 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
89MediatorMapping::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
109MediatorMapping::~MediatorMapping()
110{
111 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
112}
113
114void MediatorMapping::acquire(void)
115{
116 LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl);
117
118 osl_incrementInterlockedCount(&m_refCount);
119}
120
121void 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
131extern "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
141void MediatorMapping::mapInterface(
142 void ** ppOut,
143 void * pInterface,
144 typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
145{
146 if (*ppOut != 0)
1
Taking true branch
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
)
;
2
Within the expansion of the macro 'OSL_ASSERT':
a
Assuming 'env' is equal to null
150 env->releaseInterface( env, *ppOut );
3
Access to field 'releaseInterface' results in a dereference of a null pointer (loaded from variable 'env')
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
167extern "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
175static 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
219void 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: */