| File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/method.c | 
| Location: | line 332, column 13 | 
| Description: | Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP') | 
| 1 | /*========================================================================= | |||||
| 2 | XML-RPC server method registry | |||||
| 3 | Method services | |||||
| 4 | =========================================================================== | |||||
| 5 | These are the functions that implement the method objects that | |||||
| 6 | the XML-RPC method registry uses. | |||||
| 7 | ||||||
| 8 | By Bryan Henderson, December 2006. | |||||
| 9 | ||||||
| 10 | Contributed to the public domain by its author. | |||||
| 11 | =========================================================================*/ | |||||
| 12 | ||||||
| 13 | #define _XOPEN_SOURCE700 600 /* Make sure strdup() is in <string.h> */ | |||||
| 14 | ||||||
| 15 | #include "xmlrpc_config.h" | |||||
| 16 | ||||||
| 17 | #include <assert.h> | |||||
| 18 | #include <stdlib.h> | |||||
| 19 | #include <string.h> | |||||
| 20 | ||||||
| 21 | #include "bool.h" | |||||
| 22 | #include "mallocvar.h" | |||||
| 23 | #include "xmlrpc-c/base_int.h" | |||||
| 24 | #include "xmlrpc-c/string_int.h" | |||||
| 25 | #include "xmlrpc-c/base.h" | |||||
| 26 | #include "registry.h" | |||||
| 27 | ||||||
| 28 | #include "method.h" | |||||
| 29 | ||||||
| 30 | ||||||
| 31 | static void | |||||
| 32 | signatureDestroy(struct xmlrpc_signature * const signatureP) { | |||||
| 33 | ||||||
| 34 | if (signatureP->argList) | |||||
| 35 | free((void*)signatureP->argList); | |||||
| 36 | ||||||
| 37 | free(signatureP); | |||||
| 38 | } | |||||
| 39 | ||||||
| 40 | ||||||
| 41 | ||||||
| 42 | static void | |||||
| 43 | translateTypeSpecifierToName(xmlrpc_env * const envP, | |||||
| 44 | char const typeSpecifier, | |||||
| 45 | const char ** const typeNameP) { | |||||
| 46 | ||||||
| 47 | switch (typeSpecifier) { | |||||
| 48 | case 'i': *typeNameP = "int"; break; | |||||
| 49 | case 'b': *typeNameP = "boolean"; break; | |||||
| 50 | case 'd': *typeNameP = "double"; break; | |||||
| 51 | case 's': *typeNameP = "string"; break; | |||||
| 52 | case '8': *typeNameP = "dateTime.iso8601"; break; | |||||
| 53 | case '6': *typeNameP = "base64"; break; | |||||
| 54 | case 'S': *typeNameP = "struct"; break; | |||||
| 55 | case 'A': *typeNameP = "array"; break; | |||||
| 56 | case 'n': *typeNameP = "nil"; break; | |||||
| 57 | default: | |||||
| 58 | xmlrpc_faultf(envP, | |||||
| 59 | "Method registry contains invalid signature " | |||||
| 60 | "data. It contains the type specifier '%c'", | |||||
| 61 | typeSpecifier); | |||||
| 62 | *typeNameP = NULL((void*)0); /* quiet compiler warning */ | |||||
| 63 | } | |||||
| 64 | } | |||||
| 65 | ||||||
| 66 | ||||||
| 67 | ||||||
| 68 | #if defined(_MSC_VER) | |||||
| 69 | /* MSVC 8 complains that const char ** is incompatible with void * in the | |||||
| 70 | REALLOCARRAY. It's not. | |||||
| 71 | */ | |||||
| 72 | #pragma warning(push) | |||||
| 73 | #pragma warning(disable:4090) | |||||
| 74 | #endif | |||||
| 75 | ||||||
| 76 | static void | |||||
| 77 | makeRoomInArgList(xmlrpc_env * const envP, | |||||
| 78 | struct xmlrpc_signature * const signatureP, | |||||
| 79 | unsigned int const minArgCount) { | |||||
| 80 | ||||||
| 81 | if (signatureP->argListSpace < minArgCount) { | |||||
| 82 | REALLOCARRAY(signatureP->argList, minArgCount)do { void * array = signatureP->argList; reallocProduct(& array, minArgCount, sizeof(signatureP->argList[0])); signatureP ->argList = array; } while (0); | |||||
| 83 | if (signatureP->argList == NULL((void*)0)) { | |||||
| 84 | xmlrpc_faultf(envP, "Couldn't get memory for a argument list for " | |||||
| 85 | "a method signature with %u arguments", minArgCount); | |||||
| 86 | signatureP->argListSpace = 0; | |||||
| 87 | } | |||||
| 88 | } | |||||
| 89 | } | |||||
| 90 | ||||||
| 91 | #if defined(_MSC_VER) | |||||
| 92 | #pragma warning(pop) | |||||
| 93 | #endif | |||||
| 94 | ||||||
| 95 | ||||||
| 96 | ||||||
| 97 | static void | |||||
| 98 | parseArgumentTypeSpecifiers(xmlrpc_env * const envP, | |||||
| 99 | const char * const startP, | |||||
| 100 | struct xmlrpc_signature * const signatureP, | |||||
| 101 | const char ** const nextPP) { | |||||
| 102 | const char * cursorP; | |||||
| 103 | ||||||
| 104 | cursorP = startP; /* start at the beginning */ | |||||
| 105 | ||||||
| 106 | while (!envP->fault_occurred && *cursorP != ',' && *cursorP != '\0') { | |||||
| 107 | const char * typeName; | |||||
| 108 | ||||||
| 109 | translateTypeSpecifierToName(envP, *cursorP, &typeName); | |||||
| 110 | ||||||
| 111 | if (!envP->fault_occurred) { | |||||
| 112 | ++cursorP; | |||||
| 113 | ||||||
| 114 | makeRoomInArgList(envP, signatureP, signatureP->argCount + 1); | |||||
| 115 | ||||||
| 116 | signatureP->argList[signatureP->argCount++] = typeName; | |||||
| 117 | } | |||||
| 118 | } | |||||
| 119 | if (!envP->fault_occurred) { | |||||
| 120 | if (*cursorP) { | |||||
| 121 | XMLRPC_ASSERT(*cursorP == ',')do if (!(*cursorP == ',')) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/method.c" , 121); while (0); | |||||
| 122 | ++cursorP; /* Move past the signature and comma */ | |||||
| 123 | } | |||||
| 124 | } | |||||
| 125 | if (envP->fault_occurred) | |||||
| 126 | free((void*)signatureP->argList); | |||||
| 127 | ||||||
| 128 | *nextPP = cursorP; | |||||
| 129 | } | |||||
| 130 | ||||||
| 131 | ||||||
| 132 | ||||||
| 133 | static void | |||||
| 134 | parseOneSignature(xmlrpc_env * const envP, | |||||
| 135 | const char * const startP, | |||||
| 136 | struct xmlrpc_signature ** const signaturePP, | |||||
| 137 | const char ** const nextPP) { | |||||
| 138 | /*---------------------------------------------------------------------------- | |||||
| 139 | Parse one signature from the signature string that starts at 'startP'. | |||||
| 140 | ||||||
| 141 | Return that signature as a signature object *signaturePP. | |||||
| 142 | ||||||
| 143 | Return as *nextP the location in the signature string of the next | |||||
| 144 | signature (i.e. right after the next comma). If there is no next | |||||
| 145 | signature (the string ends before any comma), make it point to the | |||||
| 146 | terminating NUL. | |||||
| 147 | -----------------------------------------------------------------------------*/ | |||||
| 148 | struct xmlrpc_signature * signatureP; | |||||
| 149 | ||||||
| 150 | MALLOCVAR(signatureP)signatureP = malloc(sizeof(*signatureP)); | |||||
| 151 | if (signatureP == NULL((void*)0)) | |||||
| 152 | xmlrpc_faultf(envP, "Couldn't get memory for signature"); | |||||
| 153 | else { | |||||
| 154 | const char * cursorP; | |||||
| 155 | ||||||
| 156 | signatureP->argListSpace = 0; /* Start with no argument space */ | |||||
| 157 | signatureP->argList = NULL((void*)0); /* Nothing allocated yet */ | |||||
| 158 | signatureP->argCount = 0; /* Start with no arguments */ | |||||
| 159 | ||||||
| 160 | cursorP = startP; /* start at the beginning */ | |||||
| 161 | ||||||
| 162 | if (*cursorP == ',' || *cursorP == '\0') | |||||
| 163 | xmlrpc_faultf(envP, "empty signature (a signature " | |||||
| 164 | "must have at least return value type)"); | |||||
| 165 | else { | |||||
| 166 | translateTypeSpecifierToName(envP, *cursorP, &signatureP->retType); | |||||
| 167 | ||||||
| 168 | ++cursorP; | |||||
| 169 | ||||||
| 170 | if (*cursorP != ':') | |||||
| 171 | xmlrpc_faultf(envP, "No colon (':') after " | |||||
| 172 | "the result type specifier"); | |||||
| 173 | else { | |||||
| 174 | ++cursorP; | |||||
| 175 | ||||||
| 176 | parseArgumentTypeSpecifiers(envP, cursorP, signatureP, nextPP); | |||||
| 177 | } | |||||
| 178 | } | |||||
| 179 | if (envP->fault_occurred) | |||||
| 180 | free(signatureP); | |||||
| 181 | } | |||||
| 182 | *signaturePP = signatureP; | |||||
| 183 | } | |||||
| 184 | ||||||
| 185 | ||||||
| 186 | ||||||
| 187 | static void | |||||
| 188 | destroySignatures(struct xmlrpc_signature * const firstSignatureP) { | |||||
| 189 | ||||||
| 190 | struct xmlrpc_signature * p; | |||||
| 191 | struct xmlrpc_signature * nextP; | |||||
| 192 | ||||||
| 193 | for (p = firstSignatureP; p; p = nextP) { | |||||
| 194 | nextP = p->nextP; | |||||
| 195 | signatureDestroy(p); | |||||
| 196 | } | |||||
| 197 | } | |||||
| 198 | ||||||
| 199 | ||||||
| 200 | ||||||
| 201 | static void | |||||
| 202 | listSignatures(xmlrpc_env * const envP, | |||||
| 203 | const char * const sigListString, | |||||
| 204 | struct xmlrpc_signature ** const firstSignaturePP) { | |||||
| 205 | ||||||
| 206 | struct xmlrpc_signature ** p; | |||||
| 207 | const char * cursorP; | |||||
| 208 | ||||||
| 209 | *firstSignaturePP = NULL((void*)0); /* Start with empty list */ | |||||
| 210 | ||||||
| 211 | p = firstSignaturePP; | |||||
| 212 | cursorP = &sigListString[0]; | |||||
| 213 | ||||||
| 214 | while (!envP->fault_occurred && *cursorP != '\0') { | |||||
| 215 | struct xmlrpc_signature * signatureP; | |||||
| 216 | ||||||
| 217 | parseOneSignature(envP, cursorP, &signatureP, &cursorP); | |||||
| 218 | ||||||
| 219 | /* cursorP now points at next signature in the list or the | |||||
| 220 | terminating NUL. | |||||
| 221 | */ | |||||
| 222 | ||||||
| 223 | if (!envP->fault_occurred) { | |||||
| 224 | signatureP->nextP = NULL((void*)0); | |||||
| 225 | *p = signatureP; | |||||
| 226 | p = &signatureP->nextP; | |||||
| 227 | } | |||||
| 228 | } | |||||
| 229 | if (envP->fault_occurred) | |||||
| 230 | destroySignatures(*firstSignaturePP); | |||||
| 231 | } | |||||
| 232 | ||||||
| 233 | ||||||
| 234 | ||||||
| 235 | static void | |||||
| 236 | signatureListCreate(xmlrpc_env * const envP, | |||||
| 237 | const char * const sigListString, | |||||
| 238 | xmlrpc_signatureList ** const signatureListPP) { | |||||
| 239 | ||||||
| 240 | xmlrpc_signatureList * signatureListP; | |||||
| 241 | ||||||
| 242 | 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/method.c", 242); while (0); | |||||
| 243 | ||||||
| 244 | MALLOCVAR(signatureListP)signatureListP = malloc(sizeof(*signatureListP)); | |||||
| 245 | ||||||
| 246 | if (signatureListP == NULL((void*)0)) | |||||
| 247 | xmlrpc_faultf(envP, "Could not allocate memory for signature list"); | |||||
| 248 | else { | |||||
| 249 | signatureListP->firstSignatureP = NULL((void*)0); | |||||
| 250 | ||||||
| 251 | if (sigListString == NULL((void*)0) || xmlrpc_streq(sigListString, "?")) { | |||||
| 252 | /* No signatures -- leave the list empty */ | |||||
| 253 | } else { | |||||
| 254 | listSignatures(envP, sigListString, | |||||
| 255 | &signatureListP->firstSignatureP); | |||||
| 256 | ||||||
| 257 | if (!envP->fault_occurred) { | |||||
| 258 | if (!signatureListP->firstSignatureP) | |||||
| 259 | xmlrpc_faultf(envP, "Signature string is empty."); | |||||
| 260 | ||||||
| 261 | if (envP->fault_occurred) | |||||
| 262 | destroySignatures(signatureListP->firstSignatureP); | |||||
| 263 | } | |||||
| 264 | } | |||||
| 265 | if (envP->fault_occurred) | |||||
| 266 | free(signatureListP); | |||||
| 267 | ||||||
| 268 | *signatureListPP = signatureListP; | |||||
| 269 | } | |||||
| 270 | } | |||||
| 271 | ||||||
| 272 | ||||||
| 273 | ||||||
| 274 | static void | |||||
| 275 | signatureListDestroy(xmlrpc_signatureList * const signatureListP) { | |||||
| 276 | ||||||
| 277 | destroySignatures(signatureListP->firstSignatureP); | |||||
| 278 | ||||||
| 279 | free(signatureListP); | |||||
| 280 | } | |||||
| 281 | ||||||
| 282 | ||||||
| 283 | ||||||
| 284 | static void | |||||
| 285 | makeSignatureList(xmlrpc_env * const envP, | |||||
| 286 | const char * const signatureString, | |||||
| 287 | xmlrpc_signatureList ** const signatureListPP) { | |||||
| 288 | ||||||
| 289 | xmlrpc_env env; | |||||
| 290 | ||||||
| 291 | xmlrpc_env_init(&env); | |||||
| 292 | ||||||
| 293 | signatureListCreate(&env, signatureString, signatureListPP); | |||||
| 294 | ||||||
| 295 | if (env.fault_occurred) | |||||
| 296 | xmlrpc_faultf(envP, "Can't interpret signature string '%s'. %s", | |||||
| 297 | signatureString, env.fault_string); | |||||
| 298 | ||||||
| 299 | xmlrpc_env_clean(&env); | |||||
| 300 | } | |||||
| 301 | ||||||
| 302 | ||||||
| 303 | ||||||
| 304 | void | |||||
| 305 | xmlrpc_methodCreate(xmlrpc_env * const envP, | |||||
| 306 | xmlrpc_method1 methodFnType1, | |||||
| 307 | xmlrpc_method2 methodFnType2, | |||||
| 308 | void * const userData, | |||||
| 309 | const char * const signatureString, | |||||
| 310 | const char * const helpText, | |||||
| 311 | size_t const stackSize, | |||||
| 312 | xmlrpc_methodInfo ** const methodPP) { | |||||
| 313 | ||||||
| 314 | xmlrpc_methodInfo * methodP; | |||||
| 315 | ||||||
| 316 | 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/method.c", 316); while (0); | |||||
| 
 
 | ||||||
| 317 | ||||||
| 318 | MALLOCVAR(methodP)methodP = malloc(sizeof(*methodP)); | |||||
| 319 | ||||||
| 320 | if (methodP == NULL((void*)0)) | |||||
| 321 | xmlrpc_faultf(envP, "Unable to allocate storage for a method " | |||||
| 322 | "descriptor"); | |||||
| 323 | else { | |||||
| 324 | methodP->methodFnType1 = methodFnType1; | |||||
| 325 | methodP->methodFnType2 = methodFnType2; | |||||
| 326 | methodP->userData = userData; | |||||
| 327 | methodP->helpText = xmlrpc_strdupsol(helpText); | |||||
| 328 | methodP->stackSize = stackSize; | |||||
| 329 | ||||||
| 330 | makeSignatureList(envP, signatureString, &methodP->signatureListP); | |||||
| 331 | ||||||
| 332 | if (envP->fault_occurred) { | |||||
| 
 | ||||||
| 333 | xmlrpc_strfree(methodP->helpText); | |||||
| 334 | free(methodP); | |||||
| 335 | } | |||||
| 336 | ||||||
| 337 | *methodPP = methodP; | |||||
| 338 | } | |||||
| 339 | } | |||||
| 340 | ||||||
| 341 | ||||||
| 342 | ||||||
| 343 | void | |||||
| 344 | xmlrpc_methodDestroy(xmlrpc_methodInfo * const methodP) { | |||||
| 345 | ||||||
| 346 | signatureListDestroy(methodP->signatureListP); | |||||
| 347 | ||||||
| 348 | xmlrpc_strfree(methodP->helpText); | |||||
| 349 | ||||||
| 350 | free(methodP); | |||||
| 351 | } | |||||
| 352 | ||||||
| 353 | ||||||
| 354 | ||||||
| 355 | void | |||||
| 356 | xmlrpc_methodListCreate(xmlrpc_env * const envP, | |||||
| 357 | xmlrpc_methodList ** const methodListPP) { | |||||
| 358 | ||||||
| 359 | xmlrpc_methodList * methodListP; | |||||
| 360 | ||||||
| 361 | 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/method.c", 361); while (0); | |||||
| 362 | ||||||
| 363 | MALLOCVAR(methodListP)methodListP = malloc(sizeof(*methodListP)); | |||||
| 364 | ||||||
| 365 | if (methodListP == NULL((void*)0)) | |||||
| 366 | xmlrpc_faultf(envP, "Couldn't allocate method list descriptor"); | |||||
| 367 | else { | |||||
| 368 | methodListP->firstMethodP = NULL((void*)0); | |||||
| 369 | methodListP->lastMethodP = NULL((void*)0); | |||||
| 370 | ||||||
| 371 | *methodListPP = methodListP; | |||||
| 372 | } | |||||
| 373 | } | |||||
| 374 | ||||||
| 375 | ||||||
| 376 | ||||||
| 377 | void | |||||
| 378 | xmlrpc_methodListDestroy(xmlrpc_methodList * methodListP) { | |||||
| 379 | ||||||
| 380 | xmlrpc_methodNode * p; | |||||
| 381 | xmlrpc_methodNode * nextP; | |||||
| 382 | ||||||
| 383 | for (p = methodListP->firstMethodP; p; p = nextP) { | |||||
| 384 | nextP = p->nextP; | |||||
| 385 | ||||||
| 386 | xmlrpc_methodDestroy(p->methodP); | |||||
| 387 | xmlrpc_strfree(p->methodName); | |||||
| 388 | free(p); | |||||
| 389 | } | |||||
| 390 | ||||||
| 391 | free(methodListP); | |||||
| 392 | } | |||||
| 393 | ||||||
| 394 | ||||||
| 395 | ||||||
| 396 | void | |||||
| 397 | xmlrpc_methodListLookupByName(xmlrpc_methodList * const methodListP, | |||||
| 398 | const char * const methodName, | |||||
| 399 | xmlrpc_methodInfo ** const methodPP) { | |||||
| 400 | ||||||
| 401 | ||||||
| 402 | /* We do a simple linear lookup along a linked list. | |||||
| 403 | If speed is important, we can make this a binary tree instead. | |||||
| 404 | */ | |||||
| 405 | ||||||
| 406 | xmlrpc_methodNode * p; | |||||
| 407 | xmlrpc_methodInfo * methodP; | |||||
| 408 | ||||||
| 409 | for (p = methodListP->firstMethodP, methodP = NULL((void*)0); | |||||
| 410 | p && !methodP; | |||||
| 411 | p = p->nextP) { | |||||
| 412 | ||||||
| 413 | if (xmlrpc_streq(p->methodName, methodName)) | |||||
| 414 | methodP = p->methodP; | |||||
| 415 | } | |||||
| 416 | *methodPP = methodP; | |||||
| 417 | } | |||||
| 418 | ||||||
| 419 | ||||||
| 420 | ||||||
| 421 | void | |||||
| 422 | xmlrpc_methodListAdd(xmlrpc_env * const envP, | |||||
| 423 | xmlrpc_methodList * const methodListP, | |||||
| 424 | const char * const methodName, | |||||
| 425 | xmlrpc_methodInfo * const methodP) { | |||||
| 426 | ||||||
| 427 | xmlrpc_methodInfo * existingMethodP; | |||||
| 428 | ||||||
| 429 | 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/method.c", 429); while (0); | |||||
| 430 | ||||||
| 431 | xmlrpc_methodListLookupByName(methodListP, methodName, &existingMethodP); | |||||
| 432 | ||||||
| 433 | if (existingMethodP) | |||||
| 434 | xmlrpc_faultf(envP, "Method named '%s' already registered", | |||||
| 435 | methodName); | |||||
| 436 | else { | |||||
| 437 | xmlrpc_methodNode * methodNodeP; | |||||
| 438 | ||||||
| 439 | MALLOCVAR(methodNodeP)methodNodeP = malloc(sizeof(*methodNodeP)); | |||||
| 440 | ||||||
| 441 | if (methodNodeP == NULL((void*)0)) | |||||
| 442 | xmlrpc_faultf(envP, "Couldn't allocate method node"); | |||||
| 443 | else { | |||||
| 444 | methodNodeP->methodName = strdup(methodName)(__extension__ (__builtin_constant_p (methodName) && ( (size_t)(const void *)((methodName) + 1) - (size_t)(const void *)(methodName) == 1) ? (((const char *) (methodName))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (methodName) + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, methodName, __len); __retval; })) : __strdup (methodName ))); | |||||
| 445 | methodNodeP->methodP = methodP; | |||||
| 446 | methodNodeP->nextP = NULL((void*)0); | |||||
| 447 | ||||||
| 448 | if (!methodListP->firstMethodP) | |||||
| 449 | methodListP->firstMethodP = methodNodeP; | |||||
| 450 | ||||||
| 451 | if (methodListP->lastMethodP) | |||||
| 452 | methodListP->lastMethodP->nextP = methodNodeP; | |||||
| 453 | ||||||
| 454 | methodListP->lastMethodP = methodNodeP; | |||||
| 455 | } | |||||
| 456 | } | |||||
| 457 | } | |||||
| 458 |