File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_expat.c |
Location: | line 119, column 5 |
Description: | Argument to free() is a constant address (3735928559), which is not memory allocated by malloc() |
1 | /* Copyright information is at end of file */ | |||
2 | ||||
3 | #include "xmlrpc_config.h" | |||
4 | ||||
5 | #include <stddef.h> | |||
6 | #include <stdlib.h> | |||
7 | #include <string.h> | |||
8 | ||||
9 | #include <xmlparse.h> /* Expat */ | |||
10 | ||||
11 | #include "bool.h" | |||
12 | ||||
13 | #include "xmlrpc-c/base.h" | |||
14 | #include "xmlrpc-c/base_int.h" | |||
15 | #include "xmlrpc-c/string_int.h" | |||
16 | #include "xmlrpc-c/xmlparser.h" | |||
17 | ||||
18 | /* Define the contents of our internal structure. */ | |||
19 | struct _xml_element { | |||
20 | struct _xml_element *_parent; | |||
21 | char *_name; | |||
22 | xmlrpc_mem_block _cdata; /* char */ | |||
23 | xmlrpc_mem_block _children; /* xml_element* */ | |||
24 | }; | |||
25 | ||||
26 | /* Check that we're using expat in UTF-8 mode, not wchar_t mode. | |||
27 | ** If you need to use expat in wchar_t mode, write a subroutine to | |||
28 | ** copy a wchar_t string to a char string & return an error for | |||
29 | ** any non-ASCII characters. Then call this subroutine on all | |||
30 | ** XML_Char strings passed to our event handlers before using the | |||
31 | ** data. */ | |||
32 | /* #if sizeof(char) != sizeof(XML_Char) | |||
33 | ** #error expat must define XML_Char to be a regular char. | |||
34 | ** #endif | |||
35 | */ | |||
36 | ||||
37 | #define XMLRPC_ASSERT_ELEM_OK(elem)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 37); while (0) \ | |||
38 | XMLRPC_ASSERT((elem) != NULL && (elem)->_name != XMLRPC_BAD_POINTER)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 38); while (0) | |||
39 | ||||
40 | ||||
41 | /*========================================================================= | |||
42 | ** xml_element_new | |||
43 | **========================================================================= | |||
44 | ** Create a new xml_element. This routine isn't exported, because the | |||
45 | ** arguments are implementation-dependent. | |||
46 | */ | |||
47 | ||||
48 | static xml_element * | |||
49 | xml_element_new (xmlrpc_env * const env, | |||
50 | const char * const name) { | |||
51 | ||||
52 | xml_element *retval; | |||
53 | int name_valid, cdata_valid, children_valid; | |||
54 | ||||
55 | XMLRPC_ASSERT_ENV_OK(env)do if (!((env) != ((void*)0) && (env->fault_string == ((void*)0)) && !(env)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 55); while ( 0); | |||
56 | XMLRPC_ASSERT(name != NULL)do if (!(name != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 56); while (0); | |||
57 | ||||
58 | /* Set up our error-handling preconditions. */ | |||
59 | retval = NULL((void*)0); | |||
60 | name_valid = cdata_valid = children_valid = 0; | |||
61 | ||||
62 | /* Allocate our xml_element structure. */ | |||
63 | retval = (xml_element*) malloc(sizeof(xml_element)); | |||
64 | XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR,do { if ((retval) == ((void*)0)) do { xmlrpc_env_set_fault((( env)),(((-500))),(("Couldn't allocate memory for XML element" ))); goto cleanup; } while (0); } while (0) | |||
65 | "Couldn't allocate memory for XML element")do { if ((retval) == ((void*)0)) do { xmlrpc_env_set_fault((( env)),(((-500))),(("Couldn't allocate memory for XML element" ))); goto cleanup; } while (0); } while (0); | |||
66 | ||||
67 | /* Set our parent field to NULL. */ | |||
68 | retval->_parent = NULL((void*)0); | |||
69 | ||||
70 | /* Copy over the element name. */ | |||
71 | retval->_name = (char*) malloc(strlen(name) + 1); | |||
72 | XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR,do { if ((retval->_name) == ((void*)0)) do { xmlrpc_env_set_fault (((env)),(((-500))),(("Couldn't allocate memory for XML element" ))); goto cleanup; } while (0); } while (0) | |||
73 | "Couldn't allocate memory for XML element")do { if ((retval->_name) == ((void*)0)) do { xmlrpc_env_set_fault (((env)),(((-500))),(("Couldn't allocate memory for XML element" ))); goto cleanup; } while (0); } while (0); | |||
74 | name_valid = 1; | |||
75 | strcpy(retval->_name, name); | |||
76 | ||||
77 | /* Initialize a block to hold our CDATA. */ | |||
78 | XMLRPC_TYPED_MEM_BLOCK_INIT(char, env, &retval->_cdata, 0)xmlrpc_mem_block_init((env), (&retval->_cdata), sizeof (char) * (0)); | |||
79 | XMLRPC_FAIL_IF_FAULT(env)do { if ((env)->fault_occurred) goto cleanup; } while (0); | |||
80 | cdata_valid = 1; | |||
81 | ||||
82 | /* Initialize a block to hold our child elements. */ | |||
83 | XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element*, env, &retval->_children, 0)xmlrpc_mem_block_init((env), (&retval->_children), sizeof (xml_element*) * (0)); | |||
84 | XMLRPC_FAIL_IF_FAULT(env)do { if ((env)->fault_occurred) goto cleanup; } while (0); | |||
85 | children_valid = 1; | |||
86 | ||||
87 | cleanup: | |||
88 | if (env->fault_occurred) { | |||
89 | if (retval) { | |||
90 | if (name_valid) | |||
91 | free(retval->_name); | |||
92 | if (cdata_valid) | |||
93 | xmlrpc_mem_block_clean(&retval->_cdata); | |||
94 | if (children_valid) | |||
95 | xmlrpc_mem_block_clean(&retval->_children); | |||
96 | free(retval); | |||
97 | } | |||
98 | return NULL((void*)0); | |||
99 | } else { | |||
100 | return retval; | |||
101 | } | |||
102 | } | |||
103 | ||||
104 | ||||
105 | /*========================================================================= | |||
106 | ** xml_element_free | |||
107 | **========================================================================= | |||
108 | ** Blow away an existing element & all of its child elements. | |||
109 | */ | |||
110 | void | |||
111 | xml_element_free(xml_element * const elemP) { | |||
112 | ||||
113 | xmlrpc_mem_block * childrenP; | |||
114 | size_t size, i; | |||
115 | xml_element ** contents; | |||
116 | ||||
117 | XMLRPC_ASSERT_ELEM_OK(elemP)do if (!((elemP) != ((void*)0) && (elemP)->_name != ((void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 117); while (0); | |||
118 | ||||
119 | free(elemP->_name); | |||
| ||||
120 | elemP->_name = XMLRPC_BAD_POINTER((void*) 0xDEADBEEF); | |||
121 | XMLRPC_MEMBLOCK_CLEAN(xml_element *, &elemP->_cdata)xmlrpc_mem_block_clean(&elemP->_cdata); | |||
122 | ||||
123 | /* Deallocate all of our children recursively. */ | |||
124 | childrenP = &elemP->_children; | |||
125 | contents = XMLRPC_MEMBLOCK_CONTENTS(xml_element *, childrenP)((xml_element **) xmlrpc_mem_block_contents(childrenP)); | |||
126 | size = XMLRPC_MEMBLOCK_SIZE(xml_element *, childrenP)(xmlrpc_mem_block_size(childrenP) / sizeof(xml_element *)); | |||
127 | for (i = 0; i < size; ++i) | |||
128 | xml_element_free(contents[i]); | |||
129 | ||||
130 | XMLRPC_MEMBLOCK_CLEAN(xml_element *, &elemP->_children)xmlrpc_mem_block_clean(&elemP->_children); | |||
131 | ||||
132 | free(elemP); | |||
133 | } | |||
134 | ||||
135 | ||||
136 | /*========================================================================= | |||
137 | ** Miscellaneous Accessors | |||
138 | **========================================================================= | |||
139 | ** Return the fields of the xml_element. See the header for more | |||
140 | ** documentation on each function works. | |||
141 | */ | |||
142 | ||||
143 | ||||
144 | ||||
145 | const char * | |||
146 | xml_element_name(const xml_element * const elemP) { | |||
147 | ||||
148 | XMLRPC_ASSERT_ELEM_OK(elemP)do if (!((elemP) != ((void*)0) && (elemP)->_name != ((void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 148); while (0); | |||
149 | return elemP->_name; | |||
150 | } | |||
151 | ||||
152 | ||||
153 | ||||
154 | /* The result of this function is NOT VALID until the end_element handler | |||
155 | ** has been called! */ | |||
156 | size_t xml_element_cdata_size (xml_element *elem) | |||
157 | { | |||
158 | XMLRPC_ASSERT_ELEM_OK(elem)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 158); while (0); | |||
159 | return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elem->_cdata)(xmlrpc_mem_block_size(&elem->_cdata) / sizeof(char)) - 1; | |||
160 | } | |||
161 | ||||
162 | char *xml_element_cdata (xml_element *elem) | |||
163 | { | |||
164 | XMLRPC_ASSERT_ELEM_OK(elem)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 164); while (0); | |||
165 | return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata)((char*) xmlrpc_mem_block_contents(&elem->_cdata)); | |||
166 | } | |||
167 | ||||
168 | ||||
169 | ||||
170 | size_t | |||
171 | xml_element_children_size(const xml_element * const elemP) { | |||
172 | XMLRPC_ASSERT_ELEM_OK(elemP)do if (!((elemP) != ((void*)0) && (elemP)->_name != ((void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 172); while (0); | |||
173 | return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, &elemP->_children)(xmlrpc_mem_block_size(&elemP->_children) / sizeof(xml_element *)); | |||
174 | } | |||
175 | ||||
176 | ||||
177 | ||||
178 | xml_element ** | |||
179 | xml_element_children(const xml_element * const elemP) { | |||
180 | XMLRPC_ASSERT_ELEM_OK(elemP)do if (!((elemP) != ((void*)0) && (elemP)->_name != ((void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 180); while (0); | |||
181 | return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, &elemP->_children)((xml_element **) xmlrpc_mem_block_contents(&elemP->_children )); | |||
182 | } | |||
183 | ||||
184 | ||||
185 | ||||
186 | /*========================================================================= | |||
187 | ** Internal xml_element Utility Functions | |||
188 | **========================================================================= | |||
189 | */ | |||
190 | ||||
191 | static void xml_element_append_cdata (xmlrpc_env *env, | |||
192 | xml_element *elem, | |||
193 | char *cdata, | |||
194 | size_t size) | |||
195 | { | |||
196 | XMLRPC_ASSERT_ENV_OK(env)do if (!((env) != ((void*)0) && (env->fault_string == ((void*)0)) && !(env)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 196); while ( 0); | |||
197 | XMLRPC_ASSERT_ELEM_OK(elem)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 197); while (0); | |||
198 | ||||
199 | XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, &elem->_cdata, cdata, size)xmlrpc_mem_block_append(env, &elem->_cdata, cdata, sizeof (char) * (size)); | |||
200 | } | |||
201 | ||||
202 | /* Whether or not this function succeeds, it takes ownership of the 'child' | |||
203 | ** argument. | |||
204 | ** WARNING - This is the exact opposite of the usual memory ownership | |||
205 | ** rules for xmlrpc_value! So please pay attention. */ | |||
206 | static void xml_element_append_child (xmlrpc_env *env, | |||
207 | xml_element *elem, | |||
208 | xml_element *child) | |||
209 | { | |||
210 | XMLRPC_ASSERT_ENV_OK(env)do if (!((env) != ((void*)0) && (env->fault_string == ((void*)0)) && !(env)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 210); while ( 0); | |||
211 | XMLRPC_ASSERT_ELEM_OK(elem)do if (!((elem) != ((void*)0) && (elem)->_name != ( (void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 211); while (0); | |||
212 | XMLRPC_ASSERT_ELEM_OK(child)do if (!((child) != ((void*)0) && (child)->_name != ((void*) 0xDEADBEEF))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 212); while (0); | |||
213 | XMLRPC_ASSERT(child->_parent == NULL)do if (!(child->_parent == ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 213); while ( 0); | |||
214 | ||||
215 | XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children,xmlrpc_mem_block_append(env, &elem->_children, &child , sizeof(xml_element*) * (1)) | |||
216 | &child, 1)xmlrpc_mem_block_append(env, &elem->_children, &child , sizeof(xml_element*) * (1)); | |||
217 | if (!env->fault_occurred) | |||
218 | child->_parent = elem; | |||
219 | else | |||
220 | xml_element_free(child); | |||
221 | } | |||
222 | ||||
223 | ||||
224 | /*========================================================================= | |||
225 | ** Our parse context. We pass this around as expat user data. | |||
226 | **========================================================================= | |||
227 | */ | |||
228 | ||||
229 | typedef struct { | |||
230 | xmlrpc_env env; | |||
231 | xml_element * rootP; | |||
232 | xml_element * currentP; | |||
233 | } parseContext; | |||
234 | ||||
235 | ||||
236 | /*========================================================================= | |||
237 | ** Expat Event Handler Functions | |||
238 | **========================================================================= | |||
239 | */ | |||
240 | ||||
241 | static void | |||
242 | startElement(void * const userData, | |||
243 | XML_Char * const name, | |||
244 | XML_Char ** const atts ATTR_UNUSED__attribute__((__unused__))) { | |||
245 | ||||
246 | parseContext * const contextP = userData; | |||
247 | ||||
248 | XMLRPC_ASSERT(contextP != NULL)do if (!(contextP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 248); while (0); | |||
249 | XMLRPC_ASSERT(name != NULL)do if (!(name != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 249); while (0); | |||
250 | ||||
251 | if (!contextP->env.fault_occurred) { | |||
252 | xml_element * elemP; | |||
253 | ||||
254 | elemP = xml_element_new(&contextP->env, name); | |||
255 | if (!contextP->env.fault_occurred) { | |||
256 | XMLRPC_ASSERT(elemP != NULL)do if (!(elemP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 256); while (0); | |||
257 | ||||
258 | /* Insert the new element in the appropriate place. */ | |||
259 | if (!contextP->rootP) { | |||
260 | /* No root yet, so this element must be the root. */ | |||
261 | contextP->rootP = elemP; | |||
262 | contextP->currentP = elemP; | |||
263 | } else { | |||
264 | XMLRPC_ASSERT(contextP->currentP != NULL)do if (!(contextP->currentP != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 264); while ( 0); | |||
265 | ||||
266 | /* (We need to watch our error handling invariants | |||
267 | very carefully here. Read the docs for | |||
268 | xml_element_append_child. | |||
269 | */ | |||
270 | xml_element_append_child(&contextP->env, contextP->currentP, | |||
271 | elemP); | |||
272 | if (!contextP->env.fault_occurred) | |||
273 | contextP->currentP = elemP; | |||
274 | } | |||
275 | if (contextP->env.fault_occurred) | |||
276 | xml_element_free(elemP); | |||
277 | } | |||
278 | if (contextP->env.fault_occurred) { | |||
279 | /* Having changed *contextP to reflect failure, we are responsible | |||
280 | for undoing everything that has been done so far in this | |||
281 | context. | |||
282 | */ | |||
283 | if (contextP->rootP) | |||
284 | xml_element_free(contextP->rootP); | |||
285 | } | |||
286 | } | |||
287 | } | |||
288 | ||||
289 | ||||
290 | ||||
291 | static void | |||
292 | endElement(void * const userData, | |||
293 | XML_Char * const name ATTR_UNUSED__attribute__((__unused__))) { | |||
294 | ||||
295 | parseContext * const contextP = userData; | |||
296 | ||||
297 | XMLRPC_ASSERT(contextP != NULL)do if (!(contextP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 297); while (0); | |||
298 | XMLRPC_ASSERT(name != NULL)do if (!(name != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 298); while (0); | |||
299 | ||||
300 | if (!contextP->env.fault_occurred) { | |||
301 | /* I think Expat enforces these facts: */ | |||
302 | XMLRPC_ASSERT(xmlrpc_streq(name, contextP->currentP->_name))do if (!(xmlrpc_streq(name, contextP->currentP->_name)) ) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 302); while (0); | |||
303 | XMLRPC_ASSERT(contextP->currentP->_parent != NULL ||do if (!(contextP->currentP->_parent != ((void*)0) || contextP ->currentP == contextP->rootP)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 304); while ( 0) | |||
304 | contextP->currentP == contextP->rootP)do if (!(contextP->currentP->_parent != ((void*)0) || contextP ->currentP == contextP->rootP)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 304); while ( 0); | |||
305 | ||||
306 | /* Add a trailing NUL to our cdata. */ | |||
307 | xml_element_append_cdata(&contextP->env, contextP->currentP, "\0", 1); | |||
308 | if (!contextP->env.fault_occurred) | |||
309 | /* Pop our "stack" of elements. */ | |||
310 | contextP->currentP = contextP->currentP->_parent; | |||
311 | ||||
312 | if (contextP->env.fault_occurred) { | |||
313 | /* Having changed *contextP to reflect failure, we are responsible | |||
314 | for undoing everything that has been done so far in this | |||
315 | context. | |||
316 | */ | |||
317 | if (contextP->rootP) | |||
318 | xml_element_free(contextP->rootP); | |||
319 | } | |||
320 | } | |||
321 | } | |||
322 | ||||
323 | ||||
324 | ||||
325 | static void | |||
326 | characterData(void * const userData, | |||
327 | XML_Char * const s, | |||
328 | int const len) { | |||
329 | /*---------------------------------------------------------------------------- | |||
330 | This is an Expat character data (cdata) handler. When an Expat | |||
331 | parser comes across cdata, he calls one of these with the cdata as | |||
332 | argument. He can call it multiple times for consecutive cdata. | |||
333 | ||||
334 | We simply append the cdata to the cdata buffer for whatever XML | |||
335 | element the parser is presently parsing. | |||
336 | -----------------------------------------------------------------------------*/ | |||
337 | parseContext * const contextP = userData; | |||
338 | ||||
339 | XMLRPC_ASSERT(contextP != NULL)do if (!(contextP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 339); while (0); | |||
340 | XMLRPC_ASSERT(s != NULL)do if (!(s != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 340); while (0); | |||
341 | XMLRPC_ASSERT(len >= 0)do if (!(len >= 0)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 341); while (0); | |||
342 | ||||
343 | if (!contextP->env.fault_occurred) { | |||
344 | XMLRPC_ASSERT(contextP->currentP != NULL)do if (!(contextP->currentP != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 344); while ( 0); | |||
345 | ||||
346 | xml_element_append_cdata(&contextP->env, contextP->currentP, s, len); | |||
347 | } | |||
348 | } | |||
349 | ||||
350 | ||||
351 | ||||
352 | static void | |||
353 | createParser(xmlrpc_env * const envP, | |||
354 | parseContext * const contextP, | |||
355 | XML_Parser * const parserP) { | |||
356 | /*---------------------------------------------------------------------------- | |||
357 | Create an Expat parser to parse our XML. | |||
358 | -----------------------------------------------------------------------------*/ | |||
359 | XML_Parser parser; | |||
360 | ||||
361 | parser = xmlrpc_XML_ParserCreate(NULL((void*)0)); | |||
362 | if (parser == NULL((void*)0)) | |||
363 | xmlrpc_faultf(envP, "Could not create expat parser"); | |||
364 | else { | |||
365 | /* Initialize our parse context. */ | |||
366 | xmlrpc_env_init(&contextP->env); | |||
367 | contextP->rootP = NULL((void*)0); | |||
368 | contextP->currentP = NULL((void*)0); | |||
369 | ||||
370 | xmlrpc_XML_SetUserData(parser, contextP); | |||
371 | xmlrpc_XML_SetElementHandler( | |||
372 | parser, | |||
373 | (XML_StartElementHandler) startElement, | |||
374 | (XML_EndElementHandler) endElement); | |||
375 | xmlrpc_XML_SetCharacterDataHandler( | |||
376 | parser, | |||
377 | (XML_CharacterDataHandler) characterData); | |||
378 | } | |||
379 | *parserP = parser; | |||
380 | } | |||
381 | ||||
382 | ||||
383 | ||||
384 | static void | |||
385 | destroyParser(XML_Parser const parser, | |||
386 | parseContext * const contextP) { | |||
387 | ||||
388 | xmlrpc_env_clean(&contextP->env); | |||
389 | ||||
390 | xmlrpc_XML_ParserFree(parser); | |||
391 | } | |||
392 | ||||
393 | ||||
394 | ||||
395 | void | |||
396 | xml_parse(xmlrpc_env * const envP, | |||
397 | const char * const xmlData, | |||
398 | size_t const xmlDataLen, | |||
399 | xml_element ** const resultPP) { | |||
400 | /*---------------------------------------------------------------------------- | |||
401 | Parse the XML text 'xmlData', of length 'xmlDataLen'. Return the | |||
402 | description of the element that the XML text contains as *resultPP. | |||
403 | -----------------------------------------------------------------------------*/ | |||
404 | /* | |||
405 | This is an Expat driver. | |||
406 | ||||
407 | We set up event-based parser handlers for Expat and set Expat loose | |||
408 | on the XML. Expat walks through the XML, calling our handlers along | |||
409 | the way. Our handlers build up the element description in our | |||
410 | 'context' variable, so that when Expat is finished, our results are | |||
411 | in 'context' and we just have to pluck them out. | |||
412 | ||||
413 | We should allow the user to specify the encoding in 'xmlData', but | |||
414 | we don't. | |||
415 | */ | |||
416 | XML_Parser parser; | |||
417 | parseContext context; | |||
418 | ||||
419 | 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_expat.c", 419); while ( 0); | |||
420 | XMLRPC_ASSERT(xmlData != NULL)do if (!(xmlData != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c" , 420); while (0); | |||
421 | ||||
422 | createParser(envP, &context, &parser); | |||
423 | ||||
424 | if (!envP->fault_occurred) { | |||
| ||||
425 | bool ok; | |||
426 | ||||
427 | ok = xmlrpc_XML_Parse(parser, xmlData, xmlDataLen, 1); | |||
428 | /* sets 'context', *envP */ | |||
429 | if (!ok) { | |||
430 | /* Expat failed on its own to parse it -- this is not an error | |||
431 | that our handlers detected. | |||
432 | */ | |||
433 | xmlrpc_env_set_fault( | |||
434 | envP, XMLRPC_PARSE_ERROR(-503), | |||
435 | xmlrpc_XML_GetErrorString(parser)); | |||
436 | if (!context.env.fault_occurred) { | |||
437 | /* Have to clean up what our handlers built before Expat | |||
438 | barfed. | |||
439 | */ | |||
440 | if (context.rootP) | |||
441 | xml_element_free(context.rootP); | |||
442 | } | |||
443 | } else { | |||
444 | /* Expat got through the XML OK, but when it called our handlers, | |||
445 | they might have detected a problem. They would have noted | |||
446 | such a problem in *contextP. | |||
447 | */ | |||
448 | if (context.env.fault_occurred) | |||
449 | xmlrpc_env_set_fault_formatted( | |||
450 | envP, context.env.fault_code, | |||
451 | "XML doesn't parse. %s", context.env.fault_string); | |||
452 | else { | |||
453 | XMLRPC_ASSERT(context.rootP != NULL)do if (!(context.rootP != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 453); while ( 0); | |||
454 | XMLRPC_ASSERT(context.currentP == NULL)do if (!(context.currentP == ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_expat.c", 454); while ( 0); | |||
455 | ||||
456 | *resultPP = context.rootP; | |||
457 | } | |||
458 | } | |||
459 | destroyParser(parser, &context); | |||
460 | } | |||
461 | } | |||
462 | ||||
463 | ||||
464 | /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. | |||
465 | ** | |||
466 | ** Redistribution and use in source and binary forms, with or without | |||
467 | ** modification, are permitted provided that the following conditions | |||
468 | ** are met: | |||
469 | ** 1. Redistributions of source code must retain the above copyright | |||
470 | ** notice, this list of conditions and the following disclaimer. | |||
471 | ** 2. Redistributions in binary form must reproduce the above copyright | |||
472 | ** notice, this list of conditions and the following disclaimer in the | |||
473 | ** documentation and/or other materials provided with the distribution. | |||
474 | ** 3. The name of the author may not be used to endorse or promote products | |||
475 | ** derived from this software without specific prior written permission. | |||
476 | ** | |||
477 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
478 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
479 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
480 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
481 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
482 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
483 | ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
484 | ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
485 | ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
486 | ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
487 | ** SUCH DAMAGE. */ |