1 /* libxml2 - Library for parsing XML documents
2  * Copyright (C) 2006-2019 Free Software Foundation, Inc.
3  *
4  * This file is not part of the GNU gettext program, but is used with
5  * GNU gettext.
6  *
7  * The original copyright notice is as follows:
8  */
9 
10 /*
11  * Copyright (C) 1998-2012 Daniel Veillard.  All Rights Reserved.
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is fur-
18  * nished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
25  * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29  * THE SOFTWARE.
30  *
31  * joelwreed@comcast.net
32  *
33  * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
34  */
35 
36 /*
37  * xmlmodule.c : basic API for dynamic module loading added 2.6.17
38  */
39 
40 /* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
41 #if defined(__MVS__)
42 #define _UNIX03_SOURCE
43 #endif
44 
45 #define IN_LIBXML
46 #include "libxml.h"
47 
48 #include <string.h>
49 #include <libxml/xmlmemory.h>
50 #include <libxml/xmlerror.h>
51 #include <libxml/xmlmodule.h>
52 #include <libxml/globals.h>
53 
54 #ifdef LIBXML_MODULES_ENABLED
55 
56 struct _xmlModule {
57     unsigned char *name;
58     void *handle;
59 };
60 
61 static void *xmlModulePlatformOpen(const char *name);
62 static int xmlModulePlatformClose(void *handle);
63 static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
64 
65 /************************************************************************
66  *									*
67  *		module memory error handler				*
68  *									*
69  ************************************************************************/
70 
71 /**
72  * xmlModuleErrMemory:
73  * @extra:  extra information
74  *
75  * Handle an out of memory condition
76  */
77 static void
xmlModuleErrMemory(xmlModulePtr module,const char * extra)78 xmlModuleErrMemory(xmlModulePtr module, const char *extra)
79 {
80     const char *name = NULL;
81 
82     if (module != NULL) {
83         name = (const char *) module->name;
84     }
85 
86     __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
87                     XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
88                     name, NULL, 0, 0,
89                     "Memory allocation failed : %s\n", extra);
90 }
91 
92 /**
93  * xmlModuleOpen:
94  * @name: the module name
95  * @options: a set of xmlModuleOption
96  *
97  * Opens a module/shared library given its name or path
98  * NOTE: that due to portability issues, behaviour can only be
99  * guaranteed with @name using ASCII. We canot guarantee that
100  * an UTF-8 string would work, which is why name is a const char *
101  * and not a const xmlChar * .
102  * TODO: options are not yet implemented.
103  *
104  * Returns a handle for the module or NULL in case of error
105  */
106 xmlModulePtr
xmlModuleOpen(const char * name,int options ATTRIBUTE_UNUSED)107 xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
108 {
109     xmlModulePtr module;
110 
111     module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
112     if (module == NULL) {
113         xmlModuleErrMemory(NULL, "creating module");
114         return (NULL);
115     }
116 
117     memset(module, 0, sizeof(xmlModule));
118 
119     module->handle = xmlModulePlatformOpen(name);
120 
121     if (module->handle == NULL) {
122         xmlFree(module);
123         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
124                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
125                         name, NULL, 0, 0, "failed to open %s\n", name);
126         return(NULL);
127     }
128 
129     module->name = xmlStrdup((const xmlChar *) name);
130     return (module);
131 }
132 
133 /**
134  * xmlModuleSymbol:
135  * @module: the module
136  * @name: the name of the symbol
137  * @symbol: the resulting symbol address
138  *
139  * Lookup for a symbol address in the given module
140  * NOTE: that due to portability issues, behaviour can only be
141  * guaranteed with @name using ASCII. We canot guarantee that
142  * an UTF-8 string would work, which is why name is a const char *
143  * and not a const xmlChar * .
144  *
145  * Returns 0 if the symbol was found, or -1 in case of error
146  */
147 int
xmlModuleSymbol(xmlModulePtr module,const char * name,void ** symbol)148 xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
149 {
150     int rc = -1;
151 
152     if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
153         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
154                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
155                         NULL, NULL, 0, 0, "null parameter\n");
156         return rc;
157     }
158 
159     rc = xmlModulePlatformSymbol(module->handle, name, symbol);
160 
161     if (rc == -1) {
162         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
163                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
164                         name, NULL, 0, 0,
165                         "failed to find symbol: %s\n",
166 			(name == NULL ? "NULL" : name));
167         return rc;
168     }
169 
170     return rc;
171 }
172 
173 /**
174  * xmlModuleClose:
175  * @module: the module handle
176  *
177  * The close operations unload the associated module and free the
178  * data associated to the module.
179  *
180  * Returns 0 in case of success, -1 in case of argument error and -2
181  *         if the module could not be closed/unloaded.
182  */
183 int
xmlModuleClose(xmlModulePtr module)184 xmlModuleClose(xmlModulePtr module)
185 {
186     int rc;
187 
188     if (NULL == module) {
189         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
190                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
191                         NULL, NULL, 0, 0, "null module pointer\n");
192         return -1;
193     }
194 
195     rc = xmlModulePlatformClose(module->handle);
196 
197     if (rc != 0) {
198         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
199                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
200                         (const char *) module->name, NULL, 0, 0,
201                         "failed to close: %s\n", module->name);
202         return -2;
203     }
204 
205     rc = xmlModuleFree(module);
206     return (rc);
207 }
208 
209 /**
210  * xmlModuleFree:
211  * @module: the module handle
212  *
213  * The free operations free the data associated to the module
214  * but does not unload the associated shared library which may still
215  * be in use.
216  *
217  * Returns 0 in case of success, -1 in case of argument error
218  */
219 int
xmlModuleFree(xmlModulePtr module)220 xmlModuleFree(xmlModulePtr module)
221 {
222     if (NULL == module) {
223         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
224                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
225                         NULL, NULL, 0, 0, "null module pointer\n");
226         return -1;
227     }
228 
229     xmlFree(module->name);
230     xmlFree(module);
231 
232     return (0);
233 }
234 
235 #if defined(HAVE_DLOPEN) && !defined(_WIN32)
236 #ifdef HAVE_DLFCN_H
237 #include <dlfcn.h>
238 #endif
239 
240 #ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */
241 #define RTLD_GLOBAL 0
242 #endif
243 
244 /**
245  * xmlModulePlatformOpen:
246  * @name: path to the module
247  *
248  * returns a handle on success, and zero on error.
249  */
250 
251 static void *
xmlModulePlatformOpen(const char * name)252 xmlModulePlatformOpen(const char *name)
253 {
254     return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
255 }
256 
257 /*
258  * xmlModulePlatformClose:
259  * @handle: handle to the module
260  *
261  * returns 0 on success, and non-zero on error.
262  */
263 
264 static int
xmlModulePlatformClose(void * handle)265 xmlModulePlatformClose(void *handle)
266 {
267     return dlclose(handle);
268 }
269 
270 /*
271  * xmlModulePlatformSymbol:
272  * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
273  * returns 0 on success and the loaded symbol in result, and -1 on error.
274  */
275 
276 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)277 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
278 {
279     *symbol = dlsym(handle, name);
280     if (dlerror() != NULL) {
281 	return -1;
282     }
283     return 0;
284 }
285 
286 #else /* ! HAVE_DLOPEN */
287 
288 #ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */
289 #ifdef HAVE_DL_H
290 #include <dl.h>
291 #endif
292 /*
293  * xmlModulePlatformOpen:
294  * returns a handle on success, and zero on error.
295  */
296 
297 static void *
xmlModulePlatformOpen(const char * name)298 xmlModulePlatformOpen(const char *name)
299 {
300     return shl_load(name, BIND_IMMEDIATE, 0L);
301 }
302 
303 /*
304  * xmlModulePlatformClose:
305  * returns 0 on success, and non-zero on error.
306  */
307 
308 static int
xmlModulePlatformClose(void * handle)309 xmlModulePlatformClose(void *handle)
310 {
311     return shl_unload(handle);
312 }
313 
314 /*
315  * xmlModulePlatformSymbol:
316  * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
317  * returns 0 on success and the loaded symbol in result, and -1 on error.
318  */
319 
320 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)321 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
322 {
323     int rc;
324 
325     errno = 0;
326     rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
327     return rc;
328 }
329 
330 #endif /* HAVE_SHLLOAD */
331 #endif /* ! HAVE_DLOPEN */
332 
333 #if defined(_WIN32) && !defined(__CYGWIN__)
334 
335 #define WIN32_LEAN_AND_MEAN
336 #include <windows.h>
337 
338 /*
339  * xmlModulePlatformOpen:
340  * returns a handle on success, and zero on error.
341  */
342 
343 static void *
xmlModulePlatformOpen(const char * name)344 xmlModulePlatformOpen(const char *name)
345 {
346     return LoadLibraryA(name);
347 }
348 
349 /*
350  * xmlModulePlatformClose:
351  * returns 0 on success, and non-zero on error.
352  */
353 
354 static int
xmlModulePlatformClose(void * handle)355 xmlModulePlatformClose(void *handle)
356 {
357     int rc;
358 
359     rc = FreeLibrary(handle);
360     return (0 == rc);
361 }
362 
363 /*
364  * xmlModulePlatformSymbol:
365  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
366  * returns 0 on success and the loaded symbol in result, and -1 on error.
367  */
368 
369 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)370 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
371 {
372 XML_IGNORE_PEDANTIC_WARNINGS
373 #ifdef _WIN32_WCE
374     /*
375      * GetProcAddressA seems only available on WinCE
376      */
377     *symbol = GetProcAddressA(handle, name);
378 #else
379     *symbol = GetProcAddress(handle, name);
380 #endif
381     return (NULL == *symbol) ? -1 : 0;
382 XML_POP_WARNINGS
383 }
384 
385 #endif /* _WIN32 */
386 
387 #ifdef HAVE_BEOS
388 
389 #include <kernel/image.h>
390 
391 /*
392  * xmlModulePlatformOpen:
393  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
394  * returns a handle on success, and zero on error.
395  */
396 
397 static void *
xmlModulePlatformOpen(const char * name)398 xmlModulePlatformOpen(const char *name)
399 {
400     return (void *) load_add_on(name);
401 }
402 
403 /*
404  * xmlModulePlatformClose:
405  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
406  * returns 0 on success, and non-zero on error.
407  */
408 
409 static int
xmlModulePlatformClose(void * handle)410 xmlModulePlatformClose(void *handle)
411 {
412     status_t rc;
413 
414     rc = unload_add_on((image_id) handle);
415 
416     if (rc == B_OK)
417         return 0;
418     else
419         return -1;
420 }
421 
422 /*
423  * xmlModulePlatformSymbol:
424  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
425  * returns 0 on success and the loaded symbol in result, and -1 on error.
426  */
427 
428 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)429 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
430 {
431     status_t rc;
432 
433     rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
434 
435     return (rc == B_OK) ? 0 : -1;
436 }
437 
438 #endif /* HAVE_BEOS */
439 
440 #ifdef HAVE_OS2
441 
442 #include <os2.h>
443 
444 /*
445  * xmlModulePlatformOpen:
446  * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
447  * returns a handle on success, and zero on error.
448  */
449 
450 static void *
xmlModulePlatformOpen(const char * name)451 xmlModulePlatformOpen(const char *name)
452 {
453     char errbuf[256];
454     void *handle;
455     int rc;
456 
457     rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
458 
459     if (rc)
460         return 0;
461     else
462         return (handle);
463 }
464 
465 /*
466  * xmlModulePlatformClose:
467  * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
468  * returns 0 on success, and non-zero on error.
469  */
470 
471 static int
xmlModulePlatformClose(void * handle)472 xmlModulePlatformClose(void *handle)
473 {
474     return DosFreeModule(handle);
475 }
476 
477 /*
478  * xmlModulePlatformSymbol:
479  * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
480  * returns 0 on success and the loaded symbol in result, and -1 on error.
481  */
482 
483 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)484 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
485 {
486     int rc;
487 
488     rc = DosQueryProcAddr(handle, 0, name, symbol);
489 
490     return (rc == NO_ERROR) ? 0 : -1;
491 }
492 
493 #endif /* HAVE_OS2 */
494 
495 #define bottom_xmlmodule
496 #include "elfgcchack.h"
497 #endif /* LIBXML_MODULES_ENABLED */
498