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