Bug Summary

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

Annotated Source Code

1/* Copyright information is at end of file */
2
3#include "xmlrpc_config.h"
4
5#include <stddef.h>
6#include <stdlib.h>
7#include <stdarg.h>
8#include <string.h>
9
10#include "bool.h"
11#include "c_util.h"
12#include "mallocvar.h"
13#include "stdargx.h"
14
15#include "xmlrpc-c/base.h"
16#include "xmlrpc-c/base_int.h"
17#include "xmlrpc-c/string_int.h"
18
19
20
21static void
22getString(xmlrpc_env * const envP,
23 const char ** const formatP,
24 va_listx * const argsP,
25 xmlrpc_value ** const valPP) {
26
27 const char * str;
28 size_t len;
29
30 str = (const char*) va_arg(argsP->v, char*)__builtin_va_arg(argsP->v, char*);
31 if (*(*formatP) == '#') {
32 ++(*formatP);
33 len = (size_t) va_arg(argsP->v, size_t)__builtin_va_arg(argsP->v, size_t);
34 } else
35 len = strlen(str);
36
37 *valPP = xmlrpc_string_new_lp(envP, len, str);
38}
39
40
41
42static void
43getWideString(xmlrpc_env * const envP ATTR_UNUSED__attribute__((__unused__)),
44 const char ** const formatP ATTR_UNUSED__attribute__((__unused__)),
45 va_listx * const argsP ATTR_UNUSED__attribute__((__unused__)),
46 xmlrpc_value ** const valPP ATTR_UNUSED__attribute__((__unused__))) {
47
48#if HAVE_UNICODE_WCHAR1
49 wchar_t *wcs;
50 size_t len;
51
52 wcs = (wchar_t*) va_arg(argsP->v, wchar_t*)__builtin_va_arg(argsP->v, wchar_t*);
53 if (**formatP == '#') {
54 (*formatP)++;
55 len = (size_t) va_arg(argsP->v, size_t)__builtin_va_arg(argsP->v, size_t);
56 } else
57 len = wcslen(wcs);
58
59 *valPP = xmlrpc_string_w_new_lp(envP, len, wcs);
60
61#endif /* HAVE_UNICODE_WCHAR */
62}
63
64
65
66static void
67getBase64(xmlrpc_env * const envP,
68 va_listx * const argsP,
69 xmlrpc_value ** const valPP) {
70
71 unsigned char * value;
72 size_t length;
73
74 value = (unsigned char*) va_arg(argsP->v, unsigned char*)__builtin_va_arg(argsP->v, unsigned char*);
75 length = (size_t) va_arg(argsP->v, size_t)__builtin_va_arg(argsP->v, size_t);
76
77 *valPP = xmlrpc_base64_new(envP, length, value);
78}
79
80
81
82static void
83getValue(xmlrpc_env * const envP,
84 const char** const format,
85 va_listx * const argsP,
86 xmlrpc_value ** const valPP);
87
88
89
90static void
91getArray(xmlrpc_env * const envP,
92 const char ** const formatP,
93 char const delimiter,
94 va_listx * const argsP,
95 xmlrpc_value ** const arrayPP) {
96
97 xmlrpc_value * arrayP;
98
99 arrayP = xmlrpc_array_new(envP);
100
101 /* Add items to the array until we hit our delimiter. */
102
103 while (**formatP != delimiter && !envP->fault_occurred) {
104
105 xmlrpc_value * itemP;
106
107 if (**formatP == '\0')
108 xmlrpc_env_set_fault(
109 envP, XMLRPC_INTERNAL_ERROR(-500),
110 "format string ended before closing ')'.");
111 else {
112 getValue(envP, formatP, argsP, &itemP);
113 if (!envP->fault_occurred) {
114 xmlrpc_array_append_item(envP, arrayP, itemP);
115 xmlrpc_DECREF(itemP);
116 }
117 }
118 }
119 if (envP->fault_occurred)
120 xmlrpc_DECREF(arrayP);
121
122 *arrayPP = arrayP;
123}
124
125
126
127static void
128getStructMember(xmlrpc_env * const envP,
129 const char ** const formatP,
130 va_listx * const argsP,
131 xmlrpc_value ** const keyPP,
132 xmlrpc_value ** const valuePP) {
133
134
135 /* Get the key */
136 getValue(envP, formatP, argsP, keyPP);
137 if (!envP->fault_occurred) {
138 if (**formatP != ':')
139 xmlrpc_env_set_fault(
140 envP, XMLRPC_INTERNAL_ERROR(-500),
141 "format string does not have ':' after a "
142 "structure member key.");
143 else {
144 /* Skip over colon that separates key from value */
145 (*formatP)++;
146
147 /* Get the value */
148 getValue(envP, formatP, argsP, valuePP);
149 }
150 if (envP->fault_occurred)
151 xmlrpc_DECREF(*keyPP);
152 }
153}
154
155
156
157static void
158getStruct(xmlrpc_env * const envP,
159 const char ** const formatP,
160 char const delimiter,
161 va_listx * const argsP,
162 xmlrpc_value ** const structPP) {
163
164 xmlrpc_value * structP;
165
166 structP = xmlrpc_struct_new(envP);
167 if (!envP->fault_occurred) {
168 while (**formatP != delimiter && !envP->fault_occurred) {
169 xmlrpc_value * keyP;
170 xmlrpc_value * valueP;
171
172 getStructMember(envP, formatP, argsP, &keyP, &valueP);
173
174 if (!envP->fault_occurred) {
175 if (**formatP == ',')
176 (*formatP)++; /* Skip over the comma */
177 else if (**formatP == delimiter) {
178 /* End of the line */
179 } else
180 xmlrpc_env_set_fault(
181 envP, XMLRPC_INTERNAL_ERROR(-500),
182 "format string does not have ',' or ')' after "
183 "a structure member");
184
185 if (!envP->fault_occurred)
186 /* Add the new member to the struct. */
187 xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
188
189 xmlrpc_DECREF(valueP);
190 xmlrpc_DECREF(keyP);
191 }
192 }
193 if (envP->fault_occurred)
194 xmlrpc_DECREF(structP);
195 }
196 *structPP = structP;
197}
198
199
200
201static void
202mkArrayFromVal(xmlrpc_env * const envP,
203 xmlrpc_value * const value,
204 xmlrpc_value ** const valPP) {
205
206 if (xmlrpc_value_type(value) != XMLRPC_TYPE_ARRAY)
207 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR(-500),
208 "Array format ('A'), non-array xmlrpc_value");
209 else
210 xmlrpc_INCREF(value);
211
212 *valPP = value;
213}
214
215
216
217static void
218mkStructFromVal(xmlrpc_env * const envP,
219 xmlrpc_value * const value,
220 xmlrpc_value ** const valPP) {
221
222 if (xmlrpc_value_type(value) != XMLRPC_TYPE_STRUCT)
223 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR(-500),
224 "Struct format ('S'), non-struct xmlrpc_value");
225 else
226 xmlrpc_INCREF(value);
227
228 *valPP = value;
229}
230
231
232
233static void
234getValue(xmlrpc_env * const envP,
235 const char** const formatP,
236 va_listx * const argsP,
237 xmlrpc_value ** const valPP) {
238/*----------------------------------------------------------------------------
239 Get the next value from the list. *formatP points to the specifier
240 for the next value in the format string (i.e. to the type code
241 character) and we move *formatP past the whole specifier for the
242 next value. We read the required arguments from 'argsP'. We return
243 the value as *valPP with a reference to it.
244
245 For example, if *formatP points to the "i" in the string "sis",
246 we read one argument from 'argsP' and return as *valP an integer whose
247 value is the argument we read. We advance *formatP to point to the
248 last 's' and advance 'argsP' to point to the argument that belongs to
249 that 's'.
250-----------------------------------------------------------------------------*/
251 char const formatChar = *(*formatP)++;
252
253 switch (formatChar) {
254 case 'i':
255 *valPP =
256 xmlrpc_int_new(envP, (xmlrpc_int32) va_arg(argsP->v,__builtin_va_arg(argsP->v, xmlrpc_int32)
257 xmlrpc_int32)__builtin_va_arg(argsP->v, xmlrpc_int32));
258 break;
259
260 case 'b':
261 *valPP =
262 xmlrpc_bool_new(envP, (xmlrpc_bool) va_arg(argsP->v, xmlrpc_bool)__builtin_va_arg(argsP->v, xmlrpc_bool));
263 break;
264
265 case 'd':
266 *valPP =
267 xmlrpc_double_new(envP, (double) va_arg(argsP->v, double)__builtin_va_arg(argsP->v, double));
268 break;
269
270 case 's':
271 getString(envP, formatP, argsP, valPP);
272 break;
273
274 case 'w':
275 getWideString(envP, formatP, argsP, valPP);
276 break;
277
278 case 't':
279 *valPP = xmlrpc_datetime_new_sec(envP, va_arg(argsP->v, time_t)__builtin_va_arg(argsP->v, time_t));
280 break;
281
282 case '8':
283 *valPP = xmlrpc_datetime_new_str(envP, va_arg(argsP->v, char*)__builtin_va_arg(argsP->v, char*));
284 break;
285
286 case '6':
287 getBase64(envP, argsP, valPP);
288 break;
289
290 case 'n':
291 *valPP =
292 xmlrpc_nil_new(envP);
293 break;
294
295 case 'I':
296 *valPP =
297 xmlrpc_i8_new(envP, (xmlrpc_int64) va_arg(argsP->v, xmlrpc_int64)__builtin_va_arg(argsP->v, xmlrpc_int64));
298 break;
299
300 case 'p':
301 *valPP =
302 xmlrpc_cptr_new(envP, (void*) va_arg(argsP->v, void*)__builtin_va_arg(argsP->v, void*));
303 break;
304
305 case 'A':
306 mkArrayFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*)__builtin_va_arg(argsP->v, xmlrpc_value*),
307 valPP);
308 break;
309
310 case 'S':
311 mkStructFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*)__builtin_va_arg(argsP->v, xmlrpc_value*),
312 valPP);
313 break;
314
315 case 'V':
316 *valPP = (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*)__builtin_va_arg(argsP->v, xmlrpc_value*);
317 xmlrpc_INCREF(*valPP);
318 break;
319
320 case '(':
321 getArray(envP, formatP, ')', argsP, valPP);
322 if (!envP->fault_occurred) {
323 XMLRPC_ASSERT(**formatP == ')')do if (!(**formatP == ')')) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_build.c"
, 323); while (0)
;
324 (*formatP)++; /* Skip over closing parenthesis */
325 }
326 break;
327
328 case '{':
329 getStruct(envP, formatP, '}', argsP, valPP);
330 if (!envP->fault_occurred) {
331 XMLRPC_ASSERT(**formatP == '}')do if (!(**formatP == '}')) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_build.c"
, 331); while (0)
;
332 (*formatP)++; /* Skip over closing brace */
333 }
334 break;
335
336 default: {
337 const char * const badCharacter = xmlrpc_makePrintableChar(formatChar);
338 xmlrpc_env_set_fault_formatted(
339 envP, XMLRPC_INTERNAL_ERROR(-500),
340 "Unexpected character '%s' in format string", badCharacter);
341 xmlrpc_strfree(badCharacter);
342 }
343 }
344}
345
346
347
348void
349xmlrpc_build_value_va(xmlrpc_env * const envP,
350 const char * const format,
351 va_list const args,
352 xmlrpc_value ** const valPP,
353 const char ** const tailP) {
354
355 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_build.c", 355); while (
0)
;
3
Within the expansion of the macro 'XMLRPC_ASSERT_ENV_OK':
a
Assuming 'envP' is equal to null
356 XMLRPC_ASSERT(format != NULL)do if (!(format != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_build.c"
, 356); while (0)
;
357
358 if (strlen(format) == 0)
4
Taking false branch
359 xmlrpc_faultf(envP, "Format string is empty.");
360 else {
361 va_listx currentArgs;
362 const char * formatCursor;
363
364 init_va_listx(&currentArgs, args);
365 formatCursor = &format[0];
366 getValue(envP, &formatCursor, &currentArgs, valPP);
367
368 if (!envP->fault_occurred)
5
Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP')
369 XMLRPC_ASSERT_VALUE_OK(*valPP)do if (!((*valPP) != ((void*)0) && (*valPP)->_type
!= XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_build.c"
, 369); while (0)
;
370
371 *tailP = formatCursor;
372 }
373}
374
375
376
377xmlrpc_value *
378xmlrpc_build_value(xmlrpc_env * const envP,
379 const char * const format,
380 ...) {
381
382 va_list args;
383 xmlrpc_value * retval;
384 const char * suffix;
385
386 va_start(args, format)__builtin_va_start(args, format);
387 xmlrpc_build_value_va(envP, format, args, &retval, &suffix);
1
Passing value via 1st parameter 'envP'
2
Calling 'xmlrpc_build_value_va'
388 va_end(args)__builtin_va_end(args);
389
390 if (!envP->fault_occurred) {
391 if (*suffix != '\0')
392 xmlrpc_faultf(envP, "Junk after the format specifier: '%s'. "
393 "The format string must describe exactly "
394 "one XML-RPC value "
395 "(but it might be a compound value "
396 "such as an array)",
397 suffix);
398
399 if (envP->fault_occurred)
400 xmlrpc_DECREF(retval);
401 }
402 return retval;
403}
404
405
406/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
407** Copyright (C) 2001 by Eric Kidd. All rights reserved.
408**
409** Redistribution and use in source and binary forms, with or without
410** modification, are permitted provided that the following conditions
411** are met:
412** 1. Redistributions of source code must retain the above copyright
413** notice, this list of conditions and the following disclaimer.
414** 2. Redistributions in binary form must reproduce the above copyright
415** notice, this list of conditions and the following disclaimer in the
416** documentation and/or other materials provided with the distribution.
417** 3. The name of the author may not be used to endorse or promote products
418** derived from this software without specific prior written permission.
419**
420** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
421** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
422** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
423** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
424** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
425** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
426** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
427** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
428** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
429** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
430** SUCH DAMAGE. */