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 */ |