Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * buf.c: memory buffers for libxml2  | 
3  |  |  *  | 
4  |  |  * new buffer structures and entry points to simplify the maintenance  | 
5  |  |  * of libxml2 and ensure we keep good control over memory allocations  | 
6  |  |  * and stay 64 bits clean.  | 
7  |  |  * The new entry point use the xmlBufPtr opaque structure and  | 
8  |  |  * xmlBuf...() counterparts to the old xmlBuf...() functions  | 
9  |  |  *  | 
10  |  |  * See Copyright for the status of this software.  | 
11  |  |  *  | 
12  |  |  * daniel@veillard.com  | 
13  |  |  */  | 
14  |  |  | 
15  |  | #define IN_LIBXML  | 
16  |  | #include "libxml.h"  | 
17  |  |  | 
18  |  | #include <string.h> /* for memset() only ! */  | 
19  |  | #include <limits.h>  | 
20  |  | #include <ctype.h>  | 
21  |  | #include <stdlib.h>  | 
22  |  |  | 
23  |  | #include <libxml/tree.h>  | 
24  |  | #include <libxml/globals.h>  | 
25  |  | #include <libxml/tree.h>  | 
26  |  | #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */  | 
27  |  |  | 
28  |  | #include "private/buf.h"  | 
29  |  | #include "private/error.h"  | 
30  |  |  | 
31  |  | #ifndef SIZE_MAX  | 
32  | 423k  | #define SIZE_MAX ((size_t) -1)  | 
33  |  | #endif  | 
34  |  |  | 
35  |  | #define WITH_BUFFER_COMPAT  | 
36  |  |  | 
37  |  | /**  | 
38  |  |  * xmlBuf:  | 
39  |  |  *  | 
40  |  |  * A buffer structure. The base of the structure is somehow compatible  | 
41  |  |  * with struct _xmlBuffer to limit risks on application which accessed  | 
42  |  |  * directly the input->buf->buffer structures.  | 
43  |  |  */  | 
44  |  |  | 
45  |  | struct _xmlBuf { | 
46  |  |     xmlChar *content;   /* The buffer content UTF8 */  | 
47  |  |     unsigned int compat_use;    /* for binary compatibility */  | 
48  |  |     unsigned int compat_size;   /* for binary compatibility */  | 
49  |  |     xmlBufferAllocationScheme alloc; /* The realloc method */  | 
50  |  |     xmlChar *contentIO;   /* in IO mode we may have a different base */  | 
51  |  |     size_t use;           /* The buffer size used */  | 
52  |  |     size_t size;    /* The buffer size */  | 
53  |  |     xmlBufferPtr buffer;        /* wrapper for an old buffer */  | 
54  |  |     int error;                  /* an error code if a failure occurred */  | 
55  |  | };  | 
56  |  |  | 
57  |  | #ifdef WITH_BUFFER_COMPAT  | 
58  |  | /*  | 
59  |  |  * Macro for compatibility with xmlBuffer to be used after an xmlBuf  | 
60  |  |  * is updated. This makes sure the compat fields are updated too.  | 
61  |  |  */  | 
62  |  | #define UPDATE_COMPAT(buf)            \  | 
63  | 3.87M  |      if (buf->size < INT_MAX) buf->compat_size = buf->size; \  | 
64  | 3.87M  |      else buf->compat_size = INT_MAX;         \  | 
65  | 3.87M  |      if (buf->use < INT_MAX) buf->compat_use = buf->use; \  | 
66  | 3.87M  |      else buf->compat_use = INT_MAX;  | 
67  |  |  | 
68  |  | /*  | 
69  |  |  * Macro for compatibility with xmlBuffer to be used in all the xmlBuf  | 
70  |  |  * entry points, it checks that the compat fields have not been modified  | 
71  |  |  * by direct call to xmlBuffer function from code compiled before 2.9.0 .  | 
72  |  |  */  | 
73  |  | #define CHECK_COMPAT(buf)           \  | 
74  | 50.1M  |      if (buf->size != (size_t) buf->compat_size)     \  | 
75  | 50.1M  |          if (buf->compat_size < INT_MAX)       \  | 
76  | 0  |        buf->size = buf->compat_size;       \  | 
77  | 50.1M  |      if (buf->use != (size_t) buf->compat_use)       \  | 
78  | 50.1M  |          if (buf->compat_use < INT_MAX)         \  | 
79  | 0  |        buf->use = buf->compat_use;  | 
80  |  |  | 
81  |  | #else /* ! WITH_BUFFER_COMPAT */  | 
82  |  | #define UPDATE_COMPAT(buf)  | 
83  |  | #define CHECK_COMPAT(buf)  | 
84  |  | #endif /* WITH_BUFFER_COMPAT */  | 
85  |  |  | 
86  |  | /**  | 
87  |  |  * xmlBufMemoryError:  | 
88  |  |  * @extra:  extra information  | 
89  |  |  *  | 
90  |  |  * Handle an out of memory condition  | 
91  |  |  * To be improved...  | 
92  |  |  */  | 
93  |  | static void  | 
94  |  | xmlBufMemoryError(xmlBufPtr buf, const char *extra)  | 
95  | 0  | { | 
96  | 0  |     __xmlSimpleError(XML_FROM_BUFFER, XML_ERR_NO_MEMORY, NULL, NULL, extra);  | 
97  | 0  |     if ((buf) && (buf->error == 0))  | 
98  | 0  |         buf->error = XML_ERR_NO_MEMORY;  | 
99  | 0  | }  | 
100  |  |  | 
101  |  | /**  | 
102  |  |  * xmlBufOverflowError:  | 
103  |  |  * @extra:  extra information  | 
104  |  |  *  | 
105  |  |  * Handle a buffer overflow error  | 
106  |  |  * To be improved...  | 
107  |  |  */  | 
108  |  | static void  | 
109  |  | xmlBufOverflowError(xmlBufPtr buf, const char *extra)  | 
110  | 0  | { | 
111  | 0  |     __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra);  | 
112  | 0  |     if ((buf) && (buf->error == 0))  | 
113  | 0  |         buf->error = XML_BUF_OVERFLOW;  | 
114  | 0  | }  | 
115  |  |  | 
116  |  |  | 
117  |  | /**  | 
118  |  |  * xmlBufCreate:  | 
119  |  |  *  | 
120  |  |  * routine to create an XML buffer.  | 
121  |  |  * returns the new structure.  | 
122  |  |  */  | 
123  |  | xmlBufPtr  | 
124  | 22.9k  | xmlBufCreate(void) { | 
125  | 22.9k  |     xmlBufPtr ret;  | 
126  |  |  | 
127  | 22.9k  |     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));  | 
128  | 22.9k  |     if (ret == NULL) { | 
129  | 0  |   xmlBufMemoryError(NULL, "creating buffer");  | 
130  | 0  |         return(NULL);  | 
131  | 0  |     }  | 
132  | 22.9k  |     ret->use = 0;  | 
133  | 22.9k  |     ret->error = 0;  | 
134  | 22.9k  |     ret->buffer = NULL;  | 
135  | 22.9k  |     ret->size = xmlDefaultBufferSize;  | 
136  | 22.9k  |     UPDATE_COMPAT(ret);  | 
137  | 22.9k  |     ret->alloc = xmlBufferAllocScheme;  | 
138  | 22.9k  |     ret->content = (xmlChar *) xmlMallocAtomic(ret->size);  | 
139  | 22.9k  |     if (ret->content == NULL) { | 
140  | 0  |   xmlBufMemoryError(ret, "creating buffer");  | 
141  | 0  |   xmlFree(ret);  | 
142  | 0  |         return(NULL);  | 
143  | 0  |     }  | 
144  | 22.9k  |     ret->content[0] = 0;  | 
145  | 22.9k  |     ret->contentIO = NULL;  | 
146  | 22.9k  |     return(ret);  | 
147  | 22.9k  | }  | 
148  |  |  | 
149  |  | /**  | 
150  |  |  * xmlBufCreateSize:  | 
151  |  |  * @size: initial size of buffer  | 
152  |  |  *  | 
153  |  |  * routine to create an XML buffer.  | 
154  |  |  * returns the new structure.  | 
155  |  |  */  | 
156  |  | xmlBufPtr  | 
157  | 226k  | xmlBufCreateSize(size_t size) { | 
158  | 226k  |     xmlBufPtr ret;  | 
159  |  |  | 
160  | 226k  |     if (size == SIZE_MAX)  | 
161  | 0  |         return(NULL);  | 
162  | 226k  |     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));  | 
163  | 226k  |     if (ret == NULL) { | 
164  | 0  |   xmlBufMemoryError(NULL, "creating buffer");  | 
165  | 0  |         return(NULL);  | 
166  | 0  |     }  | 
167  | 226k  |     ret->use = 0;  | 
168  | 226k  |     ret->error = 0;  | 
169  | 226k  |     ret->buffer = NULL;  | 
170  | 226k  |     ret->alloc = xmlBufferAllocScheme;  | 
171  | 226k  |     ret->size = (size ? size + 1 : 0);         /* +1 for ending null */  | 
172  | 226k  |     UPDATE_COMPAT(ret);  | 
173  | 226k  |     if (ret->size){ | 
174  | 159k  |         ret->content = (xmlChar *) xmlMallocAtomic(ret->size);  | 
175  | 159k  |         if (ret->content == NULL) { | 
176  | 0  |       xmlBufMemoryError(ret, "creating buffer");  | 
177  | 0  |             xmlFree(ret);  | 
178  | 0  |             return(NULL);  | 
179  | 0  |         }  | 
180  | 159k  |         ret->content[0] = 0;  | 
181  | 159k  |     } else  | 
182  | 67.7k  |   ret->content = NULL;  | 
183  | 226k  |     ret->contentIO = NULL;  | 
184  | 226k  |     return(ret);  | 
185  | 226k  | }  | 
186  |  |  | 
187  |  | /**  | 
188  |  |  * xmlBufDetach:  | 
189  |  |  * @buf:  the buffer  | 
190  |  |  *  | 
191  |  |  * Remove the string contained in a buffer and give it back to the  | 
192  |  |  * caller. The buffer is reset to an empty content.  | 
193  |  |  * This doesn't work with immutable buffers as they can't be reset.  | 
194  |  |  *  | 
195  |  |  * Returns the previous string contained by the buffer.  | 
196  |  |  */  | 
197  |  | xmlChar *  | 
198  | 70.5k  | xmlBufDetach(xmlBufPtr buf) { | 
199  | 70.5k  |     xmlChar *ret;  | 
200  |  |  | 
201  | 70.5k  |     if (buf == NULL)  | 
202  | 0  |         return(NULL);  | 
203  | 70.5k  |     if (buf->buffer != NULL)  | 
204  | 0  |         return(NULL);  | 
205  | 70.5k  |     if (buf->error)  | 
206  | 0  |         return(NULL);  | 
207  |  |  | 
208  | 70.5k  |     ret = buf->content;  | 
209  | 70.5k  |     buf->content = NULL;  | 
210  | 70.5k  |     buf->size = 0;  | 
211  | 70.5k  |     buf->use = 0;  | 
212  | 70.5k  |     UPDATE_COMPAT(buf);  | 
213  |  |  | 
214  | 70.5k  |     return ret;  | 
215  | 70.5k  | }  | 
216  |  |  | 
217  |  | /**  | 
218  |  |  * xmlBufGetAllocationScheme:  | 
219  |  |  * @buf:  the buffer  | 
220  |  |  *  | 
221  |  |  * Get the buffer allocation scheme  | 
222  |  |  *  | 
223  |  |  * Returns the scheme or -1 in case of error  | 
224  |  |  */  | 
225  |  | int  | 
226  | 0  | xmlBufGetAllocationScheme(xmlBufPtr buf) { | 
227  | 0  |     if (buf == NULL) { | 
228  |  | #ifdef DEBUG_BUFFER  | 
229  |  |         xmlGenericError(xmlGenericErrorContext,  | 
230  |  |     "xmlBufGetAllocationScheme: buf == NULL\n");  | 
231  |  | #endif  | 
232  | 0  |         return(-1);  | 
233  | 0  |     }  | 
234  | 0  |     return(buf->alloc);  | 
235  | 0  | }  | 
236  |  |  | 
237  |  | /**  | 
238  |  |  * xmlBufSetAllocationScheme:  | 
239  |  |  * @buf:  the buffer to tune  | 
240  |  |  * @scheme:  allocation scheme to use  | 
241  |  |  *  | 
242  |  |  * Sets the allocation scheme for this buffer  | 
243  |  |  *  | 
244  |  |  * returns 0 in case of success and -1 in case of failure  | 
245  |  |  */  | 
246  |  | int  | 
247  |  | xmlBufSetAllocationScheme(xmlBufPtr buf,  | 
248  | 271k  |                           xmlBufferAllocationScheme scheme) { | 
249  | 271k  |     if ((buf == NULL) || (buf->error != 0)) { | 
250  |  | #ifdef DEBUG_BUFFER  | 
251  |  |         xmlGenericError(xmlGenericErrorContext,  | 
252  |  |     "xmlBufSetAllocationScheme: buf == NULL or in error\n");  | 
253  |  | #endif  | 
254  | 0  |         return(-1);  | 
255  | 0  |     }  | 
256  | 271k  |     if (buf->alloc == XML_BUFFER_ALLOC_IO)  | 
257  | 0  |         return(-1);  | 
258  | 271k  |     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||  | 
259  | 271k  |         (scheme == XML_BUFFER_ALLOC_EXACT) ||  | 
260  | 271k  |         (scheme == XML_BUFFER_ALLOC_HYBRID) ||  | 
261  | 271k  |   (scheme == XML_BUFFER_ALLOC_BOUNDED)) { | 
262  | 271k  |   buf->alloc = scheme;  | 
263  | 271k  |         if (buf->buffer)  | 
264  | 0  |             buf->buffer->alloc = scheme;  | 
265  | 271k  |         return(0);  | 
266  | 271k  |     }  | 
267  |  |     /*  | 
268  |  |      * Switching a buffer ALLOC_IO has the side effect of initializing  | 
269  |  |      * the contentIO field with the current content  | 
270  |  |      */  | 
271  | 0  |     if (scheme == XML_BUFFER_ALLOC_IO) { | 
272  | 0  |         buf->alloc = XML_BUFFER_ALLOC_IO;  | 
273  | 0  |         buf->contentIO = buf->content;  | 
274  | 0  |     }  | 
275  | 0  |     return(-1);  | 
276  | 271k  | }  | 
277  |  |  | 
278  |  | /**  | 
279  |  |  * xmlBufFree:  | 
280  |  |  * @buf:  the buffer to free  | 
281  |  |  *  | 
282  |  |  * Frees an XML buffer. It frees both the content and the structure which  | 
283  |  |  * encapsulate it.  | 
284  |  |  */  | 
285  |  | void  | 
286  | 249k  | xmlBufFree(xmlBufPtr buf) { | 
287  | 249k  |     if (buf == NULL) { | 
288  |  | #ifdef DEBUG_BUFFER  | 
289  |  |         xmlGenericError(xmlGenericErrorContext,  | 
290  |  |     "xmlBufFree: buf == NULL\n");  | 
291  |  | #endif  | 
292  | 0  |   return;  | 
293  | 0  |     }  | 
294  |  |  | 
295  | 249k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&  | 
296  | 249k  |         (buf->contentIO != NULL)) { | 
297  | 0  |         xmlFree(buf->contentIO);  | 
298  | 249k  |     } else if (buf->content != NULL) { | 
299  | 181k  |         xmlFree(buf->content);  | 
300  | 181k  |     }  | 
301  | 249k  |     xmlFree(buf);  | 
302  | 249k  | }  | 
303  |  |  | 
304  |  | /**  | 
305  |  |  * xmlBufEmpty:  | 
306  |  |  * @buf:  the buffer  | 
307  |  |  *  | 
308  |  |  * empty a buffer.  | 
309  |  |  */  | 
310  |  | void  | 
311  | 0  | xmlBufEmpty(xmlBufPtr buf) { | 
312  | 0  |     if ((buf == NULL) || (buf->error != 0)) return;  | 
313  | 0  |     if (buf->content == NULL) return;  | 
314  | 0  |     CHECK_COMPAT(buf)  | 
315  | 0  |     buf->use = 0;  | 
316  | 0  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&  | 
317  | 0  |                (buf->contentIO != NULL)) { | 
318  | 0  |         size_t start_buf = buf->content - buf->contentIO;  | 
319  |  | 
  | 
320  | 0  |   buf->size += start_buf;  | 
321  | 0  |         buf->content = buf->contentIO;  | 
322  | 0  |         buf->content[0] = 0;  | 
323  | 0  |     } else { | 
324  | 0  |         buf->content[0] = 0;  | 
325  | 0  |     }  | 
326  | 0  |     UPDATE_COMPAT(buf)  | 
327  | 0  | }  | 
328  |  |  | 
329  |  | /**  | 
330  |  |  * xmlBufShrink:  | 
331  |  |  * @buf:  the buffer to dump  | 
332  |  |  * @len:  the number of xmlChar to remove  | 
333  |  |  *  | 
334  |  |  * Remove the beginning of an XML buffer.  | 
335  |  |  * NOTE that this routine behaviour differs from xmlBufferShrink()  | 
336  |  |  * as it will return 0 on error instead of -1 due to size_t being  | 
337  |  |  * used as the return type.  | 
338  |  |  *  | 
339  |  |  * Returns the number of byte removed or 0 in case of failure  | 
340  |  |  */  | 
341  |  | size_t  | 
342  | 423k  | xmlBufShrink(xmlBufPtr buf, size_t len) { | 
343  | 423k  |     if ((buf == NULL) || (buf->error != 0)) return(0);  | 
344  | 423k  |     CHECK_COMPAT(buf)  | 
345  | 423k  |     if (len == 0) return(0);  | 
346  | 128k  |     if (len > buf->use) return(0);  | 
347  |  |  | 
348  | 128k  |     buf->use -= len;  | 
349  | 128k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
350  |  |   /*  | 
351  |  |    * we just move the content pointer, but also make sure  | 
352  |  |    * the perceived buffer size has shrunk accordingly  | 
353  |  |    */  | 
354  | 0  |         buf->content += len;  | 
355  | 0  |   buf->size -= len;  | 
356  |  |  | 
357  |  |         /*  | 
358  |  |    * sometimes though it maybe be better to really shrink  | 
359  |  |    * on IO buffers  | 
360  |  |    */  | 
361  | 0  |   if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
362  | 0  |       size_t start_buf = buf->content - buf->contentIO;  | 
363  | 0  |       if (start_buf >= buf->size) { | 
364  | 0  |     memmove(buf->contentIO, &buf->content[0], buf->use);  | 
365  | 0  |     buf->content = buf->contentIO;  | 
366  | 0  |     buf->content[buf->use] = 0;  | 
367  | 0  |     buf->size += start_buf;  | 
368  | 0  |       }  | 
369  | 0  |   }  | 
370  | 128k  |     } else { | 
371  | 128k  |   memmove(buf->content, &buf->content[len], buf->use);  | 
372  | 128k  |   buf->content[buf->use] = 0;  | 
373  | 128k  |     }  | 
374  | 128k  |     UPDATE_COMPAT(buf)  | 
375  | 128k  |     return(len);  | 
376  | 128k  | }  | 
377  |  |  | 
378  |  | /**  | 
379  |  |  * xmlBufGrowInternal:  | 
380  |  |  * @buf:  the buffer  | 
381  |  |  * @len:  the minimum free size to allocate  | 
382  |  |  *  | 
383  |  |  * Grow the available space of an XML buffer, @len is the target value  | 
384  |  |  * Error checking should be done on buf->error since using the return  | 
385  |  |  * value doesn't work that well  | 
386  |  |  *  | 
387  |  |  * Returns 0 in case of error or the length made available otherwise  | 
388  |  |  */  | 
389  |  | static size_t  | 
390  | 12.1k  | xmlBufGrowInternal(xmlBufPtr buf, size_t len) { | 
391  | 12.1k  |     size_t size;  | 
392  | 12.1k  |     xmlChar *newbuf;  | 
393  |  |  | 
394  | 12.1k  |     if ((buf == NULL) || (buf->error != 0)) return(0);  | 
395  | 12.1k  |     CHECK_COMPAT(buf)  | 
396  |  |  | 
397  | 12.1k  |     if (len < buf->size - buf->use)  | 
398  | 129  |         return(buf->size - buf->use - 1);  | 
399  | 11.9k  |     if (len >= SIZE_MAX - buf->use) { | 
400  | 0  |         xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");  | 
401  | 0  |         return(0);  | 
402  | 0  |     }  | 
403  |  |  | 
404  | 11.9k  |     if (buf->size > (size_t) len) { | 
405  | 4.88k  |         size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2;  | 
406  | 7.11k  |     } else { | 
407  | 7.11k  |         size = buf->use + len;  | 
408  | 7.11k  |         size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100;  | 
409  | 7.11k  |     }  | 
410  |  |  | 
411  | 11.9k  |     if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { | 
412  |  |         /*  | 
413  |  |    * Used to provide parsing limits  | 
414  |  |    */  | 
415  | 0  |         if ((buf->use + len + 1 >= XML_MAX_TEXT_LENGTH) ||  | 
416  | 0  |       (buf->size >= XML_MAX_TEXT_LENGTH)) { | 
417  | 0  |       xmlBufMemoryError(buf, "buffer error: text too long\n");  | 
418  | 0  |       return(0);  | 
419  | 0  |   }  | 
420  | 0  |   if (size >= XML_MAX_TEXT_LENGTH)  | 
421  | 0  |       size = XML_MAX_TEXT_LENGTH;  | 
422  | 0  |     }  | 
423  | 11.9k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
424  | 0  |         size_t start_buf = buf->content - buf->contentIO;  | 
425  |  | 
  | 
426  | 0  |   newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);  | 
427  | 0  |   if (newbuf == NULL) { | 
428  | 0  |       xmlBufMemoryError(buf, "growing buffer");  | 
429  | 0  |       return(0);  | 
430  | 0  |   }  | 
431  | 0  |   buf->contentIO = newbuf;  | 
432  | 0  |   buf->content = newbuf + start_buf;  | 
433  | 11.9k  |     } else { | 
434  | 11.9k  |   newbuf = (xmlChar *) xmlRealloc(buf->content, size);  | 
435  | 11.9k  |   if (newbuf == NULL) { | 
436  | 0  |       xmlBufMemoryError(buf, "growing buffer");  | 
437  | 0  |       return(0);  | 
438  | 0  |   }  | 
439  | 11.9k  |   buf->content = newbuf;  | 
440  | 11.9k  |     }  | 
441  | 11.9k  |     buf->size = size;  | 
442  | 11.9k  |     UPDATE_COMPAT(buf)  | 
443  | 11.9k  |     return(buf->size - buf->use - 1);  | 
444  | 11.9k  | }  | 
445  |  |  | 
446  |  | /**  | 
447  |  |  * xmlBufGrow:  | 
448  |  |  * @buf:  the buffer  | 
449  |  |  * @len:  the minimum free size to allocate  | 
450  |  |  *  | 
451  |  |  * Grow the available space of an XML buffer, @len is the target value  | 
452  |  |  * This is been kept compatible with xmlBufferGrow() as much as possible  | 
453  |  |  *  | 
454  |  |  * Returns -1 in case of error or the length made available otherwise  | 
455  |  |  */  | 
456  |  | int  | 
457  | 12.1k  | xmlBufGrow(xmlBufPtr buf, int len) { | 
458  | 12.1k  |     size_t ret;  | 
459  |  |  | 
460  | 12.1k  |     if ((buf == NULL) || (len < 0)) return(-1);  | 
461  | 12.1k  |     if (len == 0)  | 
462  | 0  |         return(0);  | 
463  | 12.1k  |     ret = xmlBufGrowInternal(buf, len);  | 
464  | 12.1k  |     if (buf->error != 0)  | 
465  | 0  |         return(-1);  | 
466  | 12.1k  |     return(ret > INT_MAX ? INT_MAX : ret);  | 
467  | 12.1k  | }  | 
468  |  |  | 
469  |  | /**  | 
470  |  |  * xmlBufDump:  | 
471  |  |  * @file:  the file output  | 
472  |  |  * @buf:  the buffer to dump  | 
473  |  |  *  | 
474  |  |  * Dumps an XML buffer to  a FILE *.  | 
475  |  |  * Returns the number of #xmlChar written  | 
476  |  |  */  | 
477  |  | size_t  | 
478  | 0  | xmlBufDump(FILE *file, xmlBufPtr buf) { | 
479  | 0  |     size_t ret;  | 
480  |  | 
  | 
481  | 0  |     if ((buf == NULL) || (buf->error != 0)) { | 
482  |  | #ifdef DEBUG_BUFFER  | 
483  |  |         xmlGenericError(xmlGenericErrorContext,  | 
484  |  |     "xmlBufDump: buf == NULL or in error\n");  | 
485  |  | #endif  | 
486  | 0  |   return(0);  | 
487  | 0  |     }  | 
488  | 0  |     if (buf->content == NULL) { | 
489  |  | #ifdef DEBUG_BUFFER  | 
490  |  |         xmlGenericError(xmlGenericErrorContext,  | 
491  |  |     "xmlBufDump: buf->content == NULL\n");  | 
492  |  | #endif  | 
493  | 0  |   return(0);  | 
494  | 0  |     }  | 
495  | 0  |     CHECK_COMPAT(buf)  | 
496  | 0  |     if (file == NULL)  | 
497  | 0  |   file = stdout;  | 
498  | 0  |     ret = fwrite(buf->content, 1, buf->use, file);  | 
499  | 0  |     return(ret);  | 
500  | 0  | }  | 
501  |  |  | 
502  |  | /**  | 
503  |  |  * xmlBufContent:  | 
504  |  |  * @buf:  the buffer  | 
505  |  |  *  | 
506  |  |  * Function to extract the content of a buffer  | 
507  |  |  *  | 
508  |  |  * Returns the internal content  | 
509  |  |  */  | 
510  |  |  | 
511  |  | xmlChar *  | 
512  |  | xmlBufContent(const xmlBuf *buf)  | 
513  | 716k  | { | 
514  | 716k  |     if ((!buf) || (buf->error))  | 
515  | 0  |         return NULL;  | 
516  |  |  | 
517  | 716k  |     return(buf->content);  | 
518  | 716k  | }  | 
519  |  |  | 
520  |  | /**  | 
521  |  |  * xmlBufEnd:  | 
522  |  |  * @buf:  the buffer  | 
523  |  |  *  | 
524  |  |  * Function to extract the end of the content of a buffer  | 
525  |  |  *  | 
526  |  |  * Returns the end of the internal content or NULL in case of error  | 
527  |  |  */  | 
528  |  |  | 
529  |  | xmlChar *  | 
530  |  | xmlBufEnd(xmlBufPtr buf)  | 
531  | 555k  | { | 
532  | 555k  |     if ((!buf) || (buf->error))  | 
533  | 0  |         return NULL;  | 
534  | 555k  |     CHECK_COMPAT(buf)  | 
535  |  |  | 
536  | 555k  |     return(&buf->content[buf->use]);  | 
537  | 555k  | }  | 
538  |  |  | 
539  |  | /**  | 
540  |  |  * xmlBufAddLen:  | 
541  |  |  * @buf:  the buffer  | 
542  |  |  * @len:  the size which were added at the end  | 
543  |  |  *  | 
544  |  |  * Sometime data may be added at the end of the buffer without  | 
545  |  |  * using the xmlBuf APIs that is used to expand the used space  | 
546  |  |  * and set the zero terminating at the end of the buffer  | 
547  |  |  *  | 
548  |  |  * Returns -1 in case of error and 0 otherwise  | 
549  |  |  */  | 
550  |  | int  | 
551  | 457k  | xmlBufAddLen(xmlBufPtr buf, size_t len) { | 
552  | 457k  |     if ((buf == NULL) || (buf->error))  | 
553  | 0  |         return(-1);  | 
554  | 457k  |     CHECK_COMPAT(buf)  | 
555  | 457k  |     if (len >= (buf->size - buf->use))  | 
556  | 0  |         return(-1);  | 
557  | 457k  |     buf->use += len;  | 
558  | 457k  |     buf->content[buf->use] = 0;  | 
559  | 457k  |     UPDATE_COMPAT(buf)  | 
560  | 457k  |     return(0);  | 
561  | 457k  | }  | 
562  |  |  | 
563  |  | /**  | 
564  |  |  * xmlBufLength:  | 
565  |  |  * @buf:  the buffer  | 
566  |  |  *  | 
567  |  |  * Function to get the length of a buffer  | 
568  |  |  *  | 
569  |  |  * Returns the length of data in the internal content  | 
570  |  |  */  | 
571  |  |  | 
572  |  | size_t  | 
573  |  | xmlBufLength(const xmlBufPtr buf)  | 
574  | 0  | { | 
575  | 0  |     if ((!buf) || (buf->error))  | 
576  | 0  |         return 0;  | 
577  | 0  |     CHECK_COMPAT(buf)  | 
578  |  | 
  | 
579  | 0  |     return(buf->use);  | 
580  | 0  | }  | 
581  |  |  | 
582  |  | /**  | 
583  |  |  * xmlBufUse:  | 
584  |  |  * @buf:  the buffer  | 
585  |  |  *  | 
586  |  |  * Function to get the length of a buffer  | 
587  |  |  *  | 
588  |  |  * Returns the length of data in the internal content  | 
589  |  |  */  | 
590  |  |  | 
591  |  | size_t  | 
592  |  | xmlBufUse(const xmlBufPtr buf)  | 
593  | 41.1M  | { | 
594  | 41.1M  |     if ((!buf) || (buf->error))  | 
595  | 0  |         return 0;  | 
596  | 41.1M  |     CHECK_COMPAT(buf)  | 
597  |  |  | 
598  | 41.1M  |     return(buf->use);  | 
599  | 41.1M  | }  | 
600  |  |  | 
601  |  | /**  | 
602  |  |  * xmlBufAvail:  | 
603  |  |  * @buf:  the buffer  | 
604  |  |  *  | 
605  |  |  * Function to find how much free space is allocated but not  | 
606  |  |  * used in the buffer. It reserves one byte for the NUL  | 
607  |  |  * terminator character that is usually needed, so there is  | 
608  |  |  * no need to subtract 1 from the result anymore.  | 
609  |  |  *  | 
610  |  |  * Returns the amount, or 0 if none or if an error occurred.  | 
611  |  |  */  | 
612  |  |  | 
613  |  | size_t  | 
614  |  | xmlBufAvail(const xmlBufPtr buf)  | 
615  | 500k  | { | 
616  | 500k  |     if ((!buf) || (buf->error))  | 
617  | 0  |         return 0;  | 
618  | 500k  |     CHECK_COMPAT(buf)  | 
619  |  |  | 
620  | 500k  |     return((buf->size > buf->use) ? (buf->size - buf->use - 1) : 0);  | 
621  | 500k  | }  | 
622  |  |  | 
623  |  | /**  | 
624  |  |  * xmlBufIsEmpty:  | 
625  |  |  * @buf:  the buffer  | 
626  |  |  *  | 
627  |  |  * Tell if a buffer is empty  | 
628  |  |  *  | 
629  |  |  * Returns 0 if no, 1 if yes and -1 in case of error  | 
630  |  |  */  | 
631  |  | int  | 
632  |  | xmlBufIsEmpty(const xmlBufPtr buf)  | 
633  | 1.03M  | { | 
634  | 1.03M  |     if ((!buf) || (buf->error))  | 
635  | 0  |         return(-1);  | 
636  | 1.03M  |     CHECK_COMPAT(buf)  | 
637  |  |  | 
638  | 1.03M  |     return(buf->use == 0);  | 
639  | 1.03M  | }  | 
640  |  |  | 
641  |  | /**  | 
642  |  |  * xmlBufResize:  | 
643  |  |  * @buf:  the buffer to resize  | 
644  |  |  * @size:  the desired size  | 
645  |  |  *  | 
646  |  |  * Resize a buffer to accommodate minimum size of @size.  | 
647  |  |  *  | 
648  |  |  * Returns  0 in case of problems, 1 otherwise  | 
649  |  |  */  | 
650  |  | int  | 
651  |  | xmlBufResize(xmlBufPtr buf, size_t size)  | 
652  | 82.5k  | { | 
653  | 82.5k  |     size_t newSize;  | 
654  | 82.5k  |     xmlChar* rebuf = NULL;  | 
655  | 82.5k  |     size_t start_buf;  | 
656  |  |  | 
657  | 82.5k  |     if ((buf == NULL) || (buf->error))  | 
658  | 0  |         return(0);  | 
659  | 82.5k  |     CHECK_COMPAT(buf)  | 
660  |  |  | 
661  | 82.5k  |     if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { | 
662  |  |         /*  | 
663  |  |    * Used to provide parsing limits  | 
664  |  |    */  | 
665  | 0  |         if (size >= XML_MAX_TEXT_LENGTH) { | 
666  | 0  |       xmlBufMemoryError(buf, "buffer error: text too long\n");  | 
667  | 0  |       return(0);  | 
668  | 0  |   }  | 
669  | 0  |     }  | 
670  |  |  | 
671  |  |     /* Don't resize if we don't have to */  | 
672  | 82.5k  |     if (size < buf->size)  | 
673  | 0  |         return 1;  | 
674  |  |  | 
675  |  |     /* figure out new size */  | 
676  | 82.5k  |     switch (buf->alloc){ | 
677  | 0  |   case XML_BUFFER_ALLOC_IO:  | 
678  | 82.5k  |   case XML_BUFFER_ALLOC_DOUBLEIT:  | 
679  |  |       /*take care of empty case*/  | 
680  | 82.5k  |             if (buf->size == 0) { | 
681  | 70.5k  |                 newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);  | 
682  | 70.5k  |             } else { | 
683  | 11.9k  |                 newSize = buf->size;  | 
684  | 11.9k  |             }  | 
685  | 102k  |       while (size > newSize) { | 
686  | 20.1k  |           if (newSize > SIZE_MAX / 2) { | 
687  | 0  |               xmlBufMemoryError(buf, "growing buffer");  | 
688  | 0  |               return 0;  | 
689  | 0  |           }  | 
690  | 20.1k  |           newSize *= 2;  | 
691  | 20.1k  |       }  | 
692  | 82.5k  |       break;  | 
693  | 82.5k  |   case XML_BUFFER_ALLOC_EXACT:  | 
694  | 0  |             newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);  | 
695  | 0  |       break;  | 
696  | 0  |         case XML_BUFFER_ALLOC_HYBRID:  | 
697  | 0  |             if (buf->use < BASE_BUFFER_SIZE)  | 
698  | 0  |                 newSize = size;  | 
699  | 0  |             else { | 
700  | 0  |                 newSize = buf->size;  | 
701  | 0  |                 while (size > newSize) { | 
702  | 0  |                     if (newSize > SIZE_MAX / 2) { | 
703  | 0  |                         xmlBufMemoryError(buf, "growing buffer");  | 
704  | 0  |                         return 0;  | 
705  | 0  |                     }  | 
706  | 0  |                     newSize *= 2;  | 
707  | 0  |                 }  | 
708  | 0  |             }  | 
709  | 0  |             break;  | 
710  |  |  | 
711  | 0  |   default:  | 
712  | 0  |             newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);  | 
713  | 0  |       break;  | 
714  | 82.5k  |     }  | 
715  |  |  | 
716  | 82.5k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
717  | 0  |         start_buf = buf->content - buf->contentIO;  | 
718  |  | 
  | 
