| File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_build.c |
| Location: | line 369, column 13 |
| Description: | The left operand of '!=' is a garbage value |
| 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. */ |