| 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: */ |