719  | 0  |         if (start_buf > newSize) { | 
720  |  |       /* move data back to start */  | 
721  | 0  |       memmove(buf->contentIO, buf->content, buf->use);  | 
722  | 0  |       buf->content = buf->contentIO;  | 
723  | 0  |       buf->content[buf->use] = 0;  | 
724  | 0  |       buf->size += start_buf;  | 
725  | 0  |   } else { | 
726  | 0  |       rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);  | 
727  | 0  |       if (rebuf == NULL) { | 
728  | 0  |     xmlBufMemoryError(buf, "growing buffer");  | 
729  | 0  |     return 0;  | 
730  | 0  |       }  | 
731  | 0  |       buf->contentIO = rebuf;  | 
732  | 0  |       buf->content = rebuf + start_buf;  | 
733  | 0  |   }  | 
734  | 82.5k  |     } else { | 
735  | 82.5k  |   if (buf->content == NULL) { | 
736  | 70.5k  |       rebuf = (xmlChar *) xmlMallocAtomic(newSize);  | 
737  | 70.5k  |       buf->use = 0;  | 
738  | 70.5k  |             if (rebuf != NULL)  | 
739  | 70.5k  |           rebuf[buf->use] = 0;  | 
740  | 70.5k  |   } else if (buf->size - buf->use < 100) { | 
741  | 4.38k  |       rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);  | 
742  | 7.60k  |         } else { | 
743  |  |       /*  | 
744  |  |        * if we are reallocating a buffer far from being full, it's  | 
745  |  |        * better to make a new allocation and copy only the used range  | 
746  |  |        * and free the old one.  | 
747  |  |        */  | 
748  | 7.60k  |       rebuf = (xmlChar *) xmlMallocAtomic(newSize);  | 
749  | 7.60k  |       if (rebuf != NULL) { | 
750  | 7.60k  |     memcpy(rebuf, buf->content, buf->use);  | 
751  | 7.60k  |     xmlFree(buf->content);  | 
752  | 7.60k  |     rebuf[buf->use] = 0;  | 
753  | 7.60k  |       }  | 
754  | 7.60k  |   }  | 
755  | 82.5k  |   if (rebuf == NULL) { | 
756  | 0  |       xmlBufMemoryError(buf, "growing buffer");  | 
757  | 0  |       return 0;  | 
758  | 0  |   }  | 
759  | 82.5k  |   buf->content = rebuf;  | 
760  | 82.5k  |     }  | 
761  | 82.5k  |     buf->size = newSize;  | 
762  | 82.5k  |     UPDATE_COMPAT(buf)  | 
763  |  |  | 
764  | 82.5k  |     return 1;  | 
765  | 82.5k  | }  | 
766  |  |  | 
767  |  | /**  | 
768  |  |  * xmlBufAdd:  | 
769  |  |  * @buf:  the buffer to dump  | 
770  |  |  * @str:  the #xmlChar string  | 
771  |  |  * @len:  the number of #xmlChar to add  | 
772  |  |  *  | 
773  |  |  * Add a string range to an XML buffer. if len == -1, the length of  | 
774  |  |  * str is recomputed.  | 
775  |  |  *  | 
776  |  |  * Returns 0 successful, a positive error code number otherwise  | 
777  |  |  *         and -1 in case of internal or API error.  | 
778  |  |  */  | 
779  |  | int  | 
780  | 3.12M  | xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { | 
781  | 3.12M  |     size_t needSize;  | 
782  |  |  | 
783  | 3.12M  |     if ((str == NULL) || (buf == NULL) || (buf->error))  | 
784  | 0  |   return -1;  | 
785  | 3.12M  |     CHECK_COMPAT(buf)  | 
786  |  |  | 
787  | 3.12M  |     if (len < -1) { | 
788  |  | #ifdef DEBUG_BUFFER  | 
789  |  |         xmlGenericError(xmlGenericErrorContext,  | 
790  |  |     "xmlBufAdd: len < 0\n");  | 
791  |  | #endif  | 
792  | 0  |   return -1;  | 
793  | 0  |     }  | 
794  | 3.12M  |     if (len == 0) return 0;  | 
795  |  |  | 
796  | 2.86M  |     if (len < 0)  | 
797  | 1.12M  |         len = xmlStrlen(str);  | 
798  |  |  | 
799  | 2.86M  |     if (len < 0) return -1;  | 
800  | 2.86M  |     if (len == 0) return 0;  | 
801  |  |  | 
802  |  |     /* Note that both buf->size and buf->use can be zero here. */  | 
803  | 2.86M  |     if ((size_t) len >= buf->size - buf->use) { | 
804  | 82.5k  |         if ((size_t) len >= SIZE_MAX - buf->use) { | 
805  | 0  |             xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");  | 
806  | 0  |             return(-1);  | 
807  | 0  |         }  | 
808  | 82.5k  |         needSize = buf->use + len + 1;  | 
809  | 82.5k  |   if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { | 
810  |  |       /*  | 
811  |  |        * Used to provide parsing limits  | 
812  |  |        */  | 
813  | 0  |       if (needSize >= XML_MAX_TEXT_LENGTH) { | 
814  | 0  |     xmlBufMemoryError(buf, "buffer error: text too long\n");  | 
815  | 0  |     return(-1);  | 
816  | 0  |       }  | 
817  | 0  |   }  | 
818  | 82.5k  |         if (!xmlBufResize(buf, needSize)){ | 
819  | 0  |       xmlBufMemoryError(buf, "growing buffer");  | 
820  | 0  |             return XML_ERR_NO_MEMORY;  | 
821  | 0  |         }  | 
822  | 82.5k  |     }  | 
823  |  |  | 
824  | 2.86M  |     memmove(&buf->content[buf->use], str, len);  | 
825  | 2.86M  |     buf->use += len;  | 
826  | 2.86M  |     buf->content[buf->use] = 0;  | 
827  | 2.86M  |     UPDATE_COMPAT(buf)  | 
828  | 2.86M  |     return 0;  | 
829  | 2.86M  | }  | 
830  |  |  | 
831  |  | /**  | 
832  |  |  * xmlBufCat:  | 
833  |  |  * @buf:  the buffer to add to  | 
834  |  |  * @str:  the #xmlChar string  | 
835  |  |  *  | 
836  |  |  * Append a zero terminated string to an XML buffer.  | 
837  |  |  *  | 
838  |  |  * Returns 0 successful, a positive error code number otherwise  | 
839  |  |  *         and -1 in case of internal or API error.  | 
840  |  |  */  | 
841  |  | int  | 
842  | 75.1k  | xmlBufCat(xmlBufPtr buf, const xmlChar *str) { | 
843  | 75.1k  |     if ((buf == NULL) || (buf->error))  | 
844  | 0  |         return(-1);  | 
845  | 75.1k  |     CHECK_COMPAT(buf)  | 
846  | 75.1k  |     if (str == NULL) return -1;  | 
847  | 75.0k  |     return xmlBufAdd(buf, str, -1);  | 
848  | 75.1k  | }  | 
849  |  |  | 
850  |  | /**  | 
851  |  |  * xmlBufCCat:  | 
852  |  |  * @buf:  the buffer to dump  | 
853  |  |  * @str:  the C char string  | 
854  |  |  *  | 
855  |  |  * Append a zero terminated C string to an XML buffer.  | 
856  |  |  *  | 
857  |  |  * Returns 0 successful, a positive error code number otherwise  | 
858  |  |  *         and -1 in case of internal or API error.  | 
859  |  |  */  | 
860  |  | int  | 
861  | 47.5k  | xmlBufCCat(xmlBufPtr buf, const char *str) { | 
862  | 47.5k  |     return xmlBufCat(buf, (const xmlChar *) str);  | 
863  | 47.5k  | }  | 
864  |  |  | 
865  |  | /**  | 
866  |  |  * xmlBufWriteQuotedString:  | 
867  |  |  * @buf:  the XML buffer output  | 
868  |  |  * @string:  the string to add  | 
869  |  |  *  | 
870  |  |  * routine which manage and grows an output buffer. This one writes  | 
871  |  |  * a quoted or double quoted #xmlChar string, checking first if it holds  | 
872  |  |  * quote or double-quotes internally  | 
873  |  |  *  | 
874  |  |  * Returns 0 if successful, a positive error code number otherwise  | 
875  |  |  *         and -1 in case of internal or API error.  | 
876  |  |  */  | 
877  |  | int  | 
878  | 23.7k  | xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) { | 
879  | 23.7k  |     const xmlChar *cur, *base;  | 
880  | 23.7k  |     if ((buf == NULL) || (buf->error))  | 
881  | 0  |         return(-1);  | 
882  | 23.7k  |     CHECK_COMPAT(buf)  | 
883  | 23.7k  |     if (xmlStrchr(string, '\"')) { | 
884  | 528  |         if (xmlStrchr(string, '\'')) { | 
885  |  | #ifdef DEBUG_BUFFER  | 
886  |  |       xmlGenericError(xmlGenericErrorContext,  | 
887  |  |  "xmlBufWriteQuotedString: string contains quote and double-quotes !\n");  | 
888  |  | #endif  | 
889  | 290  |       xmlBufCCat(buf, "\"");  | 
890  | 290  |             base = cur = string;  | 
891  | 2.98M  |             while(*cur != 0){ | 
892  | 2.98M  |                 if(*cur == '"'){ | 
893  | 12.3k  |                     if (base != cur)  | 
894  | 588  |                         xmlBufAdd(buf, base, cur - base);  | 
895  | 12.3k  |                     xmlBufAdd(buf, BAD_CAST """, 6);  | 
896  | 12.3k  |                     cur++;  | 
897  | 12.3k  |                     base = cur;  | 
898  | 12.3k  |                 }  | 
899  | 2.97M  |                 else { | 
900  | 2.97M  |                     cur++;  | 
901  | 2.97M  |                 }  | 
902  | 2.98M  |             }  | 
903  | 290  |             if (base != cur)  | 
904  | 280  |                 xmlBufAdd(buf, base, cur - base);  | 
905  | 290  |       xmlBufCCat(buf, "\"");  | 
906  | 290  |   }  | 
907  | 238  |         else{ | 
908  | 238  |       xmlBufCCat(buf, "\'");  | 
909  | 238  |             xmlBufCat(buf, string);  | 
910  | 238  |       xmlBufCCat(buf, "\'");  | 
911  | 238  |         }  | 
912  | 23.2k  |     } else { | 
913  | 23.2k  |         xmlBufCCat(buf, "\"");  | 
914  | 23.2k  |         xmlBufCat(buf, string);  | 
915  | 23.2k  |         xmlBufCCat(buf, "\"");  | 
916  | 23.2k  |     }  | 
917  | 23.7k  |     return(0);  | 
918  | 23.7k  | }  | 
919  |  |  | 
920  |  | /**  | 
921  |  |  * xmlBufFromBuffer:  | 
922  |  |  * @buffer: incoming old buffer to convert to a new one  | 
923  |  |  *  | 
924  |  |  * Helper routine to switch from the old buffer structures in use  | 
925  |  |  * in various APIs. It creates a wrapper xmlBufPtr which will be  | 
926  |  |  * used for internal processing until the xmlBufBackToBuffer() is  | 
927  |  |  * issued.  | 
928  |  |  *  | 
929  |  |  * Returns a new xmlBufPtr unless the call failed and NULL is returned  | 
930  |  |  */  | 
931  |  | xmlBufPtr  | 
932  | 0  | xmlBufFromBuffer(xmlBufferPtr buffer) { | 
933  | 0  |     xmlBufPtr ret;  | 
934  |  | 
  | 
935  | 0  |     if (buffer == NULL)  | 
936  | 0  |         return(NULL);  | 
937  |  |  | 
938  | 0  |     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));  | 
939  | 0  |     if (ret == NULL) { | 
940  | 0  |   xmlBufMemoryError(NULL, "creating buffer");  | 
941  | 0  |         return(NULL);  | 
942  | 0  |     }  | 
943  | 0  |     ret->use = buffer->use;  | 
944  | 0  |     ret->size = buffer->size;  | 
945  | 0  |     UPDATE_COMPAT(ret);  | 
946  | 0  |     ret->error = 0;  | 
947  | 0  |     ret->buffer = buffer;  | 
948  | 0  |     ret->alloc = buffer->alloc;  | 
949  | 0  |     ret->content = buffer->content;  | 
950  | 0  |     ret->contentIO = buffer->contentIO;  | 
951  |  | 
  | 
952  | 0  |     return(ret);  | 
953  | 0  | }  | 
954  |  |  | 
955  |  | /**  | 
956  |  |  * xmlBufBackToBuffer:  | 
957  |  |  * @buf: new buffer wrapping the old one  | 
958  |  |  *  | 
959  |  |  * Function to be called once internal processing had been done to  | 
960  |  |  * update back the buffer provided by the user. This can lead to  | 
961  |  |  * a failure in case the size accumulated in the xmlBuf is larger  | 
962  |  |  * than what an xmlBuffer can support on 64 bits (INT_MAX)  | 
963  |  |  * The xmlBufPtr @buf wrapper is deallocated by this call in any case.  | 
964  |  |  *  | 
965  |  |  * Returns the old xmlBufferPtr unless the call failed and NULL is returned  | 
966  |  |  */  | 
967  |  | xmlBufferPtr  | 
968  | 0  | xmlBufBackToBuffer(xmlBufPtr buf) { | 
969  | 0  |     xmlBufferPtr ret;  | 
970  |  | 
  | 
971  | 0  |     if (buf == NULL)  | 
972  | 0  |         return(NULL);  | 
973  | 0  |     CHECK_COMPAT(buf)  | 
974  | 0  |     if ((buf->error) || (buf->buffer == NULL)) { | 
975  | 0  |         xmlBufFree(buf);  | 
976  | 0  |         return(NULL);  | 
977  | 0  |     }  | 
978  |  |  | 
979  | 0  |     ret = buf->buffer;  | 
980  |  |     /*  | 
981  |  |      * What to do in case of error in the buffer ???  | 
982  |  |      */  | 
983  | 0  |     if (buf->use > INT_MAX) { | 
984  |  |         /*  | 
985  |  |          * Worse case, we really allocated and used more than the  | 
986  |  |          * maximum allowed memory for an xmlBuffer on this architecture.  | 
987  |  |          * Keep the buffer but provide a truncated size value.  | 
988  |  |          */  | 
989  | 0  |         xmlBufOverflowError(buf, "Used size too big for xmlBuffer");  | 
990  | 0  |         ret->use = INT_MAX;  | 
991  | 0  |         ret->size = INT_MAX;  | 
992  | 0  |     } else if (buf->size > INT_MAX) { | 
993  |  |         /*  | 
994  |  |          * milder case, we allocated more than the maximum allowed memory  | 
995  |  |          * for an xmlBuffer on this architecture, but used less than the  | 
996  |  |          * limit.  | 
997  |  |          * Keep the buffer but provide a truncated size value.  | 
998  |  |          */  | 
999  | 0  |         xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");  | 
1000  | 0  |         ret->use = buf->use;  | 
1001  | 0  |         ret->size = INT_MAX;  | 
1002  | 0  |     } else { | 
1003  | 0  |         ret->use = buf->use;  | 
1004  | 0  |         ret->size = buf->size;  | 
1005  | 0  |     }  | 
1006  | 0  |     ret->alloc = buf->alloc;  | 
1007  | 0  |     ret->content = buf->content;  | 
1008  | 0  |     ret->contentIO = buf->contentIO;  | 
1009  | 0  |     xmlFree(buf);  | 
1010  | 0  |     return(ret);  | 
1011  | 0  | }  | 
1012  |  |  | 
1013  |  | /**  | 
1014  |  |  * xmlBufMergeBuffer:  | 
1015  |  |  * @buf: an xmlBufPtr  | 
1016  |  |  * @buffer: the buffer to consume into @buf  | 
1017  |  |  *  | 
1018  |  |  * The content of @buffer is appended to @buf and @buffer is freed  | 
1019  |  |  *  | 
1020  |  |  * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed  | 
1021  |  |  */  | 
1022  |  | int  | 
1023  | 12.8k  | xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) { | 
1024  | 12.8k  |     int ret = 0;  | 
1025  |  |  | 
1026  | 12.8k  |     if ((buf == NULL) || (buf->error)) { | 
1027  | 0  |   xmlBufferFree(buffer);  | 
1028  | 0  |         return(-1);  | 
1029  | 0  |     }  | 
1030  | 12.8k  |     CHECK_COMPAT(buf)  | 
1031  | 12.8k  |     if ((buffer != NULL) && (buffer->content != NULL) &&  | 
1032  | 12.8k  |              (buffer->use > 0)) { | 
1033  | 12.8k  |         ret = xmlBufAdd(buf, buffer->content, buffer->use);  | 
1034  | 12.8k  |     }  | 
1035  | 12.8k  |     xmlBufferFree(buffer);  | 
1036  | 12.8k  |     return(ret);  | 
1037  | 12.8k  | }  | 
1038  |  |  | 
1039  |  | /**  | 
1040  |  |  * xmlBufResetInput:  | 
1041  |  |  * @buf: an xmlBufPtr  | 
1042  |  |  * @input: an xmlParserInputPtr  | 
1043  |  |  *  | 
1044  |  |  * Update the input to use the current set of pointers from the buffer.  | 
1045  |  |  *  | 
1046  |  |  * Returns -1 in case of error, 0 otherwise  | 
1047  |  |  */  | 
1048  |  | int  | 
1049  | 99.8k  | xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) { | 
1050  | 99.8k  |     if ((input == NULL) || (buf == NULL) || (buf->error))  | 
1051  | 0  |         return(-1);  | 
1052  | 99.8k  |     CHECK_COMPAT(buf)  | 
1053  | 99.8k  |     input->base = input->cur = buf->content;  | 
1054  | 99.8k  |     input->end = &buf->content[buf->use];  | 
1055  | 99.8k  |     return(0);  | 
1056  | 99.8k  | }  | 
1057  |  |  | 
1058  |  | /**  | 
1059  |  |  * xmlBufGetInputBase:  | 
1060  |  |  * @buf: an xmlBufPtr  | 
1061  |  |  * @input: an xmlParserInputPtr  | 
1062  |  |  *  | 
1063  |  |  * Get the base of the @input relative to the beginning of the buffer  | 
1064  |  |  *  | 
1065  |  |  * Returns the size_t corresponding to the displacement  | 
1066  |  |  */  | 
1067  |  | size_t  | 
1068  | 1.29M  | xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) { | 
1069  | 1.29M  |     size_t base;  | 
1070  |  |  | 
1071  | 1.29M  |     if ((input == NULL) || (buf == NULL) || (buf->error))  | 
1072  | 0  |         return(0);  | 
1073  | 1.29M  |     CHECK_COMPAT(buf)  | 
1074  | 1.29M  |     base = input->base - buf->content;  | 
1075  |  |     /*  | 
1076  |  |      * We could do some pointer arithmetic checks but that's probably  | 
1077  |  |      * sufficient.  | 
1078  |  |      */  | 
1079  | 1.29M  |     if (base > buf->size) { | 
1080  | 0  |         xmlBufOverflowError(buf, "Input reference outside of the buffer");  | 
1081  | 0  |         base = 0;  | 
1082  | 0  |     }  | 
1083  | 1.29M  |     return(base);  | 
1084  | 1.29M  | }  | 
1085  |  |  | 
1086  |  | /**  | 
1087  |  |  * xmlBufSetInputBaseCur:  | 
1088  |  |  * @buf: an xmlBufPtr  | 
1089  |  |  * @input: an xmlParserInputPtr  | 
1090  |  |  * @base: the base value relative to the beginning of the buffer  | 
1091  |  |  * @cur: the cur value relative to the beginning of the buffer  | 
1092  |  |  *  | 
1093  |  |  * Update the input to use the base and cur relative to the buffer  | 
1094  |  |  * after a possible reallocation of its content  | 
1095  |  |  *  | 
1096  |  |  * Returns -1 in case of error, 0 otherwise  | 
1097  |  |  */  | 
1098  |  | int  | 
1099  |  | xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,  | 
1100  | 1.29M  |                       size_t base, size_t cur) { | 
1101  | 1.29M  |     if (input == NULL)  | 
1102  | 0  |         return(-1);  | 
1103  | 1.29M  |     if ((buf == NULL) || (buf->error)) { | 
1104  | 0  |         input->base = input->cur = input->end = BAD_CAST "";  | 
1105  | 0  |         return(-1);  | 
1106  | 0  |     }  | 
1107  | 1.29M  |     CHECK_COMPAT(buf)  | 
1108  | 1.29M  |     input->base = &buf->content[base];  | 
1109  | 1.29M  |     input->cur = input->base + cur;  | 
1110  | 1.29M  |     input->end = &buf->content[buf->use];  | 
1111  | 1.29M  |     return(0);  | 
1112  | 1.29M  | }  | 
1113  |  |  |