File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_expat.c |
Location: | line 424, column 10 |
Description: | Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP') |
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. */ |