File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_build.c |
Location: | line 358, column 9 |
Description: | Null pointer passed as an argument to a 'nonnull' parameter |
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 | ||||
21 | static void | |||
22 | getString(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 | ||||
42 | static void | |||
43 | getWideString(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 | ||||
66 | static void | |||
67 | getBase64(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 | ||||
82 | static void | |||
83 | getValue(xmlrpc_env * const envP, | |||
84 | const char** const format, | |||
85 | va_listx * const argsP, | |||
86 | xmlrpc_value ** const valPP); | |||
87 | ||||
88 | ||||
89 | ||||
90 | static void | |||
91 | getArray(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 | ||||
127 | static void | |||
128 | getStructMember(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 | ||||
157 | static void | |||
158 | getStruct(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 | ||||
201 | static void | |||
202 | mkArrayFromVal(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 | ||||
217 | static void | |||
218 | mkStructFromVal(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 | ||||
233 | static void | |||
234 | getValue(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 | ||||
348 | void | |||
349 | xmlrpc_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); | |||
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) | |||
| ||||
359 | xmlrpc_faultf(envP, "Format string is empty."); | |||
360 | else { | |||
361 | va_listx currentArgs; | |||
362 | const char * formatCursor; | |||
363 | ||||
364 | init_va_listx(¤tArgs, args); | |||
365 | formatCursor = &format[0]; | |||
366 | getValue(envP, &formatCursor, ¤tArgs, valPP); | |||
367 | ||||
368 | if (!envP->fault_occurred) | |||
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 | ||||
377 | xmlrpc_value * | |||
378 | xmlrpc_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); | |||
| ||||
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. */ |