2 * string.c : an XML string utilities module
4 * This module provides various utility functions for manipulating
5 * the xmlChar* type. All functions named xmlStr* have been moved here
6 * from the parser.c file (their original home).
8 * See Copyright for the status of this software.
10 * UTF8 string routines from:
11 * William Brack <wbrack@mmm.com.hk>
22 #include <libxml/xmlmemory.h>
23 #include <libxml/parserInternals.h>
24 #include <libxml/xmlstring.h>
26 /************************************************************************
28 * Commodity functions to handle xmlChars *
30 ************************************************************************/
34 * @cur: the input xmlChar *
35 * @len: the len of @cur
37 * a strndup for array of xmlChar's
39 * Returns a new xmlChar * or NULL
42 xmlStrndup(const xmlChar
*cur
, int len
) {
45 if ((cur
== NULL
) || (len
< 0)) return(NULL
);
46 ret
= (xmlChar
*) xmlMallocAtomic(((size_t) len
+ 1) * sizeof(xmlChar
));
48 xmlErrMemory(NULL
, NULL
);
51 memcpy(ret
, cur
, len
* sizeof(xmlChar
));
58 * @cur: the input xmlChar *
60 * a strdup for array of xmlChar's. Since they are supposed to be
61 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
62 * a termination mark of '0'.
64 * Returns a new xmlChar * or NULL
67 xmlStrdup(const xmlChar
*cur
) {
68 const xmlChar
*p
= cur
;
70 if (cur
== NULL
) return(NULL
);
71 while (*p
!= 0) p
++; /* non input consuming */
72 return(xmlStrndup(cur
, p
- cur
));
77 * @cur: the input char *
78 * @len: the len of @cur
80 * a strndup for char's to xmlChar's
82 * Returns a new xmlChar * or NULL
86 xmlCharStrndup(const char *cur
, int len
) {
90 if ((cur
== NULL
) || (len
< 0)) return(NULL
);
91 ret
= (xmlChar
*) xmlMallocAtomic(((size_t) len
+ 1) * sizeof(xmlChar
));
93 xmlErrMemory(NULL
, NULL
);
96 for (i
= 0;i
< len
;i
++) {
97 ret
[i
] = (xmlChar
) cur
[i
];
98 if (ret
[i
] == 0) return(ret
);
106 * @cur: the input char *
108 * a strdup for char's to xmlChar's
110 * Returns a new xmlChar * or NULL
114 xmlCharStrdup(const char *cur
) {
117 if (cur
== NULL
) return(NULL
);
118 while (*p
!= '\0') p
++; /* non input consuming */
119 return(xmlCharStrndup(cur
, p
- cur
));
124 * @str1: the first xmlChar *
125 * @str2: the second xmlChar *
127 * a strcmp for xmlChar's
129 * Returns the integer result of the comparison
133 xmlStrcmp(const xmlChar
*str1
, const xmlChar
*str2
) {
134 if (str1
== str2
) return(0);
135 if (str1
== NULL
) return(-1);
136 if (str2
== NULL
) return(1);
137 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
138 return(strcmp((const char *)str1
, (const char *)str2
));
141 int tmp
= *str1
++ - *str2
;
142 if (tmp
!= 0) return(tmp
);
143 } while (*str2
++ != 0);
150 * @str1: the first xmlChar *
151 * @str2: the second xmlChar *
153 * Check if both strings are equal of have same content.
154 * Should be a bit more readable and faster than xmlStrcmp()
156 * Returns 1 if they are equal, 0 if they are different
160 xmlStrEqual(const xmlChar
*str1
, const xmlChar
*str2
) {
161 if (str1
== str2
) return(1);
162 if (str1
== NULL
) return(0);
163 if (str2
== NULL
) return(0);
164 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
165 return(strcmp((const char *)str1
, (const char *)str2
) == 0);
168 if (*str1
++ != *str2
) return(0);
176 * @pref: the prefix of the QName
177 * @name: the localname of the QName
178 * @str: the second xmlChar *
180 * Check if a QName is Equal to a given string
182 * Returns 1 if they are equal, 0 if they are different
186 xmlStrQEqual(const xmlChar
*pref
, const xmlChar
*name
, const xmlChar
*str
) {
187 if (pref
== NULL
) return(xmlStrEqual(name
, str
));
188 if (name
== NULL
) return(0);
189 if (str
== NULL
) return(0);
192 if (*pref
++ != *str
) return(0);
193 } while ((*str
++) && (*pref
));
194 if (*str
++ != ':') return(0);
196 if (*name
++ != *str
) return(0);
203 * @str1: the first xmlChar *
204 * @str2: the second xmlChar *
205 * @len: the max comparison length
207 * a strncmp for xmlChar's
209 * Returns the integer result of the comparison
213 xmlStrncmp(const xmlChar
*str1
, const xmlChar
*str2
, int len
) {
214 if (len
<= 0) return(0);
215 if (str1
== str2
) return(0);
216 if (str1
== NULL
) return(-1);
217 if (str2
== NULL
) return(1);
218 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
219 return(strncmp((const char *)str1
, (const char *)str2
, len
));
222 int tmp
= *str1
++ - *str2
;
223 if (tmp
!= 0 || --len
== 0) return(tmp
);
224 } while (*str2
++ != 0);
229 static const xmlChar casemap
[256] = {
230 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
231 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
232 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
233 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
234 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
235 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
236 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
237 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
238 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
239 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
240 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
241 0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
242 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
243 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
244 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
245 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
246 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
247 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
248 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
249 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
250 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
251 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
252 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
253 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
254 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
255 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
256 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
257 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
258 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
259 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
260 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
261 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
266 * @str1: the first xmlChar *
267 * @str2: the second xmlChar *
269 * a strcasecmp for xmlChar's
271 * Returns the integer result of the comparison
275 xmlStrcasecmp(const xmlChar
*str1
, const xmlChar
*str2
) {
278 if (str1
== str2
) return(0);
279 if (str1
== NULL
) return(-1);
280 if (str2
== NULL
) return(1);
282 tmp
= casemap
[*str1
++] - casemap
[*str2
];
283 if (tmp
!= 0) return(tmp
);
284 } while (*str2
++ != 0);
290 * @str1: the first xmlChar *
291 * @str2: the second xmlChar *
292 * @len: the max comparison length
294 * a strncasecmp for xmlChar's
296 * Returns the integer result of the comparison
300 xmlStrncasecmp(const xmlChar
*str1
, const xmlChar
*str2
, int len
) {
303 if (len
<= 0) return(0);
304 if (str1
== str2
) return(0);
305 if (str1
== NULL
) return(-1);
306 if (str2
== NULL
) return(1);
308 tmp
= casemap
[*str1
++] - casemap
[*str2
];
309 if (tmp
!= 0 || --len
== 0) return(tmp
);
310 } while (*str2
++ != 0);
316 * @str: the xmlChar * array
317 * @val: the xmlChar to search
319 * a strchr for xmlChar's
321 * Returns the xmlChar * for the first occurrence or NULL.
325 xmlStrchr(const xmlChar
*str
, xmlChar val
) {
326 if (str
== NULL
) return(NULL
);
327 while (*str
!= 0) { /* non input consuming */
328 if (*str
== val
) return((xmlChar
*) str
);
336 * @str: the xmlChar * array (haystack)
337 * @val: the xmlChar to search (needle)
339 * a strstr for xmlChar's
341 * Returns the xmlChar * for the first occurrence or NULL.
345 xmlStrstr(const xmlChar
*str
, const xmlChar
*val
) {
348 if (str
== NULL
) return(NULL
);
349 if (val
== NULL
) return(NULL
);
352 if (n
== 0) return(str
);
353 while (*str
!= 0) { /* non input consuming */
355 if (!xmlStrncmp(str
, val
, n
)) return((const xmlChar
*) str
);
364 * @str: the xmlChar * array (haystack)
365 * @val: the xmlChar to search (needle)
367 * a case-ignoring strstr for xmlChar's
369 * Returns the xmlChar * for the first occurrence or NULL.
373 xmlStrcasestr(const xmlChar
*str
, const xmlChar
*val
) {
376 if (str
== NULL
) return(NULL
);
377 if (val
== NULL
) return(NULL
);
380 if (n
== 0) return(str
);
381 while (*str
!= 0) { /* non input consuming */
382 if (casemap
[*str
] == casemap
[*val
])
383 if (!xmlStrncasecmp(str
, val
, n
)) return(str
);
391 * @str: the xmlChar * array (haystack)
392 * @start: the index of the first char (zero based)
393 * @len: the length of the substring
395 * Extract a substring of a given string
397 * Returns the xmlChar * for the first occurrence or NULL.
401 xmlStrsub(const xmlChar
*str
, int start
, int len
) {
404 if (str
== NULL
) return(NULL
);
405 if (start
< 0) return(NULL
);
406 if (len
< 0) return(NULL
);
408 for (i
= 0;i
< start
;i
++) {
409 if (*str
== 0) return(NULL
);
412 if (*str
== 0) return(NULL
);
413 return(xmlStrndup(str
, len
));
418 * @str: the xmlChar * array
420 * length of a xmlChar's string
422 * Returns the number of xmlChar contained in the ARRAY.
426 xmlStrlen(const xmlChar
*str
) {
429 if (str
== NULL
) return(0);
430 while (*str
!= 0) { /* non input consuming */
434 return(len
> INT_MAX
? 0 : len
);
439 * @cur: the original xmlChar * array
440 * @add: the xmlChar * array added
441 * @len: the length of @add
443 * a strncat for array of xmlChar's, it will extend @cur with the len
444 * first bytes of @add. Note that if @len < 0 then this is an API error
445 * and NULL will be returned.
447 * Returns a new xmlChar *, the original @cur is reallocated and should
452 xmlStrncat(xmlChar
*cur
, const xmlChar
*add
, int len
) {
456 if ((add
== NULL
) || (len
== 0))
461 return(xmlStrndup(add
, len
));
463 size
= xmlStrlen(cur
);
464 if ((size
< 0) || (size
> INT_MAX
- len
))
466 ret
= (xmlChar
*) xmlRealloc(cur
, ((size_t) size
+ len
+ 1) * sizeof(xmlChar
));
468 xmlErrMemory(NULL
, NULL
);
471 memcpy(&ret
[size
], add
, len
* sizeof(xmlChar
));
478 * @str1: first xmlChar string
479 * @str2: second xmlChar string
480 * @len: the len of @str2 or < 0
482 * same as xmlStrncat, but creates a new string. The original
483 * two strings are not freed. If @len is < 0 then the length
484 * will be calculated automatically.
486 * Returns a new xmlChar * or NULL
489 xmlStrncatNew(const xmlChar
*str1
, const xmlChar
*str2
, int len
) {
494 len
= xmlStrlen(str2
);
498 if ((str2
== NULL
) || (len
== 0))
499 return(xmlStrdup(str1
));
501 return(xmlStrndup(str2
, len
));
503 size
= xmlStrlen(str1
);
504 if ((size
< 0) || (size
> INT_MAX
- len
))
506 ret
= (xmlChar
*) xmlMalloc(((size_t) size
+ len
+ 1) * sizeof(xmlChar
));
508 xmlErrMemory(NULL
, NULL
);
509 return(xmlStrndup(str1
, size
));
511 memcpy(ret
, str1
, size
* sizeof(xmlChar
));
512 memcpy(&ret
[size
], str2
, len
* sizeof(xmlChar
));
519 * @cur: the original xmlChar * array
520 * @add: the xmlChar * array added
522 * a strcat for array of xmlChar's. Since they are supposed to be
523 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
524 * a termination mark of '0'.
526 * Returns a new xmlChar * containing the concatenated string. The original
527 * @cur is reallocated and should not be freed.
530 xmlStrcat(xmlChar
*cur
, const xmlChar
*add
) {
531 const xmlChar
*p
= add
;
533 if (add
== NULL
) return(cur
);
535 return(xmlStrdup(add
));
537 while (*p
!= 0) p
++; /* non input consuming */
538 return(xmlStrncat(cur
, add
, p
- add
));
543 * @buf: the result buffer.
544 * @len: the result buffer length.
545 * @msg: the message with printf formatting.
546 * @...: extra parameters for the message.
548 * Formats @msg and places result into @buf.
550 * Returns the number of characters written to @buf or -1 if an error occurs.
553 xmlStrPrintf(xmlChar
*buf
, int len
, const char *msg
, ...) {
557 if((buf
== NULL
) || (msg
== NULL
)) {
562 ret
= vsnprintf((char *) buf
, len
, (const char *) msg
, args
);
564 buf
[len
- 1] = 0; /* be safe ! */
571 * @buf: the result buffer.
572 * @len: the result buffer length.
573 * @msg: the message with printf formatting.
574 * @ap: extra parameters for the message.
576 * Formats @msg and places result into @buf.
578 * Returns the number of characters written to @buf or -1 if an error occurs.
581 xmlStrVPrintf(xmlChar
*buf
, int len
, const char *msg
, va_list ap
) {
584 if((buf
== NULL
) || (msg
== NULL
)) {
588 ret
= vsnprintf((char *) buf
, len
, (const char *) msg
, ap
);
589 buf
[len
- 1] = 0; /* be safe ! */
594 /************************************************************************
596 * Generic UTF8 handling routines *
598 * From rfc2044: encoding of the Unicode values on UTF-8: *
600 * UCS-4 range (hex.) UTF-8 octet sequence (binary) *
601 * 0000 0000-0000 007F 0xxxxxxx *
602 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx *
603 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx *
605 * I hope we won't use values > 0xFFFF anytime soon ! *
607 ************************************************************************/
612 * @utf: pointer to the UTF8 character
614 * calculates the internal size of a UTF8 character
616 * returns the numbers of bytes in the character, -1 on format error
619 xmlUTF8Size(const xmlChar
*utf
) {
627 /* check valid UTF8 character */
630 /* determine number of bytes in char */
632 for (mask
=0x20; mask
!= 0; mask
>>=1) {
642 * @utf1: pointer to first UTF8 char
643 * @utf2: pointer to second UTF8 char
645 * compares the two UCS4 values
647 * returns result of the compare as with xmlStrncmp
650 xmlUTF8Charcmp(const xmlChar
*utf1
, const xmlChar
*utf2
) {
657 return xmlStrncmp(utf1
, utf2
, xmlUTF8Size(utf1
));
662 * @utf: a sequence of UTF-8 encoded bytes
664 * compute the length of an UTF8 string, it doesn't do a full UTF8
665 * checking of the content of the string.
667 * Returns the number of characters in the string or -1 in case of error
670 xmlUTF8Strlen(const xmlChar
*utf
) {
678 if ((utf
[1] & 0xc0) != 0x80)
680 if ((utf
[0] & 0xe0) == 0xe0) {
681 if ((utf
[2] & 0xc0) != 0x80)
683 if ((utf
[0] & 0xf0) == 0xf0) {
684 if ((utf
[0] & 0xf8) != 0xf0 || (utf
[3] & 0xc0) != 0x80)
698 return(ret
> INT_MAX
? 0 : ret
);
703 * @utf: a sequence of UTF-8 encoded bytes
704 * @len: a pointer to the minimum number of bytes present in
705 * the sequence. This is used to assure the next character
706 * is completely contained within the sequence.
708 * Read the first UTF8 character from @utf
710 * Returns the char value or -1 in case of error, and sets *len to
711 * the actual number of bytes consumed (0 in case of error)
714 xmlGetUTF8Char(const unsigned char *utf
, int *len
) {
728 if ((utf
[1] & 0xc0) != 0x80)
730 if ((c
& 0xe0) == 0xe0) {
733 if ((utf
[2] & 0xc0) != 0x80)
735 if ((c
& 0xf0) == 0xf0) {
738 if ((c
& 0xf8) != 0xf0 || (utf
[3] & 0xc0) != 0x80)
742 c
= (utf
[0] & 0x7) << 18;
743 c
|= (utf
[1] & 0x3f) << 12;
744 c
|= (utf
[2] & 0x3f) << 6;
749 c
= (utf
[0] & 0xf) << 12;
750 c
|= (utf
[1] & 0x3f) << 6;
756 c
= (utf
[0] & 0x1f) << 6;
773 * @utf: Pointer to putative UTF-8 encoded string.
775 * Checks @utf for being valid UTF-8. @utf is assumed to be
776 * null-terminated. This function is not super-strict, as it will
777 * allow longer UTF-8 sequences than necessary. Note that Java is
778 * capable of producing these sequences if provoked. Also note, this
779 * routine checks for the 4-byte maximum size, but does not check for
780 * 0x10ffff maximum value.
782 * Return value: true if @utf is valid.
785 xmlCheckUTF8(const unsigned char *utf
)
793 * utf is a string of 1, 2, 3 or 4 bytes. The valid strings
794 * are as follows (in "bit format"):
795 * 0xxxxxxx valid 1-byte
796 * 110xxxxx 10xxxxxx valid 2-byte
797 * 1110xxxx 10xxxxxx 10xxxxxx valid 3-byte
798 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx valid 4-byte
800 while ((c
= utf
[0])) { /* string is 0-terminated */
802 if ((c
& 0x80) == 0x00) { /* 1-byte code, starts with 10 */
804 } else if ((c
& 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
805 if ((utf
[1] & 0xc0 ) != 0x80)
808 } else if ((c
& 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
809 if (((utf
[1] & 0xc0) != 0x80) ||
810 ((utf
[2] & 0xc0) != 0x80))
813 } else if ((c
& 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
814 if (((utf
[1] & 0xc0) != 0x80) ||
815 ((utf
[2] & 0xc0) != 0x80) ||
816 ((utf
[3] & 0xc0) != 0x80))
819 } else /* unknown encoding */
828 * @utf: a sequence of UTF-8 encoded bytes
829 * @len: the number of characters in the array
831 * storage size of an UTF8 string
832 * the behaviour is not guaranteed if the input string is not UTF-8
834 * Returns the storage size of
835 * the first 'len' characters of ARRAY
839 xmlUTF8Strsize(const xmlChar
*utf
, int len
) {
840 const xmlChar
*ptr
=utf
;
853 if ( (ch
= *ptr
++) & 0x80)
854 while ((ch
<<=1) & 0x80 ) {
855 if (*ptr
== 0) break;
860 return (ret
> INT_MAX
? 0 : ret
);
866 * @utf: the input UTF8 *
867 * @len: the len of @utf (in chars)
869 * a strndup for array of UTF8's
871 * Returns a new UTF8 * or NULL
874 xmlUTF8Strndup(const xmlChar
*utf
, int len
) {
878 if ((utf
== NULL
) || (len
< 0)) return(NULL
);
879 i
= xmlUTF8Strsize(utf
, len
);
880 ret
= (xmlChar
*) xmlMallocAtomic(((size_t) i
+ 1) * sizeof(xmlChar
));
884 memcpy(ret
, utf
, i
* sizeof(xmlChar
));
891 * @utf: the input UTF8 *
892 * @pos: the position of the desired UTF8 char (in chars)
894 * a function to provide the equivalent of fetching a
895 * character from a string array
897 * Returns a pointer to the UTF8 character or NULL
900 xmlUTF8Strpos(const xmlChar
*utf
, int pos
) {
903 if (utf
== NULL
) return(NULL
);
907 if ((ch
=*utf
++) == 0) return(NULL
);
909 /* if not simple ascii, verify proper format */
910 if ( (ch
& 0xc0) != 0xc0 )
912 /* then skip over remaining bytes for this char */
913 while ( (ch
<<= 1) & 0x80 )
914 if ( (*utf
++ & 0xc0) != 0x80 )
918 return((xmlChar
*)utf
);
923 * @utf: the input UTF8 *
924 * @utfchar: the UTF8 character to be found
926 * a function to provide the relative location of a UTF8 char
928 * Returns the relative character position of the desired char
932 xmlUTF8Strloc(const xmlChar
*utf
, const xmlChar
*utfchar
) {
937 if (utf
==NULL
|| utfchar
==NULL
) return -1;
938 size
= xmlUTF8Strsize(utfchar
, 1);
939 for(i
=0; (ch
=*utf
) != 0; i
++) {
940 if (xmlStrncmp(utf
, utfchar
, size
)==0)
941 return(i
> INT_MAX
? 0 : i
);
944 /* if not simple ascii, verify proper format */
945 if ( (ch
& 0xc0) != 0xc0 )
947 /* then skip over remaining bytes for this char */
948 while ( (ch
<<= 1) & 0x80 )
949 if ( (*utf
++ & 0xc0) != 0x80 )
958 * @utf: a sequence of UTF-8 encoded bytes
959 * @start: relative pos of first char
960 * @len: total number to copy
962 * Create a substring from a given UTF-8 string
963 * Note: positions are given in units of UTF-8 chars
965 * Returns a pointer to a newly created string
966 * or NULL if any problem
970 xmlUTF8Strsub(const xmlChar
*utf
, int start
, int len
) {
974 if (utf
== NULL
) return(NULL
);
975 if (start
< 0) return(NULL
);
976 if (len
< 0) return(NULL
);
979 * Skip over any leading chars
981 for (i
= 0;i
< start
;i
++) {
982 if ((ch
=*utf
++) == 0) return(NULL
);
984 /* if not simple ascii, verify proper format */
985 if ( (ch
& 0xc0) != 0xc0 )
987 /* then skip over remaining bytes for this char */
988 while ( (ch
<<= 1) & 0x80 )
989 if ( (*utf
++ & 0xc0) != 0x80 )
994 return(xmlUTF8Strndup(utf
, len
));
998 * xmlEscapeFormatString:
999 * @msg: a pointer to the string in which to escape '%' characters.
1000 * Must be a heap-allocated buffer created by libxml2 that may be
1001 * returned, or that may be freed and replaced.
1003 * Replaces the string pointed to by 'msg' with an escaped string.
1004 * Returns the same string with all '%' characters escaped.
1007 xmlEscapeFormatString(xmlChar
**msg
)
1009 xmlChar
*msgPtr
= NULL
;
1010 xmlChar
*result
= NULL
;
1011 xmlChar
*resultPtr
= NULL
;
1014 size_t resultLen
= 0;
1019 for (msgPtr
= *msg
; *msgPtr
!= '\0'; ++msgPtr
) {
1028 if ((count
> INT_MAX
) || (msgLen
> INT_MAX
- count
))
1030 resultLen
= msgLen
+ count
+ 1;
1031 result
= (xmlChar
*) xmlMallocAtomic(resultLen
* sizeof(xmlChar
));
1032 if (result
== NULL
) {
1033 /* Clear *msg to prevent format string vulnerabilities in
1034 out-of-memory situations. */
1037 xmlErrMemory(NULL
, NULL
);
1041 for (msgPtr
= *msg
, resultPtr
= result
; *msgPtr
!= '\0'; ++msgPtr
, ++resultPtr
) {
1042 *resultPtr
= *msgPtr
;
1044 *(++resultPtr
) = '%';
1046 result
[resultLen
- 1] = '\0';
1054 #define bottom_xmlstring
1055 #include "elfgcchack.h"