| File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_string.c |
| Location: | line 678, column 10 |
| Description: | Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP') |
| 1 | /*============================================================================= | |||
| 2 | xmlrpc_string | |||
| 3 | =============================================================================== | |||
| 4 | Routines for the "string" type of xmlrpc_value. | |||
| 5 | ||||
| 6 | By Bryan Henderson. | |||
| 7 | ||||
| 8 | Contributed to the public domain by its author. | |||
| 9 | =============================================================================*/ | |||
| 10 | ||||
| 11 | #include "xmlrpc_config.h" | |||
| 12 | ||||
| 13 | #include <stddef.h> | |||
| 14 | #include <stdlib.h> | |||
| 15 | #include <stdarg.h> | |||
| 16 | #include <string.h> | |||
| 17 | ||||
| 18 | #include "bool.h" | |||
| 19 | #include "mallocvar.h" | |||
| 20 | ||||
| 21 | #include "xmlrpc-c/base.h" | |||
| 22 | #include "xmlrpc-c/base_int.h" | |||
| 23 | #include "xmlrpc-c/string_int.h" | |||
| 24 | ||||
| 25 | ||||
| 26 | ||||
| 27 | void | |||
| 28 | xmlrpc_destroyString(xmlrpc_value * const valueP) { | |||
| 29 | ||||
| 30 | if (valueP->_wcs_block) | |||
| 31 | xmlrpc_mem_block_free(valueP->_wcs_block); | |||
| 32 | ||||
| 33 | xmlrpc_mem_block_clean(&valueP->_block); | |||
| 34 | } | |||
| 35 | ||||
| 36 | ||||
| 37 | ||||
| 38 | static void | |||
| 39 | verifyNoNulls(xmlrpc_env * const envP, | |||
| 40 | const char * const contents, | |||
| 41 | unsigned int const len) { | |||
| 42 | /*---------------------------------------------------------------------------- | |||
| 43 | Verify that the character array 'contents', which is 'len' bytes long, | |||
| 44 | does not contain any NUL characters, which means it can be made into | |||
| 45 | a passable ASCIIZ string just by adding a terminating NUL. | |||
| 46 | ||||
| 47 | Fail if the array contains a NUL. | |||
| 48 | -----------------------------------------------------------------------------*/ | |||
| 49 | unsigned int i; | |||
| 50 | ||||
| 51 | for (i = 0; i < len && !envP->fault_occurred; ++i) | |||
| 52 | if (contents[i] == '\0') | |||
| 53 | xmlrpc_env_set_fault_formatted( | |||
| 54 | envP, XMLRPC_TYPE_ERROR(-501), | |||
| 55 | "String must not contain NUL characters"); | |||
| 56 | } | |||
| 57 | ||||
| 58 | ||||
| 59 | ||||
| 60 | #if HAVE_UNICODE_WCHAR1 | |||
| 61 | ||||
| 62 | static void | |||
| 63 | verifyNoNullsW(xmlrpc_env * const envP, | |||
| 64 | const wchar_t * const contents, | |||
| 65 | unsigned int const len) { | |||
| 66 | /*---------------------------------------------------------------------------- | |||
| 67 | Same as verifyNoNulls(), but for wide characters. | |||
| 68 | -----------------------------------------------------------------------------*/ | |||
| 69 | unsigned int i; | |||
| 70 | ||||
| 71 | for (i = 0; i < len && !envP->fault_occurred; i++) | |||
| 72 | if (contents[i] == '\0') | |||
| 73 | xmlrpc_env_set_fault_formatted( | |||
| 74 | envP, XMLRPC_TYPE_ERROR(-501), | |||
| 75 | "String must not contain NUL characters"); | |||
| 76 | } | |||
| 77 | #endif | |||
| 78 | ||||
| 79 | ||||
| 80 | ||||
| 81 | static void | |||
| 82 | validateStringType(xmlrpc_env * const envP, | |||
| 83 | const xmlrpc_value * const valueP) { | |||
| 84 | ||||
| 85 | if (valueP->_type != XMLRPC_TYPE_STRING) { | |||
| 86 | xmlrpc_env_set_fault_formatted( | |||
| 87 | envP, XMLRPC_TYPE_ERROR(-501), "Value of type %s supplied where " | |||
| 88 | "string type was expected.", | |||
| 89 | xmlrpc_type_name(valueP->_type)); | |||
| 90 | } | |||
| 91 | } | |||
| 92 | ||||
| 93 | ||||
| 94 | ||||
| 95 | static void | |||
| 96 | accessStringValue(xmlrpc_env * const envP, | |||
| 97 | const xmlrpc_value * const valueP, | |||
| 98 | size_t * const lengthP, | |||
| 99 | const char ** const contentsP) { | |||
| 100 | ||||
| 101 | validateStringType(envP, valueP); | |||
| 102 | if (!envP->fault_occurred) { | |||
| 103 | size_t const size = | |||
| 104 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); | |||
| 105 | const char * const contents = | |||
| 106 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||
| 107 | size_t const len = size - 1; | |||
| 108 | /* The memblock has a null character added to the end */ | |||
| 109 | ||||
| 110 | verifyNoNulls(envP, contents, len); | |||
| 111 | ||||
| 112 | *lengthP = len; | |||
| 113 | *contentsP = contents; | |||
| 114 | } | |||
| 115 | } | |||
| 116 | ||||
| 117 | ||||
| 118 | ||||
| 119 | void | |||
| 120 | xmlrpc_read_string(xmlrpc_env * const envP, | |||
| 121 | const xmlrpc_value * const valueP, | |||
| 122 | const char ** const stringValueP) { | |||
| 123 | /*---------------------------------------------------------------------------- | |||
| 124 | Read the value of an XML-RPC string as an ASCIIZ string, with | |||
| 125 | LF for line delimiters. | |||
| 126 | ||||
| 127 | Return the string in newly malloc'ed storage that Caller must free. | |||
| 128 | ||||
| 129 | Fail if the string contains null characters (which means it wasn't | |||
| 130 | really a string, but XML-RPC doesn't seem to understand what a string | |||
| 131 | is, and such values are possible). | |||
| 132 | -----------------------------------------------------------------------------*/ | |||
| 133 | size_t length; | |||
| 134 | const char * contents; | |||
| 135 | ||||
| 136 | accessStringValue(envP, valueP, &length, &contents); | |||
| 137 | ||||
| 138 | if (!envP->fault_occurred) { | |||
| 139 | char * stringValue; | |||
| 140 | ||||
| 141 | MALLOCARRAY(stringValue, length + 1)do { void * array; mallocProduct(&array, length + 1, sizeof (stringValue[0])); stringValue = array; } while (0); | |||
| 142 | if (stringValue == NULL((void*)0)) | |||
| 143 | xmlrpc_faultf(envP, "Unable to allocate space " | |||
| 144 | "for %u-character string", (unsigned)length); | |||
| 145 | else { | |||
| 146 | memcpy(stringValue, contents, length); | |||
| 147 | stringValue[length] = '\0'; | |||
| 148 | ||||
| 149 | *stringValueP = stringValue; | |||
| 150 | } | |||
| 151 | } | |||
| 152 | } | |||
| 153 | ||||
| 154 | ||||
| 155 | ||||
| 156 | static unsigned int | |||
| 157 | lineDelimCount(const char * const start, | |||
| 158 | const char * const end) { | |||
| 159 | ||||
| 160 | unsigned int count; | |||
| 161 | const char * p; | |||
| 162 | ||||
| 163 | for (p = start, count = 0; p < end; ) { | |||
| 164 | const char * const nlPos = memchr(p, '\n', end-p); | |||
| 165 | if (nlPos) { | |||
| 166 | ++count; | |||
| 167 | p = nlPos + 1; | |||
| 168 | } else | |||
| 169 | p = end; | |||
| 170 | } | |||
| 171 | ||||
| 172 | return count; | |||
| 173 | } | |||
| 174 | ||||
| 175 | ||||
| 176 | ||||
| 177 | static void | |||
| 178 | copyAndConvertLfToCrlf(xmlrpc_env * const envP, | |||
| 179 | size_t const srcLen, | |||
| 180 | const char * const src, | |||
| 181 | size_t * const dstLenP, | |||
| 182 | const char ** const dstP) { | |||
| 183 | ||||
| 184 | const char * const srcEnd = src + srcLen; | |||
| 185 | unsigned int const nLineDelim = lineDelimCount(src, srcEnd); | |||
| 186 | size_t const dstLen = srcLen + nLineDelim; | |||
| 187 | char * dst; | |||
| 188 | ||||
| 189 | MALLOCARRAY(dst, dstLen + 1)do { void * array; mallocProduct(&array, dstLen + 1, sizeof (dst[0])); dst = array; } while (0); | |||
| 190 | if (dst == NULL((void*)0)) | |||
| 191 | xmlrpc_faultf(envP, "Unable to allocate space " | |||
| 192 | "for %u-character string", (unsigned)dstLen + 1); | |||
| 193 | else { | |||
| 194 | const char * p; /* source pointer */ | |||
| 195 | char * q; /* destination pointer */ | |||
| 196 | ||||
| 197 | for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) { | |||
| 198 | if (*p == '\n') | |||
| 199 | *q++ = '\r'; | |||
| 200 | ||||
| 201 | *q++ = *p; | |||
| 202 | } | |||
| 203 | XMLRPC_ASSERT(q == dst + dstLen)do if (!(q == dst + dstLen)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_string.c" , 203); while (0); | |||
| 204 | ||||
| 205 | *q = '\0'; | |||
| 206 | ||||
| 207 | *dstP = dst; | |||
| 208 | *dstLenP = dstLen; | |||
| 209 | } | |||
| 210 | } | |||
| 211 | ||||
| 212 | ||||
| 213 | ||||
| 214 | void | |||
| 215 | xmlrpc_read_string_crlf(xmlrpc_env * const envP, | |||
| 216 | const xmlrpc_value * const valueP, | |||
| 217 | const char ** const stringValueP) { | |||
| 218 | /*---------------------------------------------------------------------------- | |||
| 219 | Same as xmlrpc_read_string(), but return CRLF instead of LF for | |||
| 220 | line delimiters. | |||
| 221 | -----------------------------------------------------------------------------*/ | |||
| 222 | size_t length; | |||
| 223 | const char * contents; | |||
| 224 | ||||
| 225 | accessStringValue(envP, valueP, &length, &contents); | |||
| 226 | ||||
| 227 | if (!envP->fault_occurred) { | |||
| 228 | size_t stringLen; | |||
| 229 | ||||
| 230 | copyAndConvertLfToCrlf(envP, length, contents, | |||
| 231 | &stringLen, stringValueP); | |||
| 232 | } | |||
| 233 | } | |||
| 234 | ||||
| 235 | ||||
| 236 | ||||
| 237 | void | |||
| 238 | xmlrpc_read_string_old(xmlrpc_env * const envP, | |||
| 239 | const xmlrpc_value * const valueP, | |||
| 240 | const char ** const stringValueP) { | |||
| 241 | ||||
| 242 | size_t length; | |||
| 243 | accessStringValue(envP, valueP, &length, stringValueP); | |||
| 244 | } | |||
| 245 | ||||
| 246 | ||||
| 247 | ||||
| 248 | void | |||
| 249 | xmlrpc_read_string_lp(xmlrpc_env * const envP, | |||
| 250 | const xmlrpc_value * const valueP, | |||
| 251 | size_t * const lengthP, | |||
| 252 | const char ** const stringValueP) { | |||
| 253 | ||||
| 254 | validateStringType(envP, valueP); | |||
| 255 | if (!envP->fault_occurred) { | |||
| 256 | size_t const size = | |||
| 257 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); | |||
| 258 | const char * const contents = | |||
| 259 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||
| 260 | ||||
| 261 | char * stringValue; | |||
| 262 | ||||
| 263 | stringValue = malloc(size); | |||
| 264 | if (stringValue == NULL((void*)0)) | |||
| 265 | xmlrpc_faultf(envP, "Unable to allocate %u bytes for string.", | |||
| 266 | (unsigned int)size); | |||
| 267 | else { | |||
| 268 | memcpy(stringValue, contents, size); | |||
| 269 | *stringValueP = stringValue; | |||
| 270 | *lengthP = size - 1; /* Size includes terminating NUL */ | |||
| 271 | } | |||
| 272 | } | |||
| 273 | } | |||
| 274 | ||||
| 275 | ||||
| 276 | ||||
| 277 | void | |||
| 278 | xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP, | |||
| 279 | const xmlrpc_value * const valueP, | |||
| 280 | size_t * const lengthP, | |||
| 281 | const char ** const stringValueP) { | |||
| 282 | ||||
| 283 | validateStringType(envP, valueP); | |||
| 284 | if (!envP->fault_occurred) { | |||
| 285 | size_t const size = | |||
| 286 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ); /* Includes NUL */ | |||
| 287 | const char * const contents = | |||
| 288 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||
| 289 | ||||
| 290 | copyAndConvertLfToCrlf(envP, size-1, contents, | |||
| 291 | lengthP, stringValueP); | |||
| 292 | } | |||
| 293 | } | |||
| 294 | ||||
| 295 | ||||
| 296 | ||||
| 297 | void | |||
| 298 | xmlrpc_read_string_lp_old(xmlrpc_env * const envP, | |||
| 299 | const xmlrpc_value * const valueP, | |||
| 300 | size_t * const lengthP, | |||
| 301 | const char ** const stringValueP) { | |||
| 302 | ||||
| 303 | validateStringType(envP, valueP); | |||
| 304 | if (!envP->fault_occurred) { | |||
| 305 | *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ) - 1; | |||
| 306 | *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||
| 307 | } | |||
| 308 | } | |||
| 309 | ||||
| 310 | ||||
| 311 | ||||
| 312 | static __inline__ void | |||
| 313 | setupWcsBlock(xmlrpc_env * const envP, | |||
| 314 | xmlrpc_value * const valueP) { | |||
| 315 | /*---------------------------------------------------------------------------- | |||
| 316 | Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it | |||
| 317 | doesn't have one already. | |||
| 318 | -----------------------------------------------------------------------------*/ | |||
| 319 | if (!valueP->_wcs_block) { | |||
| 320 | char * const contents = | |||
| 321 | XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block)((char*) xmlrpc_mem_block_contents(&valueP->_block)); | |||
| 322 | size_t const len = | |||
| 323 | XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(char) ) - 1; | |||
| 324 | valueP->_wcs_block = | |||
| 325 | xmlrpc_utf8_to_wcs(envP, contents, len + 1); | |||
| 326 | } | |||
| 327 | } | |||
| 328 | ||||
| 329 | ||||
| 330 | ||||
| 331 | #if HAVE_UNICODE_WCHAR1 | |||
| 332 | ||||
| 333 | static void | |||
| 334 | accessStringValueW(xmlrpc_env * const envP, | |||
| 335 | xmlrpc_value * const valueP, | |||
| 336 | size_t * const lengthP, | |||
| 337 | const wchar_t ** const stringValueP) { | |||
| 338 | ||||
| 339 | validateStringType(envP, valueP); | |||
| 340 | if (!envP->fault_occurred) { | |||
| 341 | setupWcsBlock(envP, valueP); | |||
| 342 | ||||
| 343 | if (!envP->fault_occurred) { | |||
| 344 | wchar_t * const wcontents = | |||
| 345 | XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block)((wchar_t*) xmlrpc_mem_block_contents(valueP->_wcs_block)); | |||
| 346 | size_t const len = | |||
| 347 | XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block)(xmlrpc_mem_block_size(valueP->_wcs_block) / sizeof(wchar_t )) - 1; | |||
| 348 | ||||
| 349 | verifyNoNullsW(envP, wcontents, len); | |||
| 350 | ||||
| 351 | *lengthP = len; | |||
| 352 | *stringValueP = wcontents; | |||
| 353 | } | |||
| 354 | } | |||
| 355 | } | |||
| 356 | ||||
| 357 | ||||
| 358 | ||||
| 359 | void | |||
| 360 | xmlrpc_read_string_w(xmlrpc_env * const envP, | |||
| 361 | xmlrpc_value * const valueP, | |||
| 362 | const wchar_t ** const stringValueP) { | |||
| 363 | ||||
| 364 | size_t length; | |||
| 365 | const wchar_t * wcontents; | |||
| 366 | ||||
| 367 | accessStringValueW(envP, valueP, &length, &wcontents); | |||
| 368 | ||||
| 369 | if (!envP->fault_occurred) { | |||
| 370 | wchar_t * stringValue; | |||
| 371 | MALLOCARRAY(stringValue, length + 1)do { void * array; mallocProduct(&array, length + 1, sizeof (stringValue[0])); stringValue = array; } while (0); | |||
| 372 | if (stringValue == NULL((void*)0)) | |||
| 373 | xmlrpc_faultf(envP, "Unable to allocate space for %u-byte string", | |||
| 374 | (unsigned)length); | |||
| 375 | else { | |||
| 376 | memcpy(stringValue, wcontents, length * sizeof(wchar_t)); | |||
| 377 | stringValue[length] = '\0'; | |||
| 378 | ||||
| 379 | *stringValueP = stringValue; | |||
| 380 | } | |||
| 381 | } | |||
| 382 | } | |||
| 383 | ||||
| 384 | ||||
| 385 | ||||
| 386 | static unsigned int | |||
| 387 | lineDelimCountW(const wchar_t * const start, | |||
| 388 | const wchar_t * const end) { | |||
| 389 | ||||
| 390 | unsigned int count; | |||
| 391 | const wchar_t * p; | |||
| 392 | ||||
| 393 | count = 0; | |||
| 394 | p = start; | |||
| 395 | ||||
| 396 | while (p && p < end) { | |||
| 397 | /* We used to use memchr(), but Windows doesn't have it */ | |||
| 398 | p = wcsstr(p, L"\n"); | |||
| 399 | if (p && p < end) { | |||
| 400 | ++count; /* count the newline */ | |||
| 401 | ++p; /* skip the newline */ | |||
| 402 | } | |||
| 403 | } | |||
| 404 | ||||
| 405 | return count; | |||
| 406 | } | |||
| 407 | ||||
| 408 | ||||
| 409 | ||||
| 410 | static void | |||
| 411 | wCopyAndConvertLfToCrlf(xmlrpc_env * const envP, | |||
| 412 | size_t const srcLen, | |||
| 413 | const wchar_t * const src, | |||
| 414 | size_t * const dstLenP, | |||
| 415 | const wchar_t ** const dstP) { | |||
| 416 | ||||
| 417 | const wchar_t * const srcEnd = src + srcLen; | |||
| 418 | unsigned int const nLineDelim = lineDelimCountW(src, srcEnd); | |||
| 419 | size_t const dstLen = srcLen + nLineDelim; | |||
| 420 | wchar_t * dst; | |||
| 421 | ||||
| 422 | MALLOCARRAY(dst, dstLen + 1)do { void * array; mallocProduct(&array, dstLen + 1, sizeof (dst[0])); dst = array; } while (0); | |||
| 423 | if (dst == NULL((void*)0)) | |||
| 424 | xmlrpc_faultf(envP, "Unable to allocate space " | |||
| 425 | "for %u-character string", (unsigned)dstLen + 1); | |||
| 426 | else { | |||
| 427 | const wchar_t * p; /* source pointer */ | |||
| 428 | wchar_t * q; /* destination pointer */ | |||
| 429 | ||||
| 430 | for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) { | |||
| 431 | if (*p == '\n') | |||
| 432 | *q++ = '\r'; | |||
| 433 | ||||
| 434 | *q++ = *p; | |||
| 435 | } | |||
| 436 | XMLRPC_ASSERT(q == dst + dstLen)do if (!(q == dst + dstLen)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_string.c" , 436); while (0); | |||
| 437 | ||||
| 438 | *q = '\0'; | |||
| 439 | ||||
| 440 | *dstP = dst; | |||
| 441 | *dstLenP = dstLen; | |||
| 442 | } | |||
| 443 | } | |||
| 444 | ||||
| 445 | ||||
| 446 | ||||
| 447 | void | |||
| 448 | xmlrpc_read_string_w_crlf(xmlrpc_env * const envP, | |||
| 449 | xmlrpc_value * const valueP, | |||
| 450 | const wchar_t ** const stringValueP) { | |||
| 451 | ||||
| 452 | size_t size; | |||
| 453 | const wchar_t * contents; | |||
| 454 | ||||
| 455 | accessStringValueW(envP, valueP, &size, &contents); | |||
| 456 | ||||
| 457 | if (!envP->fault_occurred) { | |||
| 458 | size_t stringLen; | |||
| 459 | ||||
| 460 | wCopyAndConvertLfToCrlf(envP, size, contents, | |||
| 461 | &stringLen, stringValueP); | |||
| 462 | } | |||
| 463 | } | |||
| 464 | ||||
| 465 | ||||
| 466 | ||||
| 467 | void | |||
| 468 | xmlrpc_read_string_w_old(xmlrpc_env * const envP, | |||
| 469 | xmlrpc_value * const valueP, | |||
| 470 | const wchar_t ** const stringValueP) { | |||
| 471 | ||||
| 472 | size_t length; | |||
| 473 | ||||
| 474 | accessStringValueW(envP, valueP, &length, stringValueP); | |||
| 475 | } | |||
| 476 | ||||
| 477 | ||||
| 478 | ||||
| 479 | void | |||
| 480 | xmlrpc_read_string_w_lp(xmlrpc_env * const envP, | |||
| 481 | xmlrpc_value * const valueP, | |||
| 482 | size_t * const lengthP, | |||
| 483 | const wchar_t ** const stringValueP) { | |||
| 484 | ||||
| 485 | validateStringType(envP, valueP); | |||
| 486 | if (!envP->fault_occurred) { | |||
| 487 | setupWcsBlock(envP, valueP); | |||
| 488 | ||||
| 489 | if (!envP->fault_occurred) { | |||
| 490 | wchar_t * const wcontents = | |||
| 491 | XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block)((wchar_t*) xmlrpc_mem_block_contents(valueP->_wcs_block)); | |||
| 492 | size_t const size = | |||
| 493 | XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block)(xmlrpc_mem_block_size(valueP->_wcs_block) / sizeof(wchar_t )); | |||
| 494 | ||||
| 495 | wchar_t * stringValue; | |||
| 496 | ||||
| 497 | MALLOCARRAY(stringValue, size)do { void * array; mallocProduct(&array, size, sizeof(stringValue [0])); stringValue = array; } while (0); | |||
| 498 | if (stringValue == NULL((void*)0)) | |||
| 499 | xmlrpc_faultf(envP, | |||
| 500 | "Unable to allocate space for %u-byte string", | |||
| 501 | (unsigned int)size); | |||
| 502 | else { | |||
| 503 | memcpy(stringValue, wcontents, size * sizeof(wchar_t)); | |||
| 504 | ||||
| 505 | *lengthP = size - 1; /* size includes terminating NUL */ | |||
| 506 | *stringValueP = stringValue; | |||
| 507 | } | |||
| 508 | } | |||
| 509 | } | |||
| 510 | } | |||
| 511 | ||||
| 512 | ||||
| 513 | ||||
| 514 | void | |||
| 515 | xmlrpc_read_string_w_lp_crlf(xmlrpc_env * const envP, | |||
| 516 | xmlrpc_value * const valueP, | |||
| 517 | size_t * const lengthP, | |||
| 518 | const wchar_t ** const stringValueP) { | |||
| 519 | ||||
| 520 | validateStringType(envP, valueP); | |||
| 521 | if (!envP->fault_occurred) { | |||
| 522 | setupWcsBlock(envP, valueP); | |||
| 523 | ||||
| 524 | if (!envP->fault_occurred) { | |||
| 525 | size_t const size = | |||
| 526 | XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block)(xmlrpc_mem_block_size(valueP->_wcs_block) / sizeof(wchar_t )); | |||
| 527 | wchar_t * const wcontents = | |||
| 528 | XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block)((wchar_t*) xmlrpc_mem_block_contents(valueP->_wcs_block)); | |||
| 529 | ||||
| 530 | wCopyAndConvertLfToCrlf(envP, size-1, wcontents, | |||
| 531 | lengthP, stringValueP); | |||
| 532 | } | |||
| 533 | } | |||
| 534 | } | |||
| 535 | ||||
| 536 | ||||
| 537 | ||||
| 538 | void | |||
| 539 | xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, | |||
| 540 | xmlrpc_value * const valueP, | |||
| 541 | size_t * const lengthP, | |||
| 542 | const wchar_t ** const stringValueP) { | |||
| 543 | ||||
| 544 | validateStringType(envP, valueP); | |||
| 545 | if (!envP->fault_occurred) { | |||
| 546 | setupWcsBlock(envP, valueP); | |||
| 547 | ||||
| 548 | if (!envP->fault_occurred) { | |||
| 549 | wchar_t * const wcontents = | |||
| 550 | XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block)((wchar_t*) xmlrpc_mem_block_contents(valueP->_wcs_block)); | |||
| 551 | size_t const size = | |||
| 552 | XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block)(xmlrpc_mem_block_size(valueP->_wcs_block) / sizeof(wchar_t )); | |||
| 553 | ||||
| 554 | *lengthP = size - 1; /* size includes terminating NUL */ | |||
| 555 | *stringValueP = wcontents; | |||
| 556 | } | |||
| 557 | } | |||
| 558 | } | |||
| 559 | #endif /* HAVE_UNICODE_WCHAR */ | |||
| 560 | ||||
| 561 | ||||
| 562 | ||||
| 563 | static void | |||
| 564 | copyLines(xmlrpc_env * const envP, | |||
| 565 | const char * const src, | |||
| 566 | size_t const srcLen, | |||
| 567 | xmlrpc_mem_block * const dstP) { | |||
| 568 | /*---------------------------------------------------------------------------- | |||
| 569 | Copy the string 'src', 'srcLen' characters long, into 'dst', where | |||
| 570 | 'dst' is the internal representation of string xmlrpc_value contents, | |||
| 571 | and 'src' has lines separated by LF, CR, and/or CRLF. | |||
| 572 | ||||
| 573 | Note that the source format differs from the destination format in | |||
| 574 | that in the destination format, lines are separated only by newline | |||
| 575 | (LF). | |||
| 576 | ||||
| 577 | It is tempting to believe that if we just put the user's line | |||
| 578 | delimiters in the xmlrpc_value here (i.e. where user has CRLF, the | |||
| 579 | xmlrpc_value also has CRLF), the user's line delimiters would go | |||
| 580 | all the way across to the XML-RPC partner. But that won't work, | |||
| 581 | because the XML processor on the other side will, following Section | |||
| 582 | 2.11 of the XML spec, normalize all line endings to LF anyhow. So | |||
| 583 | then you might ask, why do we bother to do all the work to convert | |||
| 584 | them here? Because: besides just being logically cleaner, this way | |||
| 585 | xmlrpc_read_string() gets the proper value -- the same one the | |||
| 586 | XML-RPC partner would see. | |||
| 587 | -----------------------------------------------------------------------------*/ | |||
| 588 | /* Destination format is sometimes smaller than source (because | |||
| 589 | CRLF turns into LF), but never smaller. So we allocate | |||
| 590 | destination space equal to source size (plus one for | |||
| 591 | terminating NUL), but don't necessarily use it all. | |||
| 592 | */ | |||
| 593 | ||||
| 594 | /* To convert LF, CR, and CRLF to LF, all we have to do is | |||
| 595 | copy everything up to a CR verbatim, then insert an LF and | |||
| 596 | skip the CR and any following LF, and repeat. | |||
| 597 | */ | |||
| 598 | ||||
| 599 | XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1)xmlrpc_mem_block_init((envP), (dstP), sizeof(char) * (srcLen + 1)); | |||
| 600 | ||||
| 601 | if (!envP->fault_occurred) { | |||
| 602 | const char * const srcEnd = &src[srcLen]; | |||
| 603 | char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP)((char*) xmlrpc_mem_block_contents(dstP)); | |||
| 604 | ||||
| 605 | const char * srcCursor; | |||
| 606 | char * dstCursor; | |||
| 607 | ||||
| 608 | for (srcCursor = &src[0], dstCursor = &contents[0]; | |||
| 609 | srcCursor < srcEnd;) { | |||
| 610 | ||||
| 611 | char * const crPos = memchr(srcCursor, '\r', srcEnd - srcCursor); | |||
| 612 | ||||
| 613 | if (crPos) { | |||
| 614 | size_t const copyLen = crPos - srcCursor; | |||
| 615 | memcpy(dstCursor, srcCursor, copyLen); | |||
| 616 | srcCursor += copyLen; | |||
| 617 | dstCursor += copyLen; | |||
| 618 | ||||
| 619 | *(dstCursor++) = '\n'; | |||
| 620 | ||||
| 621 | XMLRPC_ASSERT(*srcCursor == '\r')do if (!(*srcCursor == '\r')) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_string.c" , 621); while (0); | |||
| 622 | ++srcCursor; /* Move past CR */ | |||
| 623 | if (*srcCursor == '\n') | |||
| 624 | ++srcCursor; /* Move past LF */ | |||
| 625 | } else { | |||
| 626 | size_t const remainingLen = srcEnd - srcCursor; | |||
| 627 | memcpy(dstCursor, srcCursor, remainingLen); | |||
| 628 | srcCursor += remainingLen; | |||
| 629 | dstCursor += remainingLen; | |||
| 630 | } | |||
| 631 | } | |||
| 632 | ||||
| 633 | *dstCursor++ = '\0'; | |||
| 634 | ||||
| 635 | XMLRPC_ASSERT((unsigned)(dstCursor - &contents[0]) <= srcLen + 1)do if (!((unsigned)(dstCursor - &contents[0]) <= srcLen + 1)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_string.c" , 635); while (0); | |||
| 636 | ||||
| 637 | XMLRPC_MEMBLOCK_RESIZE(char, envP, dstP, dstCursor - &contents[0])xmlrpc_mem_block_resize(envP, dstP, sizeof(char) * (dstCursor - &contents[0])); | |||
| 638 | } | |||
| 639 | } | |||
| 640 | ||||
| 641 | ||||
| 642 | ||||
| 643 | static void | |||
| 644 | copySimple(xmlrpc_env * const envP, | |||
| 645 | const char * const src, | |||
| 646 | size_t const srcLen, | |||
| 647 | xmlrpc_mem_block * const dstP) { | |||
| 648 | /*---------------------------------------------------------------------------- | |||
| 649 | Copy the string 'src', 'srcLen' characters long, into 'dst', where | |||
| 650 | 'dst' is the internal representation of string xmlrpc_value contents, | |||
| 651 | and 'src', conveniently enough, is in the exact same format. | |||
| 652 | ||||
| 653 | To wit, 'src' has lines separated by LFs only -- no CR or CRLF. | |||
| 654 | -----------------------------------------------------------------------------*/ | |||
| 655 | XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1)xmlrpc_mem_block_init((envP), (dstP), sizeof(char) * (srcLen + 1)); | |||
| 656 | if (!envP->fault_occurred) { | |||
| 657 | char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP)((char*) xmlrpc_mem_block_contents(dstP)); | |||
| 658 | ||||
| 659 | memcpy(contents, src, srcLen); | |||
| 660 | contents[srcLen] = '\0'; | |||
| 661 | } | |||
| 662 | } | |||
| 663 | ||||
| 664 | ||||
| 665 | ||||
| 666 | enum crTreatment { CR_IS_LINEDELIM, CR_IS_CHAR }; | |||
| 667 | ||||
| 668 | static xmlrpc_value * | |||
| 669 | stringNew(xmlrpc_env * const envP, | |||
| 670 | size_t const length, | |||
| 671 | const char * const value, | |||
| 672 | enum crTreatment const crTreatment) { | |||
| 673 | ||||
| 674 | xmlrpc_value * valP; | |||
| 675 | ||||
| 676 | xmlrpc_validate_utf8(envP, value, length); | |||
| 677 | ||||
| 678 | if (!envP->fault_occurred) { | |||
| ||||
| 679 | xmlrpc_createXmlrpcValue(envP, &valP); | |||
| 680 | ||||
| 681 | if (!envP->fault_occurred) { | |||
| 682 | valP->_type = XMLRPC_TYPE_STRING; | |||
| 683 | valP->_wcs_block = NULL((void*)0); | |||
| 684 | ||||
| 685 | /* Note that copyLines() works for strings with no CRs, but | |||
| 686 | it's slower. | |||
| 687 | */ | |||
| 688 | if (memchr(value, '\r', length) && crTreatment == CR_IS_LINEDELIM) | |||
| 689 | copyLines(envP, value, length, &valP->_block); | |||
| 690 | else | |||
| 691 | copySimple(envP, value, length, &valP->_block); | |||
| 692 | ||||
| 693 | if (envP->fault_occurred) | |||
| 694 | free(valP); | |||
| 695 | } | |||
| 696 | } | |||
| 697 | return valP; | |||
| 698 | } | |||
| 699 | ||||
| 700 | ||||
| 701 | ||||
| 702 | xmlrpc_value * | |||
| 703 | xmlrpc_string_new_lp(xmlrpc_env * const envP, | |||
| 704 | size_t const length, | |||
| 705 | const char * const value) { | |||
| 706 | ||||
| 707 | return stringNew(envP, length, value, CR_IS_LINEDELIM); | |||
| 708 | } | |||
| 709 | ||||
| 710 | ||||
| 711 | ||||
| 712 | xmlrpc_value * | |||
| 713 | xmlrpc_string_new_lp_cr(xmlrpc_env * const envP, | |||
| 714 | size_t const length, | |||
| 715 | const char * const value) { | |||
| 716 | ||||
| 717 | return stringNew(envP, length, value, CR_IS_CHAR); | |||
| 718 | } | |||
| 719 | ||||
| 720 | ||||
| 721 | ||||
| 722 | xmlrpc_value * | |||
| 723 | xmlrpc_string_new(xmlrpc_env * const envP, | |||
| 724 | const char * const value) { | |||
| 725 | ||||
| 726 | return stringNew(envP, strlen(value), value, CR_IS_LINEDELIM); | |||
| 727 | } | |||
| 728 | ||||
| 729 | ||||
| 730 | ||||
| 731 | xmlrpc_value * | |||
| 732 | xmlrpc_string_new_cr(xmlrpc_env * const envP, | |||
| 733 | const char * const value) { | |||
| 734 | ||||
| 735 | return stringNew(envP, strlen(value), value, CR_IS_CHAR); | |||
| 736 | } | |||
| 737 | ||||
| 738 | ||||
| 739 | ||||
| 740 | xmlrpc_value * | |||
| 741 | xmlrpc_string_new_va(xmlrpc_env * const envP, | |||
| 742 | const char * const format, | |||
| 743 | va_list args) { | |||
| 744 | ||||
| 745 | const char * formattedString; | |||
| 746 | xmlrpc_value * retvalP; | |||
| 747 | ||||
| 748 | 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_string.c", 748); while (0); | |||
| 749 | XMLRPC_ASSERT(format != NULL)do if (!(format != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_string.c" , 749); while (0); | |||
| 750 | ||||
| 751 | xmlrpc_vasprintf(&formattedString, format, args); | |||
| 752 | ||||
| 753 | if (xmlrpc_strnomem(formattedString)) { | |||
| 754 | xmlrpc_faultf(envP, "Out of memory building formatted string"); | |||
| 755 | retvalP = NULL((void*)0); /* defeat compiler warning */ | |||
| 756 | } else | |||
| 757 | retvalP = xmlrpc_string_new(envP, formattedString); | |||
| 758 | ||||
| 759 | xmlrpc_strfree(formattedString); | |||
| 760 | ||||
| 761 | return retvalP; | |||
| 762 | } | |||
| 763 | ||||
| 764 | ||||
| 765 | ||||
| 766 | xmlrpc_value * | |||
| 767 | xmlrpc_string_new_f(xmlrpc_env * const envP, | |||
| 768 | const char * const format, | |||
| 769 | ...) { | |||
| 770 | ||||
| 771 | va_list args; | |||
| 772 | xmlrpc_value * retval; | |||
| 773 | ||||
| 774 | va_start(args, format)__builtin_va_start(args, format); | |||
| 775 | ||||
| 776 | retval = xmlrpc_string_new_va(envP, format, args); | |||
| ||||
| 777 | ||||
| 778 | va_end(args)__builtin_va_end(args); | |||
| 779 | ||||
| 780 | return retval; | |||
| 781 | } | |||
| 782 | ||||
| 783 | ||||
| 784 | ||||
| 785 | #if HAVE_UNICODE_WCHAR1 | |||
| 786 | ||||
| 787 | static xmlrpc_value * | |||
| 788 | stringWNew(xmlrpc_env * const envP, | |||
| 789 | size_t const length, | |||
| 790 | const wchar_t * const value, | |||
| 791 | enum crTreatment const crTreatment) { | |||
| 792 | ||||
| 793 | xmlrpc_value * valP; | |||
| 794 | xmlrpc_mem_block * utf8P; | |||
| 795 | ||||
| 796 | valP = NULL((void*)0); /* defeat compiler warning */ | |||
| 797 | ||||
| 798 | utf8P = xmlrpc_wcs_to_utf8(envP, value, length); | |||
| 799 | if (!envP->fault_occurred) { | |||
| 800 | char * const utf8_value = XMLRPC_MEMBLOCK_CONTENTS(char, utf8P)((char*) xmlrpc_mem_block_contents(utf8P)); | |||
| 801 | size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8P)(xmlrpc_mem_block_size(utf8P) / sizeof(char)); | |||
| 802 | ||||
| 803 | if (!envP->fault_occurred) { | |||
| 804 | valP = stringNew(envP, utf8_len, utf8_value, crTreatment); | |||
| 805 | ||||
| 806 | XMLRPC_MEMBLOCK_FREE(char, utf8P)xmlrpc_mem_block_free(utf8P); | |||
| 807 | } | |||
| 808 | } | |||
| 809 | return valP; | |||
| 810 | } | |||
| 811 | ||||
| 812 | ||||
| 813 | ||||
| 814 | xmlrpc_value * | |||
| 815 | xmlrpc_string_w_new_lp(xmlrpc_env * const envP, | |||
| 816 | size_t const length, | |||
| 817 | const wchar_t * const value) { | |||
| 818 | ||||
| 819 | return stringWNew(envP, length, value, CR_IS_LINEDELIM); | |||
| 820 | } | |||
| 821 | ||||
| 822 | ||||
| 823 | ||||
| 824 | ||||
| 825 | xmlrpc_value * | |||
| 826 | xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP, | |||
| 827 | size_t const length, | |||
| 828 | const wchar_t * const value) { | |||
| 829 | ||||
| 830 | return stringWNew(envP, length, value, CR_IS_CHAR); | |||
| 831 | } | |||
| 832 | ||||
| 833 | ||||
| 834 | ||||
| 835 | ||||
| 836 | xmlrpc_value * | |||
| 837 | xmlrpc_string_w_new(xmlrpc_env * const envP, | |||
| 838 | const wchar_t * const value) { | |||
| 839 | ||||
| 840 | return stringWNew(envP, wcslen(value), value, CR_IS_LINEDELIM); | |||
| 841 | } | |||
| 842 | ||||
| 843 | ||||
| 844 | ||||
| 845 | xmlrpc_value * | |||
| 846 | xmlrpc_string_w_new_cr(xmlrpc_env * const envP, | |||
| 847 | const wchar_t * const value) { | |||
| 848 | ||||
| 849 | return stringWNew(envP, wcslen(value), value, CR_IS_CHAR); | |||
| 850 | } | |||
| 851 | ||||
| 852 | #endif /* HAVE_UNICODE_WCHAR */ |