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') |
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 | ||||||
31 | static void | |||||
32 | signatureDestroy(struct xmlrpc_signature * const signatureP) { | |||||
33 | ||||||
34 | if (signatureP->argList) | |||||
35 | free((void*)signatureP->argList); | |||||
36 | ||||||
37 | free(signatureP); | |||||
38 | } | |||||
39 | ||||||
40 | ||||||
41 | ||||||
42 | static void | |||||
43 | translateTypeSpecifierToName(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 | ||||||
76 | static void | |||||
77 | makeRoomInArgList(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 | ||||||
97 | static void | |||||
98 | parseArgumentTypeSpecifiers(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 | ||||||
133 | static void | |||||
134 | parseOneSignature(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 | ||||||
187 | static void | |||||
188 | destroySignatures(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 | ||||||
201 | static void | |||||
202 | listSignatures(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 | ||||||
235 | static void | |||||
236 | signatureListCreate(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 | ||||||
274 | static void | |||||
275 | signatureListDestroy(xmlrpc_signatureList * const signatureListP) { | |||||
276 | ||||||
277 | destroySignatures(signatureListP->firstSignatureP); | |||||
278 | ||||||
279 | free(signatureListP); | |||||
280 | } | |||||
281 | ||||||
282 | ||||||
283 | ||||||
284 | static void | |||||
285 | makeSignatureList(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 | ||||||
304 | void | |||||
305 | xmlrpc_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); | |||||
| ||||||
317 | ||||||
318 | MALLOCVAR(methodP)methodP = malloc(sizeof(*methodP)); | |||||
319 | ||||||
320 | if (methodP == NULL((void*)0)) | |||||
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) { | |||||
| ||||||
333 | xmlrpc_strfree(methodP->helpText); | |||||
334 | free(methodP); | |||||
335 | } | |||||
336 | ||||||
337 | *methodPP = methodP; | |||||
338 | } | |||||
339 | } | |||||
340 | ||||||
341 | ||||||
342 | ||||||
343 | void | |||||
344 | xmlrpc_methodDestroy(xmlrpc_methodInfo * const methodP) { | |||||
345 | ||||||
346 | signatureListDestroy(methodP->signatureListP); | |||||
347 | ||||||
348 | xmlrpc_strfree(methodP->helpText); | |||||
349 | ||||||
350 | free(methodP); | |||||
351 | } | |||||
352 | ||||||
353 | ||||||
354 | ||||||
355 | void | |||||
356 | xmlrpc_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 | ||||||
377 | void | |||||
378 | xmlrpc_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 | ||||||
396 | void | |||||
397 | xmlrpc_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 | ||||||
421 | void | |||||
422 | xmlrpc_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 |