Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_parse.c
Location:line 211, column 26
Description:Dereference of null pointer (loaded from variable 'methodNameP')

Annotated Source Code

1/* Copyright information is at end of file. */
2
3#define _XOPEN_SOURCE700 600 /* Make sure strdup() is in <string.h> */
4
5#include "xmlrpc_config.h"
6
7#include <stddef.h>
8#include <stdlib.h>
9#include <string.h>
10#include <errno(*__errno_location ()).h>
11#include <ctype.h>
12#include <limits.h>
13
14#include "bool.h"
15
16#include "xmlrpc-c/base.h"
17#include "xmlrpc-c/base_int.h"
18#include "xmlrpc-c/string_int.h"
19#include "xmlrpc-c/util.h"
20#include "xmlrpc-c/xmlparser.h"
21#include "parse_value.h"
22
23
24/* Notes about XML-RPC XML documents:
25
26 Contain CDATA: methodName, i4, int, boolean, string, double,
27 dateTime.iso8601, base64, name
28
29 We attempt to validate the structure of the XML document carefully.
30 We also try *very* hard to handle malicious data gracefully, and without
31 leaking memory.
32
33 The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and
34 invoke XMLRPC_FAIL if something looks wrong.
35*/
36
37static void
38setParseFault(xmlrpc_env * const envP,
39 const char * const format,
40 ...) {
41
42 va_list args;
43 va_start(args, format)__builtin_va_start(args, format);
44 xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR(-503), format, args);
45 va_end(args)__builtin_va_end(args);
46}
47
48
49
50#define CHECK_NAME(env,elem,name)do if (!xmlrpc_streq((name), xml_element_name(elem))) do { xmlrpc_env_set_fault_formatted
((env),((-503)),("Expected element of type <%s>, found <%s>"
),((name)),(xml_element_name(elem))); goto cleanup; } while (
0); while (0)
\
51 do \
52 if (!xmlrpc_streq((name), xml_element_name(elem))) \
53 XMLRPC_FAIL2(env, XMLRPC_PARSE_ERROR, \do { xmlrpc_env_set_fault_formatted((env),((-503)),("Expected element of type <%s>, found <%s>"
),((name)),(xml_element_name(elem))); goto cleanup; } while (
0)
54 "Expected element of type <%s>, found <%s>", \do { xmlrpc_env_set_fault_formatted((env),((-503)),("Expected element of type <%s>, found <%s>"
),((name)),(xml_element_name(elem))); goto cleanup; } while (
0)
55 (name), xml_element_name(elem))do { xmlrpc_env_set_fault_formatted((env),((-503)),("Expected element of type <%s>, found <%s>"
),((name)),(xml_element_name(elem))); goto cleanup; } while (
0)
; \
56 while (0)
57
58#define CHECK_CHILD_COUNT(env,elem,count)do if (xml_element_children_size(elem) != (count)) do { xmlrpc_env_set_fault_formatted
((env),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(elem)),((count)),((unsigned)xml_element_children_size
(elem))); goto cleanup; } while (0); while (0)
\
59 do \
60 if (xml_element_children_size(elem) != (count)) \
61 XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR, \do { xmlrpc_env_set_fault_formatted((env),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(elem)),((count)),((unsigned)xml_element_children_size
(elem))); goto cleanup; } while (0)
62 "Expected <%s> to have %u children, found %u", \do { xmlrpc_env_set_fault_formatted((env),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(elem)),((count)),((unsigned)xml_element_children_size
(elem))); goto cleanup; } while (0)
63 xml_element_name(elem), (count), \do { xmlrpc_env_set_fault_formatted((env),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(elem)),((count)),((unsigned)xml_element_children_size
(elem))); goto cleanup; } while (0)
64 (unsigned)xml_element_children_size(elem))do { xmlrpc_env_set_fault_formatted((env),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(elem)),((count)),((unsigned)xml_element_children_size
(elem))); goto cleanup; } while (0)
; \
65 while (0)
66
67static xml_element *
68getChildByName (xmlrpc_env * const envP,
69 xml_element * const parentP,
70 const char * const name) {
71
72 size_t const childCount = xml_element_children_size(parentP);
73 xml_element ** const childrenP = xml_element_children(parentP);
74
75 unsigned int i;
76
77 for (i = 0; i < childCount; ++i) {
78 if (xmlrpc_streq(xml_element_name(childrenP[i]), name))
79 return childrenP[i];
80 }
81
82 setParseFault(envP, "Expected <%s> to have child <%s>",
83 xml_element_name(parentP), name);
84 return NULL((void*)0);
85}
86
87
88
89/*=========================================================================
90** convert_params
91**=========================================================================
92** Convert an XML element representing a list of params into an
93** xmlrpc_value (of type array).
94*/
95
96static xmlrpc_value *
97convert_params(xmlrpc_env * const envP,
98 const xml_element * const elemP) {
99/*----------------------------------------------------------------------------
100 Convert an XML element representing a list of parameters (i.e. a <params>
101 element) to an xmlrpc_value of type array. Note that an xmlrpc_value is
102 normally represented in XML by a <value> element, not a <params> element.
103 We use type xmlrpc_value to represent the parameter list just for
104 convenience.
105-----------------------------------------------------------------------------*/
106 xmlrpc_value *array, *item;
107 int size, i;
108 xml_element **params, *param, *value;
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/xmlrpc_parse.c", 110); while (
0)
;
111 XMLRPC_ASSERT(elemP != NULL)do if (!(elemP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 111); while (0)
;
112
113 /* Set up our error-handling preconditions. */
114 array = item = NULL((void*)0);
115
116 /* Allocate an array to hold our parameters. */
117 array = xmlrpc_build_value(envP, "()");
118 XMLRPC_FAIL_IF_FAULT(envP)do { if ((envP)->fault_occurred) goto cleanup; } while (0);
119
120 /* We're responsible for checking our own element name. */
121 CHECK_NAME(envP, elemP, "params")do if (!xmlrpc_streq(("params"), xml_element_name(elemP))) do
{ xmlrpc_env_set_fault_formatted((envP),((-503)),("Expected element of type <%s>, found <%s>"
),(("params")),(xml_element_name(elemP))); goto cleanup; } while
(0); while (0)
;
122
123 /* Iterate over our children. */
124 size = xml_element_children_size(elemP);
125 params = xml_element_children(elemP);
126 for (i = 0; i < size; ++i) {
127 unsigned int const maxNest = (unsigned int)
128 xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID(0));
129
130 param = params[i];
131 CHECK_NAME(envP, param, "param")do if (!xmlrpc_streq(("param"), xml_element_name(param))) do {
xmlrpc_env_set_fault_formatted((envP),((-503)),("Expected element of type <%s>, found <%s>"
),(("param")),(xml_element_name(param))); goto cleanup; } while
(0); while (0)
;
132 CHECK_CHILD_COUNT(envP, param, 1)do if (xml_element_children_size(param) != (1)) do { xmlrpc_env_set_fault_formatted
((envP),((-503)), ("Expected <%s> to have %u children, found %u"
),(xml_element_name(param)),((1)),((unsigned)xml_element_children_size
(param))); goto cleanup; } while (0); while (0)
;
133
134 value = xml_element_children(param)[0];
135
136 CHECK_NAME(envP, value, "value")do if (!xmlrpc_streq(("value"), xml_element_name(value))) do {
xmlrpc_env_set_fault_formatted((envP),((-503)),("Expected element of type <%s>, found <%s>"
),(("value")),(xml_element_name(value))); goto cleanup; } while
(0); while (0)
;
137
138 xmlrpc_parseValue(envP, maxNest, value, &item);
139 XMLRPC_FAIL_IF_FAULT(envP)do { if ((envP)->fault_occurred) goto cleanup; } while (0);
140
141 xmlrpc_array_append_item(envP, array, item);
142 xmlrpc_DECREF(item);
143 item = NULL((void*)0);
144 XMLRPC_FAIL_IF_FAULT(envP)do { if ((envP)->fault_occurred) goto cleanup; } while (0);
145 }
146
147 cleanup:
148 if (envP->fault_occurred) {
149 if (array)
150 xmlrpc_DECREF(array);
151 if (item)
152 xmlrpc_DECREF(item);
153 return NULL((void*)0);
154 }
155 return array;
156}
157
158
159
160static void
161parseCallXml(xmlrpc_env * const envP,
162 const char * const xmlData,
163 size_t const xmlDataLen,
164 xml_element ** const callElemPP) {
165/*----------------------------------------------------------------------------
166 Parse the XML of an XML-RPC call.
167-----------------------------------------------------------------------------*/
168 xml_element * callElemP;
169 xmlrpc_env env;
170
171 xmlrpc_env_init(&env);
172 xml_parse(&env, xmlData, xmlDataLen, &callElemP);
173 if (env.fault_occurred)
174 xmlrpc_env_set_fault_formatted(
175 envP, env.fault_code, "Call is not valid XML. %s",
176 env.fault_string);
177 else {
178 if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall"))
179 setParseFault(envP,
180 "XML-RPC call should be a <methodCall> element. "
181 "Instead, we have a <%s> element.",
182 xml_element_name(callElemP));
183
184 if (envP->fault_occurred)
185 xml_element_free(callElemP);
186 }
187 *callElemPP = callElemP;
188
189 xmlrpc_env_clean(&env);
190}
191
192
193
194static void
195parseMethodNameElement(xmlrpc_env * const envP,
196 xml_element * const nameElemP,
197 const char ** const methodNameP) {
198
199 XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName"))do if (!(xmlrpc_streq(xml_element_name(nameElemP), "methodName"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 199); while (0)
;
200
201 if (xml_element_children_size(nameElemP) > 0)
9
Taking false branch
202 setParseFault(envP, "A <methodName> element should not have "
203 "children. This one has %u of them.",
204 xml_element_children_size(nameElemP));
205 else {
206 const char * const cdata = xml_element_cdata(nameElemP);
207
208 xmlrpc_validate_utf8(envP, cdata, strlen(cdata));
209
210 if (!envP->fault_occurred) {
10
Taking true branch
211 *methodNameP = strdup(cdata)(__extension__ (__builtin_constant_p (cdata) && ((size_t
)(const void *)((cdata) + 1) - (size_t)(const void *)(cdata) ==
1) ? (((const char *) (cdata))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (cdata) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, cdata, __len
); __retval; })) : __strdup (cdata)))
;
11
Dereference of null pointer (loaded from variable 'methodNameP')
212 if (*methodNameP == NULL((void*)0))
213 xmlrpc_faultf(envP,
214 "Could not allocate memory for method name");
215 }
216 }
217}
218
219
220
221static void
222parseCallChildren(xmlrpc_env * const envP,
223 xml_element * const callElemP,
224 const char ** const methodNameP,
225 xmlrpc_value ** const paramArrayPP ) {
226/*----------------------------------------------------------------------------
227 Parse the children of a <methodCall> XML element *callElemP. They should
228 be <methodName> and <params>.
229-----------------------------------------------------------------------------*/
230 size_t const callChildCount = xml_element_children_size(callElemP);
231
232 xml_element * nameElemP;
233
234 XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall"))do if (!(xmlrpc_streq(xml_element_name(callElemP), "methodCall"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 234); while (0)
;
235
236 nameElemP = getChildByName(envP, callElemP, "methodName");
237
238 if (!envP->fault_occurred) {
6
Taking true branch
239 parseMethodNameElement(envP, nameElemP, methodNameP);
7
Passing null pointer value via 3rd parameter 'methodNameP'
8
Calling 'parseMethodNameElement'
240
241 if (!envP->fault_occurred) {
242 /* Convert our parameters. */
243 if (callChildCount > 1) {
244 xml_element * paramsElemP;
245
246 paramsElemP = getChildByName(envP, callElemP, "params");
247
248 if (!envP->fault_occurred)
249 *paramArrayPP = convert_params(envP, paramsElemP);
250 } else {
251 /* Workaround for Ruby XML-RPC and old versions of
252 xmlrpc-epi. Future improvement: Instead of looking
253 at child count, we should just check for existence
254 of <params>.
255 */
256 *paramArrayPP = xmlrpc_array_new(envP);
257 }
258 if (!envP->fault_occurred) {
259 if (callChildCount > 2)
260 setParseFault(envP, "<methodCall> has extraneous "
261 "children, other than <methodName> and "
262 "<params>. Total child count = %u",
263 callChildCount);
264
265 if (envP->fault_occurred)
266 xmlrpc_DECREF(*paramArrayPP);
267 }
268 if (envP->fault_occurred)
269 xmlrpc_strfree(*methodNameP);
270 }
271 }
272}
273
274
275
276void
277xmlrpc_parse_call(xmlrpc_env * const envP,
278 const char * const xmlData,
279 size_t const xmlDataLen,
280 const char ** const methodNameP,
281 xmlrpc_value ** const paramArrayPP) {
282/*----------------------------------------------------------------------------
283 Given some XML text, attempt to parse it as an XML-RPC call.
284 Return as *methodNameP the name of the method identified in the call
285 and as *paramArrayPP the parameter list as an XML-RPC array.
286 Caller must free() and xmlrpc_DECREF() these, respectively).
287-----------------------------------------------------------------------------*/
288 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/xmlrpc_parse.c", 288); while (
0)
;
289 XMLRPC_ASSERT(xmlData != NULL)do if (!(xmlData != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 289); while (0)
;
290 XMLRPC_ASSERT(methodNameP != NULL && paramArrayPP != NULL)do if (!(methodNameP != ((void*)0) && paramArrayPP !=
((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 290); while (0)
;
1
Within the expansion of the macro 'XMLRPC_ASSERT':
a
Assuming 'methodNameP' is equal to null
291
292 /* SECURITY: Last-ditch attempt to make sure our content length is
293 legal. XXX - This check occurs too late to prevent an attacker
294 from creating an enormous memory block, so you should try to
295 enforce it *before* reading any data off the network.
296 */
297 if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID(1)))
2
Taking false branch
298 xmlrpc_env_set_fault_formatted(
299 envP, XMLRPC_LIMIT_EXCEEDED_ERROR(-509),
300 "XML-RPC request too large. Max allowed is %u bytes",
301 (unsigned)xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID(1)));
302 else {
303 xml_element * callElemP;
304 parseCallXml(envP, xmlData, xmlDataLen, &callElemP);
305 if (!envP->fault_occurred) {
3
Taking true branch
306 parseCallChildren(envP, callElemP, methodNameP, paramArrayPP);
4
Passing null pointer value via 3rd parameter 'methodNameP'
5
Calling 'parseCallChildren'
307
308 xml_element_free(callElemP);
309 }
310 }
311 if (envP->fault_occurred) {
312 /* Should not be necessary, but for backward compatibility: */
313 *methodNameP = NULL((void*)0);
314 *paramArrayPP = NULL((void*)0);
315 }
316}
317
318
319
320static void
321interpretFaultCode(xmlrpc_env * const envP,
322 xmlrpc_value * const faultCodeVP,
323 int * const faultCodeP) {
324
325 xmlrpc_env fcEnv;
326 xmlrpc_env_init(&fcEnv);
327
328 xmlrpc_read_int(&fcEnv, faultCodeVP, faultCodeP);
329 if (fcEnv.fault_occurred)
330 xmlrpc_faultf(envP, "Invalid value for 'faultCode' member. %s",
331 fcEnv.fault_string);
332
333 xmlrpc_env_clean(&fcEnv);
334}
335
336
337
338static void
339interpretFaultString(xmlrpc_env * const envP,
340 xmlrpc_value * const faultStringVP,
341 const char ** const faultStringP) {
342
343 xmlrpc_env fsEnv;
344 xmlrpc_env_init(&fsEnv);
345
346 xmlrpc_read_string(&fsEnv, faultStringVP, faultStringP);
347
348 if (fsEnv.fault_occurred)
349 xmlrpc_faultf(envP, "Invalid value for 'faultString' member. %s",
350 fsEnv.fault_string);
351
352 xmlrpc_env_clean(&fsEnv);
353}
354
355
356
357static void
358interpretFaultValue(xmlrpc_env * const envP,
359 xmlrpc_value * const faultVP,
360 int * const faultCodeP,
361 const char ** const faultStringP) {
362
363 if (faultVP->_type != XMLRPC_TYPE_STRUCT)
364 setParseFault(envP,
365 "<value> element of <fault> response is not "
366 "of structure type");
367 else {
368 xmlrpc_value * faultCodeVP;
369 xmlrpc_env fvEnv;
370
371 xmlrpc_env_init(&fvEnv);
372
373 xmlrpc_struct_read_value(&fvEnv, faultVP, "faultCode", &faultCodeVP);
374 if (!fvEnv.fault_occurred) {
375 interpretFaultCode(&fvEnv, faultCodeVP, faultCodeP);
376
377 if (!fvEnv.fault_occurred) {
378 xmlrpc_value * faultStringVP;
379
380 xmlrpc_struct_read_value(&fvEnv, faultVP, "faultString",
381 &faultStringVP);
382 if (!fvEnv.fault_occurred) {
383 interpretFaultString(&fvEnv, faultStringVP, faultStringP);
384
385 xmlrpc_DECREF(faultStringVP);
386 }
387 }
388 xmlrpc_DECREF(faultCodeVP);
389 }
390 if (fvEnv.fault_occurred)
391 setParseFault(envP, "Invalid struct for <fault> value. %s",
392 fvEnv.fault_string);
393
394 xmlrpc_env_clean(&fvEnv);
395 }
396}
397
398
399
400static void
401parseFaultElement(xmlrpc_env * const envP,
402 const xml_element * const faultElement,
403 int * const faultCodeP,
404 const char ** const faultStringP) {
405
406 unsigned int const maxRecursion = (unsigned int)
407 xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID(0));
408
409 XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault"))do if (!(xmlrpc_streq(xml_element_name(faultElement), "fault"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 409); while (0)
;
410
411 if (xml_element_children_size(faultElement) != 1)
412 setParseFault(envP, "<fault> element should have 1 child, "
413 "but it has %u.",
414 xml_element_children_size(faultElement));
415 else {
416 xml_element * const faultValueP =
417 xml_element_children(faultElement)[0];
418 const char * const elemName = xml_element_name(faultValueP);
419
420 if (!xmlrpc_streq(elemName, "value"))
421 setParseFault(envP,
422 "<fault> contains a <%s> element. "
423 "Only <value> makes sense.",
424 elemName);
425 else {
426 xmlrpc_value * faultVP;
427
428 xmlrpc_parseValue(envP, maxRecursion, faultValueP, &faultVP);
429
430 if (!envP->fault_occurred) {
431 interpretFaultValue(envP, faultVP, faultCodeP, faultStringP);
432
433 xmlrpc_DECREF(faultVP);
434 }
435 }
436 }
437}
438
439
440
441static void
442parseParamsElement(xmlrpc_env * const envP,
443 const xml_element * const paramsElementP,
444 xmlrpc_value ** const resultPP) {
445
446 xmlrpc_value * paramsVP;
447 xmlrpc_env env;
448
449 xmlrpc_env_init(&env);
450
451 XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(paramsElementP), "params"))do if (!(xmlrpc_streq(xml_element_name(paramsElementP), "params"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 451); while (0)
;
452
453 paramsVP = convert_params(envP, paramsElementP);
454
455 if (!envP->fault_occurred) {
456 int arraySize;
457 xmlrpc_env sizeEnv;
458
459 XMLRPC_ASSERT_ARRAY_OK(paramsVP)xmlrpc_abort_if_array_bad(paramsVP);
460
461 xmlrpc_env_init(&sizeEnv);
462
463 arraySize = xmlrpc_array_size(&sizeEnv, paramsVP);
464 /* Since it's a valid array, as asserted above, can't fail */
465 XMLRPC_ASSERT(!sizeEnv.fault_occurred)do if (!(!sizeEnv.fault_occurred)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 465); while (0)
;
466
467 if (arraySize != 1)
468 setParseFault(envP, "Contains %d items. It should have 1.",
469 arraySize);
470 else {
471 xmlrpc_array_read_item(envP, paramsVP, 0, resultPP);
472 }
473 xmlrpc_DECREF(paramsVP);
474 xmlrpc_env_clean(&sizeEnv);
475 }
476 if (env.fault_occurred)
477 xmlrpc_env_set_fault_formatted(
478 envP, env.fault_code,
479 "Invalid <params> element. %s", env.fault_string);
480
481 xmlrpc_env_clean(&env);
482}
483
484
485
486static void
487parseMethodResponseElt(xmlrpc_env * const envP,
488 const xml_element * const methodResponseEltP,
489 xmlrpc_value ** const resultPP,
490 int * const faultCodeP,
491 const char ** const faultStringP) {
492
493 XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP),do if (!(xmlrpc_streq(xml_element_name(methodResponseEltP), "methodResponse"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 494); while (0)
494 "methodResponse"))do if (!(xmlrpc_streq(xml_element_name(methodResponseEltP), "methodResponse"
))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 494); while (0)
;
495
496 if (xml_element_children_size(methodResponseEltP) == 1) {
497 xml_element * const child =
498 xml_element_children(methodResponseEltP)[0];
499
500 if (xmlrpc_streq(xml_element_name(child), "params")) {
501 /* It's a successful response */
502 parseParamsElement(envP, child, resultPP);
503 *faultStringP = NULL((void*)0);
504 } else if (xmlrpc_streq(xml_element_name(child), "fault")) {
505 /* It's a failure response */
506 parseFaultElement(envP, child, faultCodeP, faultStringP);
507 } else
508 setParseFault(envP,
509 "<methodResponse> must contain <params> or <fault>, "
510 "but contains <%s>.", xml_element_name(child));
511 } else
512 setParseFault(envP,
513 "<methodResponse> has %u children, should have 1.",
514 xml_element_children_size(methodResponseEltP));
515}
516
517
518
519void
520xmlrpc_parse_response2(xmlrpc_env * const envP,
521 const char * const xmlData,
522 size_t const xmlDataLen,
523 xmlrpc_value ** const resultPP,
524 int * const faultCodeP,
525 const char ** const faultStringP) {
526/*----------------------------------------------------------------------------
527 Given some XML text, attempt to parse it as an XML-RPC response.
528
529 If the response is a regular, valid response, return a new reference
530 to the appropriate value as *resultP and return NULL as
531 *faultStringP and nothing as *faultCodeP.
532
533 If the response is valid, but indicates a failure of the RPC, return the
534 fault string in newly malloc'ed space as *faultStringP and the fault
535 code as *faultCodeP and nothing as *resultP.
536
537 If the XML text is not a valid response or something prevents us from
538 parsing it, return a description of the error as *envP and nothing else.
539-----------------------------------------------------------------------------*/
540 xml_element * responseEltP;
541
542 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/xmlrpc_parse.c", 542); while (
0)
;
543 XMLRPC_ASSERT(xmlData != NULL)do if (!(xmlData != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 543); while (0)
;
544
545 /* SECURITY: Last-ditch attempt to make sure our content length is legal.
546 ** XXX - This check occurs too late to prevent an attacker from creating
547 ** an enormous memory block, so you should try to enforce it
548 ** *before* reading any data off the network. */
549 if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID(1)))
550 xmlrpc_env_set_fault_formatted(
551 envP, XMLRPC_LIMIT_EXCEEDED_ERROR(-509),
552 "XML-RPC response too large. Our limit is %u characters. "
553 "We got %u characters",
554 (unsigned)xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID(1)),
555 (unsigned)xmlDataLen);
556 else {
557 xmlrpc_env env;
558 xmlrpc_env_init(&env);
559
560 xml_parse(&env, xmlData, xmlDataLen, &responseEltP);
561
562 if (env.fault_occurred)
563 setParseFault(envP, "Not valid XML. %s", env.fault_string);
564 else {
565 /* Pick apart and verify our structure. */
566 if (xmlrpc_streq(xml_element_name(responseEltP),
567 "methodResponse")) {
568 parseMethodResponseElt(envP, responseEltP,
569 resultPP, faultCodeP, faultStringP);
570 } else
571 setParseFault(envP, "XML-RPC response must consist of a "
572 "<methodResponse> element. "
573 "This has a <%s> instead.",
574 xml_element_name(responseEltP));
575
576 xml_element_free(responseEltP);
577 }
578 xmlrpc_env_clean(&env);
579 }
580}
581
582
583
584xmlrpc_value *
585xmlrpc_parse_response(xmlrpc_env * const envP,
586 const char * const xmlData,
587 size_t const xmlDataLen) {
588/*----------------------------------------------------------------------------
589 This exists for backward compatibility. It is like
590 xmlrpc_parse_response2(), except that it merges the concepts of a
591 failed RPC and an error in executing the RPC.
592-----------------------------------------------------------------------------*/
593 xmlrpc_value * retval;
594 xmlrpc_value * result;
595 const char * faultString;
596 int faultCode;
597
598 xmlrpc_parse_response2(envP, xmlData, xmlDataLen,
599 &result, &faultCode, &faultString);
600
601 if (envP->fault_occurred)
602 retval = NULL((void*)0);
603 else {
604 if (faultString) {
605 xmlrpc_env_set_fault(envP, faultCode, faultString);
606 xmlrpc_strfree(faultString);
607 retval = NULL((void*)0);
608 } else
609 retval = result; /* transfer reference */
610 }
611 return retval;
612}
613
614
615
616void
617xmlrpc_parse_value_xml(xmlrpc_env * const envP,
618 const char * const xmlData,
619 size_t const xmlDataLen,
620 xmlrpc_value ** const valuePP) {
621/*----------------------------------------------------------------------------
622 Compute the xmlrpc_value represented by the XML document 'xmlData' (of
623 length 'xmlDataLen' characters), which must consist of a single <value>
624 element. Return that xmlrpc_value.
625
626 We call convert_array() and convert_struct(), which may ultimately
627 call us recursively. Don't recurse any more than 'maxRecursion'
628 times.
629
630 This isn't generally useful in XML-RPC programs, because such programs
631 parse a whole XML-RPC call or response document, and never see the XML text
632 of just a <value> element. But a program may do some weird form of XML-RPC
633 processing or just borrow Xmlrpc-c's value serialization facilities for
634 something unrelated to XML-RPC. In any case, it makes sense to have an
635 inverse of xmlrpc_serialize_value2(), which generates XML text from an
636 xmlrpc_value.
637-----------------------------------------------------------------------------*/
638 xmlrpc_env env;
639
640 xml_element * valueEltP;
641
642 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/xmlrpc_parse.c", 642); while (
0)
;
643 XMLRPC_ASSERT(xmlData != NULL)do if (!(xmlData != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_parse.c"
, 643); while (0)
;
644
645 xmlrpc_env_init(&env);
646
647 xml_parse(&env, xmlData, xmlDataLen, &valueEltP);
648
649 if (env.fault_occurred) {
650 setParseFault(envP, "Not valid XML. %s", env.fault_string);
651 } else {
652 if (xmlrpc_streq(xml_element_name(valueEltP), "value")) {
653 unsigned int const maxRecursion = (unsigned int)
654 xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID(0));
655 xmlrpc_parseValue(envP, maxRecursion, valueEltP, valuePP);
656 } else
657 setParseFault(envP, "XML-RPC value XML document must consist of "
658 "a <value> element. This has a <%s> instead.",
659 xml_element_name(valueEltP));
660 xml_element_free(valueEltP);
661 }
662 xmlrpc_env_clean(&env);
663}
664
665
666
667/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
668**
669** Redistribution and use in source and binary forms, with or without
670** modification, are permitted provided that the following conditions
671** are met:
672** 1. Redistributions of source code must retain the above copyright
673** notice, this list of conditions and the following disclaimer.
674** 2. Redistributions in binary form must reproduce the above copyright
675** notice, this list of conditions and the following disclaimer in the
676** documentation and/or other materials provided with the distribution.
677** 3. The name of the author may not be used to endorse or promote products
678** derived from this software without specific prior written permission.
679**
680** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
681** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
682** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
683** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
684** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
685** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
686** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
687** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
688** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
689** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
690** SUCH DAMAGE. */