Avoid potential negative array index access to cached text.
[LibreOffice.git] / sal / osl / unx / module.cxx
blob0da54f475847daf5e9f898f33d36ed550f9e86a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <sal/log.hxx>
23 #include <sal/types.h>
24 #include <osl/module.h>
25 #include <osl/thread.h>
26 #include <osl/file.h>
27 #include <rtl/string.hxx>
28 #include <rtl/ustring.hxx>
29 #include <assert.h>
30 #include <dlfcn.h>
31 #include <limits.h>
32 #include "file_url.hxx"
34 static bool getModulePathFromAddress(void * address, rtl_String ** path)
36 bool result = false;
37 #if HAVE_UNIX_DLAPI
38 Dl_info dl_info;
40 result = dladdr(address, &dl_info) != 0;
42 if (result)
44 rtl_string_newFromStr(path, dl_info.dli_fname);
46 #else
47 (void) address;
48 (void) path;
49 #endif
50 return result;
53 #ifndef DISABLE_DYNLOADING
55 /*****************************************************************************/
56 /* osl_loadModule */
57 /*****************************************************************************/
59 oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
61 oslModule pModule=nullptr;
62 rtl_uString* ustrTmp = nullptr;
64 SAL_WARN_IF(ustrModuleName == nullptr, "sal.osl", "string is not valid");
66 /* ensure ustrTmp hold valid string */
67 if (osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp) != osl_File_E_None)
68 rtl_uString_assign(&ustrTmp, ustrModuleName);
70 if (ustrTmp)
72 char buffer[PATH_MAX];
74 if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
75 pModule = osl_loadModuleAscii(buffer, nRtldMode);
76 rtl_uString_release(ustrTmp);
79 return pModule;
82 /*****************************************************************************/
83 /* osl_loadModuleAscii */
84 /*****************************************************************************/
86 oslModule SAL_CALL osl_loadModuleAscii(const char *pModuleName, sal_Int32 nRtldMode)
88 #if HAVE_UNIX_DLAPI
89 SAL_WARN_IF(
90 ((nRtldMode & SAL_LOADMODULE_LAZY) != 0
91 && (nRtldMode & SAL_LOADMODULE_NOW) != 0),
92 "sal.osl", "only either LAZY or NOW");
93 if (pModuleName)
95 int rtld_mode =
96 ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
97 ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
98 void* pLib = dlopen(pModuleName, rtld_mode);
100 SAL_WARN_IF(
101 pLib == nullptr, "sal.osl",
102 "dlopen(" << pModuleName << ", " << rtld_mode << "): "
103 << dlerror());
104 return pLib;
106 #else
107 (void) pModuleName;
108 (void) nRtldMode;
109 #endif
110 return nullptr;
113 oslModule osl_loadModuleRelativeAscii(
114 oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
116 assert(relativePath && "illegal argument");
117 if (relativePath[0] == '/') {
118 return osl_loadModuleAscii(relativePath, mode);
120 rtl_String * path = nullptr;
121 rtl_String * suffix = nullptr;
122 oslModule module;
123 if (!getModulePathFromAddress(
124 reinterpret_cast< void * >(baseModule), &path))
126 return nullptr;
128 rtl_string_newFromStr_WithLength(
129 &path, path->buffer,
130 (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
131 + 1));
132 /* cut off everything after the last slash; should the original path
133 contain no slash, the resulting path is the empty string */
134 rtl_string_newFromStr(&suffix, relativePath);
135 rtl_string_newConcat(&path, path, suffix);
136 rtl_string_release(suffix);
137 module = osl_loadModuleAscii(path->buffer, mode);
138 rtl_string_release(path);
139 return module;
142 #endif // !DISABLE_DYNLOADING
144 /*****************************************************************************/
145 /* osl_getModuleHandle */
146 /*****************************************************************************/
148 sal_Bool SAL_CALL
149 osl_getModuleHandle(rtl_uString *, oslModule *pResult)
151 #if HAVE_UNIX_DLAPI
152 *pResult = static_cast<oslModule>(RTLD_DEFAULT);
153 return true;
154 #else
155 *pResult = nullptr;
156 return false;
157 #endif
160 /*****************************************************************************/
161 /* osl_unloadModule */
162 /*****************************************************************************/
163 void SAL_CALL osl_unloadModule(oslModule hModule)
165 #if !defined(DISABLE_DYNLOADING) && HAVE_UNIX_DLAPI
166 if (hModule)
168 int nRet = dlclose(hModule);
169 SAL_INFO_IF(
170 nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
172 #else
173 (void) hModule;
174 #endif
177 namespace {
179 void * getSymbol(oslModule module, char const * symbol)
181 assert(symbol != nullptr);
182 #if HAVE_UNIX_DLAPI
183 // We do want to use dlsym() also in the DISABLE_DYNLOADING case
184 // just to look up symbols in the static executable, I think:
185 void * p = dlsym(module, symbol);
186 SAL_INFO_IF(
187 p == nullptr, "sal.osl",
188 "dlsym(" << module << ", " << symbol << "): " << dlerror());
189 #else
190 (void) module;
191 (void) symbol;
192 void *p = nullptr;
193 #endif
194 return p;
199 /*****************************************************************************/
200 /* osl_getSymbol */
201 /*****************************************************************************/
202 void* SAL_CALL
203 osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
205 // Arbitrarily using UTF-8:
206 OString s;
207 if (!OUString::unacquired(&pSymbolName).convertToString(
208 &s, RTL_TEXTENCODING_UTF8,
209 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
210 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
212 SAL_INFO(
213 "sal.osl", "cannot convert \"" << OUString::unacquired(&pSymbolName)
214 << "\" to UTF-8");
215 return nullptr;
217 if (s.indexOf('\0') != -1) {
218 SAL_INFO("sal.osl", "\"" << s << "\" contains embedded NUL");
219 return nullptr;
221 return getSymbol(Module, s.getStr());
224 /*****************************************************************************/
225 /* osl_getAsciiFunctionSymbol */
226 /*****************************************************************************/
227 oslGenericFunction SAL_CALL
228 osl_getAsciiFunctionSymbol(oslModule Module, const char *pSymbol)
230 return reinterpret_cast<oslGenericFunction>(getSymbol(Module, pSymbol));
231 // requires conditionally-supported conversion from void * to function
232 // pointer
235 /*****************************************************************************/
236 /* osl_getFunctionSymbol */
237 /*****************************************************************************/
238 oslGenericFunction SAL_CALL
239 osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
241 return reinterpret_cast<oslGenericFunction>(
242 osl_getSymbol(module, puFunctionSymbolName));
243 // requires conditionally-supported conversion from void * to function
244 // pointer
247 /*****************************************************************************/
248 /* osl_getModuleURLFromAddress */
249 /*****************************************************************************/
250 sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
252 bool result = false;
253 rtl_String * path = nullptr;
254 if (getModulePathFromAddress(addr, &path))
256 rtl_string2UString(ppLibraryUrl,
257 path->buffer,
258 path->length,
259 osl_getThreadTextEncoding(),
260 OSTRING_TO_OUSTRING_CVTFLAGS);
262 SAL_WARN_IF(
263 *ppLibraryUrl == nullptr, "sal.osl", "rtl_string2UString failed");
264 auto const e = osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
265 if (e == osl_File_E_None)
267 SAL_INFO("sal.osl", "osl_getModuleURLFromAddress(" << addr << ") => " << OUString(*ppLibraryUrl));
269 result = true;
271 else
273 SAL_WARN(
274 "sal.osl",
275 "osl_getModuleURLFromAddress(" << addr << "), osl_getFileURLFromSystemPath("
276 << OUString::unacquired(ppLibraryUrl) << ") failed with " << e);
277 result = false;
279 rtl_string_release(path);
281 return result;
284 /*****************************************************************************/
285 /* osl_getModuleURLFromFunctionAddress */
286 /*****************************************************************************/
287 sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
289 return osl_getModuleURLFromAddress(
290 reinterpret_cast<void*>(addr), ppLibraryUrl);
291 // requires conditionally-supported conversion from function pointer to
292 // void *
295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */