Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/parse_value.c
Location:line 281, column 9
Description:Array access (from variable 'str') results in a null pointer dereference

Annotated Source Code

1#include "xmlrpc_config.h"
2
3#include <stddef.h>
4#include <stdlib.h>
5#include <string.h>
6#include <errno(*__errno_location ()).h>
7#include <ctype.h>
8#include <limits.h>
9#include <float.h>
10
11#include "bool.h"
12
13#include "xmlrpc-c/base.h"
14#include "xmlrpc-c/base_int.h"
15#include "xmlrpc-c/string_int.h"
16#include "xmlrpc-c/string_number.h"
17#include "xmlrpc-c/util.h"
18#include "xmlrpc-c/xmlparser.h"
19#include "parse_datetime.h"
20
21#include "parse_value.h"
22
23
24
25static void
26setParseFault(xmlrpc_env * const envP,
27 const char * const format,
28 ...) {
29
30 va_list args;
31 va_start(args, format)__builtin_va_start(args, format);
32 xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR(-503), format, args);
33 va_end(args)__builtin_va_end(args);
34}
35
36
37
38static void
39parseArrayDataChild(xmlrpc_env * const envP,
40 xml_element * const childP,
41 unsigned int const maxRecursion,
42 xmlrpc_value * const arrayP) {
43
44 const char * const elemName = xml_element_name(childP);
45
46 if (!xmlrpc_streq(elemName, "value"))
47 setParseFault(envP, "<data> element has <%s> child. "
48 "Only <value> makes sense.", elemName);
49 else {
50 xmlrpc_value * itemP;
51
52 xmlrpc_parseValue(envP, maxRecursion-1, childP, &itemP);
53
54 if (!envP->fault_occurred) {
55 xmlrpc_array_append_item(envP, arrayP, itemP);
56
57 xmlrpc_DECREF(itemP);
58 }
59 }
60}
61
62
63
64static void
65parseArray(xmlrpc_env * const envP,
66 unsigned int const maxRecursion,
67 xml_element * const arrayElemP,
68 xmlrpc_value ** const arrayPP) {
69
70 xmlrpc_value * arrayP;
71
72 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/parse_value.c", 72); while (0
)
;
73 XMLRPC_ASSERT(arrayElemP != NULL)do if (!(arrayElemP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 73); while (0)
;
74
75 arrayP = xmlrpc_array_new(envP);
76 if (!envP->fault_occurred) {
77 size_t const childCount = xml_element_children_size(arrayElemP);
78
79 if (childCount != 1)
80 setParseFault(envP,
81 "<array> element has %u children. Only one <data> "
82 "makes sense.", (unsigned int)childCount);
83 else {
84 xml_element * const dataElemP =
85 xml_element_children(arrayElemP)[0];
86 const char * const elemName = xml_element_name(dataElemP);
87
88 if (!xmlrpc_streq(elemName, "data"))
89 setParseFault(envP,
90 "<array> element has <%s> child. Only <data> "
91 "makes sense.", elemName);
92 else {
93 xml_element ** const values = xml_element_children(dataElemP);
94 unsigned int const size = xml_element_children_size(dataElemP);
95
96 unsigned int i;
97
98 for (i = 0; i < size && !envP->fault_occurred; ++i)
99 parseArrayDataChild(envP, values[i], maxRecursion, arrayP);
100 }
101 }
102 if (envP->fault_occurred)
103 xmlrpc_DECREF(arrayP);
104 else
105 *arrayPP = arrayP;
106 }
107}
108
109
110
111static void
112parseName(xmlrpc_env * const envP,
113 xml_element * const nameElemP,
114 xmlrpc_value ** const valuePP) {
115
116 size_t const childCount = xml_element_children_size(nameElemP);
117
118 if (childCount > 0)
119 setParseFault(envP, "<name> element has %u children. "
120 "Should have none.", (unsigned int)childCount);
121 else {
122 const char * const cdata = xml_element_cdata(nameElemP);
123 size_t const cdataSize = xml_element_cdata_size(nameElemP);
124
125 *valuePP = xmlrpc_string_new_lp(envP, cdataSize, cdata);
126 }
127}
128
129
130
131static void
132getNameChild(xmlrpc_env * const envP,
133 xml_element * const parentP,
134 xml_element * * const childPP) {
135
136 xml_element ** const children = xml_element_children(parentP);
137 size_t const childCount = xml_element_children_size(parentP);
138
139 xml_element * childP;
140 unsigned int i;
141
142 for (i = 0, childP = NULL((void*)0); i < childCount && !childP; ++i) {
143 if (xmlrpc_streq(xml_element_name(children[i]), "name"))
144 childP = children[i];
145 }
146 if (!childP)
147 xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR(-503),
148 "<member> has no <name> child");
149 else
150 *childPP = childP;
151}
152
153
154
155static void
156getValueChild(xmlrpc_env * const envP,
157 xml_element * const parentP,
158 xml_element * * const childPP) {
159
160 xml_element ** const children = xml_element_children(parentP);
161 size_t const childCount = xml_element_children_size(parentP);
162
163 xml_element * childP;
164 unsigned int i;
165
166 for (i = 0, childP = NULL((void*)0); i < childCount && !childP; ++i) {
167 if (xmlrpc_streq(xml_element_name(children[i]), "value"))
168 childP = children[i];
169 }
170 if (!childP)
171 xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR(-503),
172 "<member> has no <value> child");
173 else
174 *childPP = childP;
175}
176
177
178
179static void
180parseMember(xmlrpc_env * const envP,
181 xml_element * const memberP,
182 unsigned int const maxRecursion,
183 xmlrpc_value ** const keyPP,
184 xmlrpc_value ** const valuePP) {
185
186 size_t const childCount = xml_element_children_size(memberP);
187
188 if (childCount != 2)
189 setParseFault(envP,
190 "<member> element has %u children. Only one <name> and "
191 "one <value> make sense.", (unsigned int)childCount);
192 else {
193 xml_element * nameElemP = NULL((void*)0);
194
195 getNameChild(envP, memberP, &nameElemP);
196
197 if (!envP->fault_occurred) {
198 parseName(envP, nameElemP, keyPP);
199
200 if (!envP->fault_occurred) {
201 xml_element * valueElemP = NULL((void*)0);
202
203 getValueChild(envP, memberP, &valueElemP);
204
205 if (!envP->fault_occurred)
206 xmlrpc_parseValue(envP, maxRecursion-1, valueElemP,
207 valuePP);
208
209 if (envP->fault_occurred)
210 xmlrpc_DECREF(*keyPP);
211 }
212 }
213 }
214}
215
216
217
218static void
219parseStruct(xmlrpc_env * const envP,
220 unsigned int const maxRecursion,
221 xml_element * const elemP,
222 xmlrpc_value ** const structPP) {
223/*----------------------------------------------------------------------------
224 Parse the <struct> element 'elemP'.
225-----------------------------------------------------------------------------*/
226 xmlrpc_value * structP;
227
228 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/parse_value.c", 228); while (
0)
;
229 XMLRPC_ASSERT(elemP != NULL)do if (!(elemP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 229); while (0)
;
230
231 structP = xmlrpc_struct_new(envP);
232 if (!envP->fault_occurred) {
233 /* Iterate over our children, extracting key/value pairs. */
234
235 xml_element ** const members = xml_element_children(elemP);
236 unsigned int const size = xml_element_children_size(elemP);
237
238 unsigned int i;
239
240 for (i = 0; i < size && !envP->fault_occurred; ++i) {
241 const char * const elemName = xml_element_name(members[i]);
242
243 if (!xmlrpc_streq(elemName, "member"))
244 setParseFault(envP, "<%s> element found where only <member> "
245 "makes sense", elemName);
246 else {
247 xmlrpc_value * keyP = NULL((void*)0);
248 xmlrpc_value * valueP;
249
250 parseMember(envP, members[i], maxRecursion, &keyP, &valueP);
251
252 if (!envP->fault_occurred) {
253 xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
254
255 xmlrpc_DECREF(keyP);
256 xmlrpc_DECREF(valueP);
257 }
258 }
259 }
260 if (envP->fault_occurred)
261 xmlrpc_DECREF(structP);
262 else
263 *structPP = structP;
264 }
265}
266
267
268
269static void
270parseInt(xmlrpc_env * const envP,
271 const char * const str,
272 xmlrpc_value ** const valuePP) {
273/*----------------------------------------------------------------------------
274 Parse the content of a <int> XML-RPC XML element, e.g. "34".
275
276 'str' is that content.
277-----------------------------------------------------------------------------*/
278 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/parse_value.c", 278); while (
0)
;
279 XMLRPC_ASSERT_PTR_OK(str)do if (!((str) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 279); while (0)
;
16
Within the expansion of the macro 'XMLRPC_ASSERT_PTR_OK':
a
Assuming 'str' is equal to null
280
281 if (str[0] == '\0')
17
Array access (from variable 'str') results in a null pointer dereference
282 setParseFault(envP, "<int> XML element content is empty");
283 else if (isspace(str[0])((*__ctype_b_loc ())[(int) ((str[0]))] & (unsigned short int
) _ISspace)
)
284 setParseFault(envP, "<int> content '%s' starts with white space",
285 str);
286 else {
287 long i;
288 char * tail;
289
290 errno(*__errno_location ()) = 0;
291 i = strtol(str, &tail, 10);
292
293 /* Look for ERANGE. */
294 if (errno(*__errno_location ()) == ERANGE34)
295 setParseFault(envP, "<int> XML element value '%s' represents a "
296 "number beyond the range that "
297 "XML-RPC allows (%d - %d)", str,
298 XMLRPC_INT32_MIN(-0x7fffffff - 1), XMLRPC_INT32_MAX0x7fffffff);
299 else if (errno(*__errno_location ()) != 0)
300 setParseFault(envP, "unexpected error parsing <int> XML element "
301 "value '%s'. strtol() failed with errno %d (%s)",
302 str, errno(*__errno_location ()), strerror(errno(*__errno_location ())));
303 else {
304 /* Look for out-of-range errors which didn't produce ERANGE. */
305 if (i < XMLRPC_INT32_MIN(-0x7fffffff - 1))
306 setParseFault(envP,
307 "<int> value %ld is below the range allowed "
308 "by XML-RPC (minimum is %d)",
309 i, XMLRPC_INT32_MIN(-0x7fffffff - 1));
310 else if (i > XMLRPC_INT32_MAX0x7fffffff)
311 setParseFault(envP,
312 "<int> value %ld is above the range allowed "
313 "by XML-RPC (maximum is %d)",
314 i, XMLRPC_INT32_MAX0x7fffffff);
315 else {
316 if (tail[0] != '\0')
317 setParseFault(envP,
318 "<int> value '%s' contains non-numerical "
319 "junk: '%s'", str, tail);
320 else
321 *valuePP = xmlrpc_int_new(envP, i);
322 }
323 }
324 }
325}
326
327
328
329static void
330parseBoolean(xmlrpc_env * const envP,
331 const char * const str,
332 xmlrpc_value ** const valuePP) {
333/*----------------------------------------------------------------------------
334 Parse the content of a <boolean> XML-RPC XML element, e.g. "1".
335
336 'str' is that content.
337-----------------------------------------------------------------------------*/
338 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/parse_value.c", 338); while (
0)
;
339 XMLRPC_ASSERT_PTR_OK(str)do if (!((str) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 339); while (0)
;
340
341 if (xmlrpc_streq(str, "0") || xmlrpc_streq(str, "1"))
342 *valuePP = xmlrpc_bool_new(envP, xmlrpc_streq(str, "1") ? 1 : 0);
343 else
344 setParseFault(envP, "<boolean> XML element content must be either "
345 "'0' or '1' according to XML-RPC. This one has '%s'",
346 str);
347}
348
349
350
351static void
352scanAndValidateDoubleString(xmlrpc_env * const envP,
353 const char * const string,
354 const char ** const mantissaP,
355 const char ** const mantissaEndP,
356 const char ** const fractionP,
357 const char ** const fractionEndP) {
358
359 const char * mantissa;
360 const char * dp;
361 const char * p;
362
363 if (string[0] == '-' || string[0] == '+')
364 mantissa = &string[1];
365 else
366 mantissa = &string[0];
367
368 for (p = mantissa, dp = NULL((void*)0); *p; ++p) {
369 char const c = *p;
370 if (c == '.') {
371 if (dp) {
372 setParseFault(envP, "Two decimal points");
373 return;
374 } else
375 dp = p;
376 } else if (c < '0' || c > '9') {
377 setParseFault(envP, "Garbage (not sign, digit, or period) "
378 "starting at '%s'", p);
379 return;
380 }
381 }
382 *mantissaP = mantissa;
383 if (dp) {
384 *mantissaEndP = dp;
385 *fractionP = dp+1;
386 *fractionEndP = p;
387 } else {
388 *mantissaEndP = p;
389 *fractionP = p;
390 *fractionEndP = p;
391 }
392}
393
394
395
396static bool
397isInfinite(double const value) {
398
399 return value > DBL_MAX1.7976931348623157e+308;
400}
401
402
403
404static void
405parseDoubleString(xmlrpc_env * const envP,
406 const char * const string,
407 double * const valueP) {
408/*----------------------------------------------------------------------------
409 Turn e.g. "4.3" into 4.3 .
410-----------------------------------------------------------------------------*/
411 /* strtod() is no good for this because it is designed for human
412 interfaces; it parses according to locale. As a practical
413 matter that sometimes means that it does not recognize "." as a
414 decimal point. In XML-RPC, "." is a decimal point.
415
416 Design note: in my experiments, using strtod() was 10 times
417 slower than using this function.
418 */
419 const char * mantissa = NULL((void*)0);
420 const char * mantissaEnd = NULL((void*)0);
421 const char * fraction = NULL((void*)0);
422 const char * fractionEnd = NULL((void*)0);
423
424 scanAndValidateDoubleString(envP, string, &mantissa, &mantissaEnd,
425 &fraction, &fractionEnd);
426
427 if (!envP->fault_occurred) {
428 double accum;
429
430 accum = 0.0;
431
432 if (mantissa == mantissaEnd && fraction == fractionEnd) {
433 setParseFault(envP, "No digits");
434 return;
435 }
436 {
437 /* Add in the whole part */
438 const char * p;
439
440 for (p = mantissa; p < mantissaEnd; ++p) {
441 accum *= 10;
442 accum += (*p - '0');
443 }
444 }
445 {
446 /* Add in the fractional part */
447 double significance;
448 const char * p;
449 for (significance = 0.1, p = fraction;
450 p < fractionEnd;
451 ++p, significance *= 0.1) {
452
453 accum += (*p - '0') * significance;
454 }
455 }
456 if (isInfinite(accum))
457 setParseFault(envP, "Value exceeds the size allowed by XML-RPC");
458 else
459 *valueP = string[0] == '-' ? (- accum) : accum;
460 }
461}
462
463
464
465static void
466parseDoubleStringStrtod(const char * const str,
467 bool * const failedP,
468 double * const valueP) {
469
470 if (strlen(str) == 0) {
471 /* strtod() happily interprets empty string as 0.0. We don't think
472 the user will appreciate that XML-RPC extension.
473 */
474 *failedP = true;
475 } else {
476 char * tail;
477
478 errno(*__errno_location ()) = 0;
479
480 *valueP = strtod(str, &tail);
481
482 if (errno(*__errno_location ()) != 0)
483 *failedP = true;
484 else {
485 if (tail[0] != '\0')
486 *failedP = true;
487 else
488 *failedP = false;
489 }
490 }
491}
492
493
494
495static void
496parseDouble(xmlrpc_env * const envP,
497 const char * const str,
498 xmlrpc_value ** const valuePP) {
499/*----------------------------------------------------------------------------
500 Parse the content of a <double> XML-RPC XML element, e.g. "34.5".
501
502 'str' is that content.
503-----------------------------------------------------------------------------*/
504 xmlrpc_env parseEnv;
505 double valueDouble = 0;
506
507 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/parse_value.c", 507); while (
0)
;
508 XMLRPC_ASSERT_PTR_OK(str)do if (!((str) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 508); while (0)
;
509
510 xmlrpc_env_init(&parseEnv);
511
512 parseDoubleString(&parseEnv, str, &valueDouble);
513
514 if (parseEnv.fault_occurred) {
515 /* As an alternative, try a strtod() parsing. strtod()
516 accepts other forms, e.g. "3.4E6"; "3,4"; " 3.4". These
517 are not permitted by XML-RPC, but an almost-XML-RPC partner
518 might use one. In fact, for many years, Xmlrpc-c generated
519 such alternatives (by mistake).
520 */
521 bool failed;
522 parseDoubleStringStrtod(str, &failed, &valueDouble);
523 if (failed)
524 setParseFault(envP, "<double> element value '%s' is not a valid "
525 "floating point number. %s",
526 str, parseEnv.fault_string);
527 }
528
529 if (!envP->fault_occurred)
530 *valuePP = xmlrpc_double_new(envP, valueDouble);
531
532 xmlrpc_env_clean(&parseEnv);
533}
534
535
536
537static void
538parseBase64(xmlrpc_env * const envP,
539 const char * const str,
540 size_t const strLength,
541 xmlrpc_value ** const valuePP) {
542/*----------------------------------------------------------------------------
543 Parse the content of a <base64> XML-RPC XML element, e.g. "FD32YY".
544
545 'str' is that content.
546-----------------------------------------------------------------------------*/
547 xmlrpc_mem_block * decoded;
548
549 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/parse_value.c", 549); while (
0)
;
550 XMLRPC_ASSERT_PTR_OK(str)do if (!((str) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 550); while (0)
;
551
552 decoded = xmlrpc_base64_decode(envP, str, strLength);
553 if (!envP->fault_occurred) {
554 unsigned char * const bytes =
555 XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded)((unsigned char*) xmlrpc_mem_block_contents(decoded));
556 size_t const byteCount =
557 XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded)(xmlrpc_mem_block_size(decoded) / sizeof(unsigned char));
558
559 *valuePP = xmlrpc_base64_new(envP, byteCount, bytes);
560
561 XMLRPC_MEMBLOCK_FREE(unsigned char, decoded)xmlrpc_mem_block_free(decoded);
562 }
563}
564
565
566
567static void
568parseI8(xmlrpc_env * const envP,
569 const char * const str,
570 xmlrpc_value ** const valuePP) {
571/*----------------------------------------------------------------------------
572 Parse the content of a <i8> XML-RPC XML element, e.g. "34".
573
574 'str' is that content.
575-----------------------------------------------------------------------------*/
576 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/parse_value.c", 576); while (
0)
;
577 XMLRPC_ASSERT_PTR_OK(str)do if (!((str) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 577); while (0)
;
578
579 if (str[0] == '\0')
580 setParseFault(envP, "<i8> XML element content is empty");
581 else if (isspace(str[0])((*__ctype_b_loc ())[(int) ((str[0]))] & (unsigned short int
) _ISspace)
)
582 setParseFault(envP,
583 "<i8> content '%s' starts with white space", str);
584 else {
585 xmlrpc_int64 i;
586 xmlrpc_env env;
587
588 xmlrpc_env_init(&env);
589
590 xmlrpc_parse_int64(&env, str, &i);
591
592 if (env.fault_occurred)
593 setParseFault(envP, "<i8> XML element value '%s' is invalid "
594 "because it does not represent "
595 "a 64 bit integer. %s", env.fault_string);
596 else
597 *valuePP = xmlrpc_i8_new(envP, i);
598
599 xmlrpc_env_clean(&env);
600 }
601}
602
603
604
605static void
606parseSimpleValueCdata(xmlrpc_env * const envP,
607 const char * const elementName,
608 const char * const cdata,
609 size_t const cdataLength,
610 xmlrpc_value ** const valuePP) {
611/*----------------------------------------------------------------------------
612 Parse an XML element is supposedly a data type element such as
613 <string>. Its name is 'elementName', and it has no children, but
614 contains cdata 'cdata', which is 'dataLength' characters long.
615-----------------------------------------------------------------------------*/
616 /* We need to straighten out the whole character set / encoding thing
617 some day. What is 'cdata', and what should it be? Does it have
618 embedded NUL? Some of the code here assumes it doesn't. Is it
619 text?
620
621 The <string> parser assumes it's UTF 8 with embedded NULs.
622 But the <int> parser will get terribly confused if there are any
623 UTF-8 multibyte sequences or NUL characters. So will most of the
624 others.
625
626 The "ex:XXX" element names are what the Apache XML-RPC facility
627 uses: http://ws.apache.org/xmlrpc/types.html. (Technically, it
628 isn't "ex" but an arbitrary prefix that identifies a namespace
629 declared earlier in the XML document -- this is an XML thing.
630 But we aren't nearly sophisticated enough to use real XML
631 namespaces, so we exploit the fact that XML-RPC actually uses
632 "ex").
633
634 "i1" and "i2" are just from my imagination.
635 */
636
637 if (xmlrpc_streq(elementName, "int") ||
638 xmlrpc_streq(elementName, "i4") ||
639 xmlrpc_streq(elementName, "i1") ||
640 xmlrpc_streq(elementName, "i2") ||
641 xmlrpc_streq(elementName, "ex:i1") ||
642 xmlrpc_streq(elementName, "ex:i2"))
643 parseInt(envP, cdata, valuePP);
14
Passing value via 2nd parameter 'str'
15
Calling 'parseInt'
644 else if (xmlrpc_streq(elementName, "boolean"))
645 parseBoolean(envP, cdata, valuePP);
646 else if (xmlrpc_streq(elementName, "double"))
647 parseDouble(envP, cdata, valuePP);
648 else if (xmlrpc_streq(elementName, "dateTime.iso8601"))
649 xmlrpc_parseDatetime(envP, cdata, valuePP);
650 else if (xmlrpc_streq(elementName, "string"))
651 *valuePP = xmlrpc_string_new_lp(envP, cdataLength, cdata);
652 else if (xmlrpc_streq(elementName, "base64"))
653 parseBase64(envP, cdata, cdataLength, valuePP);
654 else if (xmlrpc_streq(elementName, "nil") ||
655 xmlrpc_streq(elementName, "ex:nil"))
656 *valuePP = xmlrpc_nil_new(envP);
657 else if (xmlrpc_streq(elementName, "i8") ||
658 xmlrpc_streq(elementName, "ex:i8"))
659 parseI8(envP, cdata, valuePP);
660 else
661 setParseFault(envP, "Unknown value type -- XML element is named "
662 "<%s>", elementName);
663}
664
665
666
667static void
668parseSimpleValue(xmlrpc_env * const envP,
669 xml_element * const elemP,
670 xmlrpc_value ** const valuePP) {
671
672 size_t childCount = xml_element_children_size(elemP);
673
674 if (childCount > 0)
11
Assuming 'childCount' is <= 0
12
Taking false branch
675 setParseFault(envP, "The child of a <value> element "
676 "is neither <array> nor <struct>, "
677 "but has %u child elements of its own.",
678 (unsigned int)childCount);
679 else {
680 const char * const elemName = xml_element_name(elemP);
681 const char * const cdata = xml_element_cdata(elemP);
682 size_t const cdataSize = xml_element_cdata_size(elemP);
683
684 parseSimpleValueCdata(envP, elemName, cdata, cdataSize, valuePP);
13
Calling 'parseSimpleValueCdata'
685 }
686}
687
688
689
690void
691xmlrpc_parseValue(xmlrpc_env * const envP,
692 unsigned int const maxRecursion,
693 xml_element * const elemP,
694 xmlrpc_value ** const valuePP) {
695/*----------------------------------------------------------------------------
696 Compute the xmlrpc_value represented by the XML <value> element 'elem'.
697 Return that xmlrpc_value.
698
699 We call convert_array() and convert_struct(), which may ultimately
700 call us recursively. Don't recurse any more than 'maxRecursion'
701 times.
702-----------------------------------------------------------------------------*/
703 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/parse_value.c", 703); while (
0)
;
704 XMLRPC_ASSERT(elemP != NULL)do if (!(elemP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/parse_value.c"
, 704); while (0)
;
705
706 /* Assume we'll need to recurse, make sure we're allowed */
707 if (maxRecursion < 1)
1
Assuming 'maxRecursion' is >= 1
2
Taking false branch
708 xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR(-503),
709 "Nested data structure too deep.");
710 else {
711 if (!xmlrpc_streq(xml_element_name(elemP), "value"))
3
Taking false branch
712 setParseFault(envP,
713 "<%s> element where <value> expected",
714 xml_element_name(elemP));
715 else {
716 size_t const childCount = xml_element_children_size(elemP);
717
718 if (childCount == 0) {
4
Assuming 'childCount' is not equal to 0
5
Taking false branch
719 /* We have no type element, so treat the value as a string. */
720 char * const cdata = xml_element_cdata(elemP);
721 size_t const cdata_size = xml_element_cdata_size(elemP);
722 *valuePP = xmlrpc_string_new_lp(envP, cdata_size, cdata);
723 } else if (childCount > 1)
6
Assuming 'childCount' is <= 1
7
Taking false branch
724 setParseFault(envP, "<value> has %u child elements. "
725 "Only zero or one make sense.",
726 (unsigned int)childCount);
727 else {
728 /* We should have a type tag inside our value tag. */
729 xml_element * const childP = xml_element_children(elemP)[0];
730 const char * const childName = xml_element_name(childP);
731
732 if (xmlrpc_streq(childName, "struct"))
8
Taking false branch
733 parseStruct(envP, maxRecursion, childP, valuePP);
734 else if (xmlrpc_streq(childName, "array"))
9
Taking false branch
735 parseArray(envP, maxRecursion, childP, valuePP);
736 else
737 parseSimpleValue(envP, childP, valuePP);
10
Calling 'parseSimpleValue'
738 }
739 }
740 }
741}
742
743
744