Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/method.c
Location:line 332, column 13
Description:Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP')

Annotated Source Code

1/*=========================================================================
2 XML-RPC server method registry
3 Method services
4===========================================================================
5 These are the functions that implement the method objects that
6 the XML-RPC method registry uses.
7
8 By Bryan Henderson, December 2006.
9
10 Contributed to the public domain by its author.
11=========================================================================*/
12
13#define _XOPEN_SOURCE700 600 /* Make sure strdup() is in <string.h> */
14
15#include "xmlrpc_config.h"
16
17#include <assert.h>
18#include <stdlib.h>
19#include <string.h>
20
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 "registry.h"
27
28#include "method.h"
29
30
31static void
32signatureDestroy(struct xmlrpc_signature * const signatureP) {
33
34 if (signatureP->argList)
35 free((void*)signatureP->argList);
36
37 free(signatureP);
38}
39
40
41
42static void
43translateTypeSpecifierToName(xmlrpc_env * const envP,
44 char const typeSpecifier,
45 const char ** const typeNameP) {
46
47 switch (typeSpecifier) {
48 case 'i': *typeNameP = "int"; break;
49 case 'b': *typeNameP = "boolean"; break;
50 case 'd': *typeNameP = "double"; break;
51 case 's': *typeNameP = "string"; break;
52 case '8': *typeNameP = "dateTime.iso8601"; break;
53 case '6': *typeNameP = "base64"; break;
54 case 'S': *typeNameP = "struct"; break;
55 case 'A': *typeNameP = "array"; break;
56 case 'n': *typeNameP = "nil"; break;
57 default:
58 xmlrpc_faultf(envP,
59 "Method registry contains invalid signature "
60 "data. It contains the type specifier '%c'",
61 typeSpecifier);
62 *typeNameP = NULL((void*)0); /* quiet compiler warning */
63 }
64}
65
66
67
68#if defined(_MSC_VER)
69/* MSVC 8 complains that const char ** is incompatible with void * in the
70 REALLOCARRAY. It's not.
71*/
72#pragma warning(push)
73#pragma warning(disable:4090)
74#endif
75
76static void
77makeRoomInArgList(xmlrpc_env * const envP,
78 struct xmlrpc_signature * const signatureP,
79 unsigned int const minArgCount) {
80
81 if (signatureP->argListSpace < minArgCount) {
82 REALLOCARRAY(signatureP->argList, minArgCount)do { void * array = signatureP->argList; reallocProduct(&
array, minArgCount, sizeof(signatureP->argList[0])); signatureP
->argList = array; } while (0)
;
83 if (signatureP->argList == NULL((void*)0)) {
84 xmlrpc_faultf(envP, "Couldn't get memory for a argument list for "
85 "a method signature with %u arguments", minArgCount);
86 signatureP->argListSpace = 0;
87 }
88 }
89}
90
91#if defined(_MSC_VER)
92#pragma warning(pop)
93#endif
94
95
96
97static void
98parseArgumentTypeSpecifiers(xmlrpc_env * const envP,
99 const char * const startP,
100 struct xmlrpc_signature * const signatureP,
101 const char ** const nextPP) {
102 const char * cursorP;
103
104 cursorP = startP; /* start at the beginning */
105
106 while (!envP->fault_occurred && *cursorP != ',' && *cursorP != '\0') {
107 const char * typeName;
108
109 translateTypeSpecifierToName(envP, *cursorP, &typeName);
110
111 if (!envP->fault_occurred) {
112 ++cursorP;
113
114 makeRoomInArgList(envP, signatureP, signatureP->argCount + 1);
115
116 signatureP->argList[signatureP->argCount++] = typeName;
117 }
118 }
119 if (!envP->fault_occurred) {
120 if (*cursorP) {
121 XMLRPC_ASSERT(*cursorP == ',')do if (!(*cursorP == ',')) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/method.c"
, 121); while (0)
;
122 ++cursorP; /* Move past the signature and comma */
123 }
124 }
125 if (envP->fault_occurred)
126 free((void*)signatureP->argList);
127
128 *nextPP = cursorP;
129}
130
131
132
133static void
134parseOneSignature(xmlrpc_env * const envP,
135 const char * const startP,
136 struct xmlrpc_signature ** const signaturePP,
137 const char ** const nextPP) {
138/*----------------------------------------------------------------------------
139 Parse one signature from the signature string that starts at 'startP'.
140
141 Return that signature as a signature object *signaturePP.
142
143 Return as *nextP the location in the signature string of the next
144 signature (i.e. right after the next comma). If there is no next
145 signature (the string ends before any comma), make it point to the
146 terminating NUL.
147-----------------------------------------------------------------------------*/
148 struct xmlrpc_signature * signatureP;
149
150 MALLOCVAR(signatureP)signatureP = malloc(sizeof(*signatureP));
151 if (signatureP == NULL((void*)0))
152 xmlrpc_faultf(envP, "Couldn't get memory for signature");
153 else {
154 const char * cursorP;
155
156 signatureP->argListSpace = 0; /* Start with no argument space */
157 signatureP->argList = NULL((void*)0); /* Nothing allocated yet */
158 signatureP->argCount = 0; /* Start with no arguments */
159
160 cursorP = startP; /* start at the beginning */
161
162 if (*cursorP == ',' || *cursorP == '\0')
163 xmlrpc_faultf(envP, "empty signature (a signature "
164 "must have at least return value type)");
165 else {
166 translateTypeSpecifierToName(envP, *cursorP, &signatureP->retType);
167
168 ++cursorP;
169
170 if (*cursorP != ':')
171 xmlrpc_faultf(envP, "No colon (':') after "
172 "the result type specifier");
173 else {
174 ++cursorP;
175
176 parseArgumentTypeSpecifiers(envP, cursorP, signatureP, nextPP);
177 }
178 }
179 if (envP->fault_occurred)
180 free(signatureP);
181 }
182 *signaturePP = signatureP;
183}
184
185
186
187static void
188destroySignatures(struct xmlrpc_signature * const firstSignatureP) {
189
190 struct xmlrpc_signature * p;
191 struct xmlrpc_signature * nextP;
192
193 for (p = firstSignatureP; p; p = nextP) {
194 nextP = p->nextP;
195 signatureDestroy(p);
196 }
197}
198
199
200
201static void
202listSignatures(xmlrpc_env * const envP,
203 const char * const sigListString,
204 struct xmlrpc_signature ** const firstSignaturePP) {
205
206 struct xmlrpc_signature ** p;
207 const char * cursorP;
208
209 *firstSignaturePP = NULL((void*)0); /* Start with empty list */
210
211 p = firstSignaturePP;
212 cursorP = &sigListString[0];
213
214 while (!envP->fault_occurred && *cursorP != '\0') {
215 struct xmlrpc_signature * signatureP;
216
217 parseOneSignature(envP, cursorP, &signatureP, &cursorP);
218
219 /* cursorP now points at next signature in the list or the
220 terminating NUL.
221 */
222
223 if (!envP->fault_occurred) {
224 signatureP->nextP = NULL((void*)0);
225 *p = signatureP;
226 p = &signatureP->nextP;
227 }
228 }
229 if (envP->fault_occurred)
230 destroySignatures(*firstSignaturePP);
231}
232
233
234
235static void
236signatureListCreate(xmlrpc_env * const envP,
237 const char * const sigListString,
238 xmlrpc_signatureList ** const signatureListPP) {
239
240 xmlrpc_signatureList * signatureListP;
241
242 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/method.c", 242); while (0)
;
243
244 MALLOCVAR(signatureListP)signatureListP = malloc(sizeof(*signatureListP));
245
246 if (signatureListP == NULL((void*)0))
247 xmlrpc_faultf(envP, "Could not allocate memory for signature list");
248 else {
249 signatureListP->firstSignatureP = NULL((void*)0);
250
251 if (sigListString == NULL((void*)0) || xmlrpc_streq(sigListString, "?")) {
252 /* No signatures -- leave the list empty */
253 } else {
254 listSignatures(envP, sigListString,
255 &signatureListP->firstSignatureP);
256
257 if (!envP->fault_occurred) {
258 if (!signatureListP->firstSignatureP)
259 xmlrpc_faultf(envP, "Signature string is empty.");
260
261 if (envP->fault_occurred)
262 destroySignatures(signatureListP->firstSignatureP);
263 }
264 }
265 if (envP->fault_occurred)
266 free(signatureListP);
267
268 *signatureListPP = signatureListP;
269 }
270}
271
272
273
274static void
275signatureListDestroy(xmlrpc_signatureList * const signatureListP) {
276
277 destroySignatures(signatureListP->firstSignatureP);
278
279 free(signatureListP);
280}
281
282
283
284static void
285makeSignatureList(xmlrpc_env * const envP,
286 const char * const signatureString,
287 xmlrpc_signatureList ** const signatureListPP) {
288
289 xmlrpc_env env;
290
291 xmlrpc_env_init(&env);
292
293 signatureListCreate(&env, signatureString, signatureListPP);
294
295 if (env.fault_occurred)
296 xmlrpc_faultf(envP, "Can't interpret signature string '%s'. %s",
297 signatureString, env.fault_string);
298
299 xmlrpc_env_clean(&env);
300}
301
302
303
304void
305xmlrpc_methodCreate(xmlrpc_env * const envP,
306 xmlrpc_method1 methodFnType1,
307 xmlrpc_method2 methodFnType2,
308 void * const userData,
309 const char * const signatureString,
310 const char * const helpText,
311 size_t const stackSize,
312 xmlrpc_methodInfo ** const methodPP) {
313
314 xmlrpc_methodInfo * methodP;
315
316 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/method.c", 316); while (0)
;
1
Within the expansion of the macro 'XMLRPC_ASSERT_ENV_OK':
a
Assuming 'envP' is equal to null
317
318 MALLOCVAR(methodP)methodP = malloc(sizeof(*methodP));
319
320 if (methodP == NULL((void*)0))
2
Assuming 'methodP' is not equal to null
3
Taking false branch
321 xmlrpc_faultf(envP, "Unable to allocate storage for a method "
322 "descriptor");
323 else {
324 methodP->methodFnType1 = methodFnType1;
325 methodP->methodFnType2 = methodFnType2;
326 methodP->userData = userData;
327 methodP->helpText = xmlrpc_strdupsol(helpText);
328 methodP->stackSize = stackSize;
329
330 makeSignatureList(envP, signatureString, &methodP->signatureListP);
331
332 if (envP->fault_occurred) {
4
Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP')
333 xmlrpc_strfree(methodP->helpText);
334 free(methodP);
335 }
336
337 *methodPP = methodP;
338 }
339}
340
341
342
343void
344xmlrpc_methodDestroy(xmlrpc_methodInfo * const methodP) {
345
346 signatureListDestroy(methodP->signatureListP);
347
348 xmlrpc_strfree(methodP->helpText);
349
350 free(methodP);
351}
352
353
354
355void
356xmlrpc_methodListCreate(xmlrpc_env * const envP,
357 xmlrpc_methodList ** const methodListPP) {
358
359 xmlrpc_methodList * methodListP;
360
361 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/method.c", 361); while (0)
;
362
363 MALLOCVAR(methodListP)methodListP = malloc(sizeof(*methodListP));
364
365 if (methodListP == NULL((void*)0))
366 xmlrpc_faultf(envP, "Couldn't allocate method list descriptor");
367 else {
368 methodListP->firstMethodP = NULL((void*)0);
369 methodListP->lastMethodP = NULL((void*)0);
370
371 *methodListPP = methodListP;
372 }
373}
374
375
376
377void
378xmlrpc_methodListDestroy(xmlrpc_methodList * methodListP) {
379
380 xmlrpc_methodNode * p;
381 xmlrpc_methodNode * nextP;
382
383 for (p = methodListP->firstMethodP; p; p = nextP) {
384 nextP = p->nextP;
385
386 xmlrpc_methodDestroy(p->methodP);
387 xmlrpc_strfree(p->methodName);
388 free(p);
389 }
390
391 free(methodListP);
392}
393
394
395
396void
397xmlrpc_methodListLookupByName(xmlrpc_methodList * const methodListP,
398 const char * const methodName,
399 xmlrpc_methodInfo ** const methodPP) {
400
401
402 /* We do a simple linear lookup along a linked list.
403 If speed is important, we can make this a binary tree instead.
404 */
405
406 xmlrpc_methodNode * p;
407 xmlrpc_methodInfo * methodP;
408
409 for (p = methodListP->firstMethodP, methodP = NULL((void*)0);
410 p && !methodP;
411 p = p->nextP) {
412
413 if (xmlrpc_streq(p->methodName, methodName))
414 methodP = p->methodP;
415 }
416 *methodPP = methodP;
417}
418
419
420
421void
422xmlrpc_methodListAdd(xmlrpc_env * const envP,
423 xmlrpc_methodList * const methodListP,
424 const char * const methodName,
425 xmlrpc_methodInfo * const methodP) {
426
427 xmlrpc_methodInfo * existingMethodP;
428
429 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/method.c", 429); while (0)
;
430
431 xmlrpc_methodListLookupByName(methodListP, methodName, &existingMethodP);
432
433 if (existingMethodP)
434 xmlrpc_faultf(envP, "Method named '%s' already registered",
435 methodName);
436 else {
437 xmlrpc_methodNode * methodNodeP;
438
439 MALLOCVAR(methodNodeP)methodNodeP = malloc(sizeof(*methodNodeP));
440
441 if (methodNodeP == NULL((void*)0))
442 xmlrpc_faultf(envP, "Couldn't allocate method node");
443 else {
444 methodNodeP->methodName = strdup(methodName)(__extension__ (__builtin_constant_p (methodName) && (
(size_t)(const void *)((methodName) + 1) - (size_t)(const void
*)(methodName) == 1) ? (((const char *) (methodName))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (methodName) + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, methodName, __len); __retval; })) : __strdup (methodName
)))
;
445 methodNodeP->methodP = methodP;
446 methodNodeP->nextP = NULL((void*)0);
447
448 if (!methodListP->firstMethodP)
449 methodListP->firstMethodP = methodNodeP;
450
451 if (methodListP->lastMethodP)
452 methodListP->lastMethodP->nextP = methodNodeP;
453
454 methodListP->lastMethodP = methodNodeP;
455 }
456 }
457}
458