Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/registry.c
Location:line 276, column 33
Description:Access to field 'shutdownServerFn' results in a dereference of a null pointer (loaded from variable 'registryP')

Annotated Source Code

1/*=========================================================================
2 XML-RPC Server Method Registry
3===========================================================================
4 These are the functions that implement the XML-RPC method registry.
5
6 A method registry is a list of XML-RPC methods for a server to
7 implement, along with the details of how to implement each -- most
8 notably a function pointer for a function that executes the method.
9
10 To build an XML-RPC server, just add a communication facility.
11
12 Copyright information is at end of file
13
14=========================================================================*/
15
16#include <assert.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "xmlrpc_config.h"
21#include "bool.h"
22#include "mallocvar.h"
23#include "xmlrpc-c/base_int.h"
24#include "xmlrpc-c/string_int.h"
25#include "xmlrpc-c/base.h"
26#include "xmlrpc-c/server.h"
27#include "method.h"
28#include "system_method.h"
29#include "version.h"
30
31#include "registry.h"
32
33
34unsigned int const xmlrpc_server_version_major = XMLRPC_VERSION_MAJOR1;
35unsigned int const xmlrpc_server_version_minor = XMLRPC_VERSION_MINOR26;
36unsigned int const xmlrpc_server_version_point = XMLRPC_VERSION_POINT0;
37
38
39
40void
41xmlrpc_server_version(unsigned int * const majorP,
42 unsigned int * const minorP,
43 unsigned int * const pointP) {
44
45 *majorP = XMLRPC_VERSION_MAJOR1;
46 *minorP = XMLRPC_VERSION_MINOR26;
47 *pointP = XMLRPC_VERSION_POINT0;
48}
49
50
51
52xmlrpc_registry *
53xmlrpc_registry_new(xmlrpc_env * const envP) {
54
55 xmlrpc_registry * registryP;
56
57 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 57); while (0)
;
58
59 MALLOCVAR(registryP)registryP = malloc(sizeof(*registryP));
60
61 if (registryP == NULL((void*)0))
62 xmlrpc_faultf(envP, "Could not allocate memory for registry");
63 else {
64 registryP->introspectionEnabled = true;
65 registryP->defaultMethodFunction = NULL((void*)0);
66 registryP->preinvokeFunction = NULL((void*)0);
67 registryP->shutdownServerFn = NULL((void*)0);
68 registryP->dialect = xmlrpc_dialect_i8;
69
70 xmlrpc_methodListCreate(envP, &registryP->methodListP);
71 if (!envP->fault_occurred)
72 xmlrpc_installSystemMethods(envP, registryP);
73
74 if (envP->fault_occurred)
75 free(registryP);
76 }
77 return registryP;
78}
79
80
81
82void
83xmlrpc_registry_free(xmlrpc_registry * const registryP) {
84
85 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/registry.c", 85); while (0)
;
86
87 xmlrpc_methodListDestroy(registryP->methodListP);
88
89 free(registryP);
90}
91
92
93
94static void
95registryAddMethod(xmlrpc_env * const envP,
96 xmlrpc_registry * const registryP,
97 const char * const methodName,
98 xmlrpc_method1 method1,
99 xmlrpc_method2 method2,
100 const char * const signatureString,
101 const char * const help,
102 void * const userData,
103 size_t const stackSize) {
104
105 const char * const helpString =
106 help ? help : "No help is available for this method.";
107
108 xmlrpc_methodInfo * methodP;
109
110 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 110); while (0)
;
111 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/registry.c", 111); while (0)
;
112 XMLRPC_ASSERT_PTR_OK(methodName)do if (!((methodName) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 112); while (0)
;
113 XMLRPC_ASSERT(method1 != NULL || method2 != NULL)do if (!(method1 != ((void*)0) || method2 != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 113); while (0)
;
114
115 xmlrpc_methodCreate(envP, method1, method2, userData,
116 signatureString, helpString, stackSize, &methodP);
117
118 if (!envP->fault_occurred) {
119 xmlrpc_methodListAdd(envP, registryP->methodListP, methodName,
120 methodP);
121
122 if (envP->fault_occurred)
123 xmlrpc_methodDestroy(methodP);
124 }
125}
126
127
128
129void
130xmlrpc_registry_add_method_w_doc(
131 xmlrpc_env * const envP,
132 xmlrpc_registry * const registryP,
133 const char * const host ATTR_UNUSED__attribute__((__unused__)),
134 const char * const methodName,
135 xmlrpc_method1 const method,
136 void * const serverInfo,
137 const char * const signatureString,
138 const char * const help) {
139
140 XMLRPC_ASSERT(host == NULL)do if (!(host == ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c"
, 140); while (0)
;
141
142 registryAddMethod(envP, registryP, methodName, method, NULL((void*)0),
143 signatureString, help, serverInfo, 0);
144}
145
146
147
148void
149xmlrpc_registry_add_method(xmlrpc_env * const envP,
150 xmlrpc_registry * const registryP,
151 const char * const host,
152 const char * const methodName,
153 xmlrpc_method1 const method,
154 void * const serverInfoP) {
155
156 xmlrpc_registry_add_method_w_doc(
157 envP, registryP, host, methodName,
158 method, serverInfoP, "?", "No help is available for this method.");
159}
160
161
162
163void
164xmlrpc_registry_add_method2(xmlrpc_env * const envP,
165 xmlrpc_registry * const registryP,
166 const char * const methodName,
167 xmlrpc_method2 method,
168 const char * const signatureString,
169 const char * const help,
170 void * const serverInfo) {
171
172 registryAddMethod(envP, registryP, methodName, NULL((void*)0), method,
173 signatureString, help, serverInfo, 0);
174}
175
176
177
178void
179xmlrpc_registry_add_method3(
180 xmlrpc_env * const envP,
181 xmlrpc_registry * const registryP,
182 const struct xmlrpc_method_info3 * const infoP) {
183
184 registryAddMethod(envP, registryP, infoP->methodName, NULL((void*)0),
185 infoP->methodFunction,
186 infoP->signatureString, infoP->help, infoP->serverInfo,
187 infoP->stackSize);
188}
189
190
191
192void
193xmlrpc_registry_set_default_method(
194 xmlrpc_env * const envP ATTR_UNUSED__attribute__((__unused__)),
195 xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)),
196 xmlrpc_default_method const function,
197 void * const userData) {
198
199 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 199); while (0)
;
200 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/registry.c", 200); while (0)
;
201 XMLRPC_ASSERT_PTR_OK(function)do if (!((function) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c"
, 201); while (0)
;
202
203 /* Note: this may be the first default method, or it may be a replacement
204 of the current one.
205 */
206
207 registryP->defaultMethodFunction = function;
208 registryP->defaultMethodUserData = userData;
209}
210
211
212
213/* This is our guess at what a method function requires when the user
214 doesn't say.
215*/
216#define METHOD_FUNCTION_STACK128*1024 128*1024
217
218
219
220static size_t
221methodStackSize(const xmlrpc_methodInfo * const methodP) {
222
223 return methodP->stackSize ==
224 0 ? METHOD_FUNCTION_STACK128*1024 : methodP->stackSize;
225}
226
227
228
229size_t
230xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP) {
231/*----------------------------------------------------------------------------
232 Return the maximum amount of stack required by the methods in registry
233 *registryP.
234
235 If there are no methods, return 0.
236-----------------------------------------------------------------------------*/
237 xmlrpc_methodNode * p;
238 size_t stackSize;
239
240 for (p = registryP->methodListP->firstMethodP, stackSize = 0;
241 p;
242 p = p->nextP) {
243
244 stackSize = MAX(stackSize, methodStackSize(p->methodP))((stackSize) > (methodStackSize(p->methodP)) ? (stackSize
) : (methodStackSize(p->methodP)))
;
245 }
246 return stackSize;
247}
248
249
250
251void
252xmlrpc_registry_set_preinvoke_method(
253 xmlrpc_env * const envP ATTR_UNUSED__attribute__((__unused__)),
254 xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)),
255 xmlrpc_preinvoke_method const function,
256 void * const userData) {
257
258 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 258); while (0)
;
259 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/registry.c", 259); while (0)
;
260 XMLRPC_ASSERT_PTR_OK(function)do if (!((function) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c"
, 260); while (0)
;
261
262 registryP->preinvokeFunction = function;
263 registryP->preinvokeUserData = userData;
264}
265
266
267
268void
269xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP,
270 xmlrpc_server_shutdown_fn * const shutdownFn,
271 void * const context) {
272
273 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/registry.c", 273); while (0)
;
1
Within the expansion of the macro 'XMLRPC_ASSERT_PTR_OK':
a
Assuming 'registryP' is equal to null
274 XMLRPC_ASSERT_PTR_OK(shutdownFn)do if (!((shutdownFn) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 274); while (0)
;
275
276 registryP->shutdownServerFn = shutdownFn;
2
Access to field 'shutdownServerFn' results in a dereference of a null pointer (loaded from variable 'registryP')
277
278 registryP->shutdownContext = context;
279}
280
281
282
283void
284xmlrpc_registry_set_dialect(xmlrpc_env * const envP,
285 xmlrpc_registry * const registryP,
286 xmlrpc_dialect const dialect) {
287
288 if (dialect != xmlrpc_dialect_i8 &&
289 dialect != xmlrpc_dialect_apache)
290 xmlrpc_faultf(envP, "Invalid dialect argument -- not of type "
291 "xmlrpc_dialect. Numerical value is %u", dialect);
292 else
293 registryP->dialect = dialect;
294}
295
296
297
298static void
299callNamedMethod(xmlrpc_env * const envP,
300 xmlrpc_methodInfo * const methodP,
301 xmlrpc_value * const paramArrayP,
302 void * const callInfoP,
303 xmlrpc_value ** const resultPP) {
304
305 if (methodP->methodFnType2)
306 *resultPP =
307 methodP->methodFnType2(envP, paramArrayP,
308 methodP->userData, callInfoP);
309 else {
310 assert(methodP->methodFnType1)((methodP->methodFnType1) ? (void) (0) : __assert_fail ("methodP->methodFnType1"
, "../../../../libs/xmlrpc-c/src/registry.c", 310, __PRETTY_FUNCTION__
))
;
311 *resultPP =
312 methodP->methodFnType1(envP, paramArrayP, methodP->userData);
313 }
314}
315
316
317
318void
319xmlrpc_dispatchCall(xmlrpc_env * const envP,
320 xmlrpc_registry * const registryP,
321 const char * const methodName,
322 xmlrpc_value * const paramArrayP,
323 void * const callInfoP,
324 xmlrpc_value ** const resultPP) {
325
326 if (registryP->preinvokeFunction)
327 registryP->preinvokeFunction(envP, methodName, paramArrayP,
328 registryP->preinvokeUserData);
329
330 if (!envP->fault_occurred) {
331 xmlrpc_methodInfo * methodP;
332
333 xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
334 &methodP);
335
336 if (methodP)
337 callNamedMethod(envP, methodP, paramArrayP, callInfoP, resultPP);
338 else {
339 if (registryP->defaultMethodFunction)
340 *resultPP = registryP->defaultMethodFunction(
341 envP, callInfoP, methodName, paramArrayP,
342 registryP->defaultMethodUserData);
343 else {
344 /* No matching method, and no default. */
345 xmlrpc_env_set_fault_formatted(
346 envP, XMLRPC_NO_SUCH_METHOD_ERROR(-506),
347 "Method '%s' not defined", methodName);
348 }
349 }
350 }
351 /* For backward compatibility, for sloppy users: */
352 if (envP->fault_occurred)
353 *resultPP = NULL((void*)0);
354}
355
356
357
358/*=========================================================================
359** xmlrpc_registry_process_call
360**=========================================================================
361**
362*/
363
364static void
365serializeFault(xmlrpc_env * const envP,
366 xmlrpc_env const fault,
367 xmlrpc_mem_block * const responseXmlP) {
368
369 xmlrpc_env env;
370
371 xmlrpc_env_init(&env);
372
373 xmlrpc_serialize_fault(&env, responseXmlP, &fault);
374
375 if (env.fault_occurred)
376 xmlrpc_faultf(envP,
377 "Executed XML-RPC method completely and it "
378 "generated a fault response, but we failed "
379 "to encode that fault response as XML-RPC "
380 "so we could send it to the client. %s",
381 env.fault_string);
382
383 xmlrpc_env_clean(&env);
384}
385
386
387
388void
389xmlrpc_registry_process_call2(xmlrpc_env * const envP,
390 xmlrpc_registry * const registryP,
391 const char * const callXml,
392 size_t const callXmlLen,
393 void * const callInfo,
394 xmlrpc_mem_block ** const responseXmlPP) {
395
396 xmlrpc_mem_block * responseXmlP;
397
398 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/registry.c", 398); while (0)
;
399 XMLRPC_ASSERT_PTR_OK(callXml)do if (!((callXml) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c"
, 399); while (0)
;
400
401 xmlrpc_traceXml("XML-RPC CALL", callXml, callXmlLen);
402
403 /* Allocate our output buffer.
404 ** If this fails, we need to die in a special fashion. */
405 responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0)xmlrpc_mem_block_new((envP), sizeof(char) * (0));
406 if (!envP->fault_occurred) {
407 const char * methodName;
408 xmlrpc_value * paramArrayP;
409 xmlrpc_env fault;
410 xmlrpc_env parseEnv;
411
412 xmlrpc_env_init(&fault);
413 xmlrpc_env_init(&parseEnv);
414
415 xmlrpc_parse_call(&parseEnv, callXml, callXmlLen,
416 &methodName, &paramArrayP);
417
418 if (parseEnv.fault_occurred)
419 xmlrpc_env_set_fault_formatted(
420 &fault, XMLRPC_PARSE_ERROR(-503),
421 "Call XML not a proper XML-RPC call. %s",
422 parseEnv.fault_string);
423 else {
424 xmlrpc_value * resultP;
425
426 xmlrpc_dispatchCall(&fault, registryP, methodName, paramArrayP,
427 callInfo, &resultP);
428
429 if (!fault.fault_occurred) {
430 xmlrpc_serialize_response2(envP, responseXmlP,
431 resultP, registryP->dialect);
432
433 xmlrpc_DECREF(resultP);
434 }
435 xmlrpc_strfree(methodName);
436 xmlrpc_DECREF(paramArrayP);
437 }
438 if (!envP->fault_occurred && fault.fault_occurred)
439 serializeFault(envP, fault, responseXmlP);
440
441 xmlrpc_env_clean(&parseEnv);
442 xmlrpc_env_clean(&fault);
443
444 if (envP->fault_occurred)
445 XMLRPC_MEMBLOCK_FREE(char, responseXmlP)xmlrpc_mem_block_free(responseXmlP);
446 else {
447 *responseXmlPP = responseXmlP;
448 xmlrpc_traceXml("XML-RPC RESPONSE",
449 XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP)((char*) xmlrpc_mem_block_contents(responseXmlP)),
450 XMLRPC_MEMBLOCK_SIZE(char, responseXmlP)(xmlrpc_mem_block_size(responseXmlP) / sizeof(char)));
451 }
452 }
453}
454
455
456
457xmlrpc_mem_block *
458xmlrpc_registry_process_call(xmlrpc_env * const envP,
459 xmlrpc_registry * const registryP,
460 const char * const host ATTR_UNUSED__attribute__((__unused__)),
461 const char * const callXml,
462 size_t const callXmlLen) {
463
464 xmlrpc_mem_block * responseXmlP;
465
466 xmlrpc_registry_process_call2(envP, registryP, callXml, callXmlLen, NULL((void*)0),
467 &responseXmlP);
468
469 return responseXmlP;
470}
471
472
473
474/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
475** Copyright (C) 2001 by Eric Kidd. All rights reserved.
476** Copyright (C) 2001 by Luke Howard. All rights reserved.
477**
478** Redistribution and use in source and binary forms, with or without
479** modification, are permitted provided that the following conditions
480** are met:
481** 1. Redistributions of source code must retain the above copyright
482** notice, this list of conditions and the following disclaimer.
483** 2. Redistributions in binary form must reproduce the above copyright
484** notice, this list of conditions and the following disclaimer in the
485** documentation and/or other materials provided with the distribution.
486** 3. The name of the author may not be used to endorse or promote products
487** derived from this software without specific prior written permission.
488**
489** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
490** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
491** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
492** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
493** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
494** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
495** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
496** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
497** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
498** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
499** SUCH DAMAGE. */