| 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. */ |