Branch data Line data Source code
1 : : #include "Python.h"
2 : : #include <ctype.h>
3 : :
4 : : #include "structmember.h" // PyMemberDef
5 : : #include "expat.h"
6 : :
7 : : #include "pyexpat.h"
8 : :
9 : : /* Do not emit Clinic output to a file as that wreaks havoc with conditionally
10 : : included methods. */
11 : : /*[clinic input]
12 : : module pyexpat
13 : : [clinic start generated code]*/
14 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b168d503a4490c15]*/
15 : :
16 : : #define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION)
17 : :
18 : : static XML_Memory_Handling_Suite ExpatMemoryHandler = {
19 : : PyObject_Malloc, PyObject_Realloc, PyObject_Free};
20 : :
21 : : enum HandlerTypes {
22 : : StartElement,
23 : : EndElement,
24 : : ProcessingInstruction,
25 : : CharacterData,
26 : : UnparsedEntityDecl,
27 : : NotationDecl,
28 : : StartNamespaceDecl,
29 : : EndNamespaceDecl,
30 : : Comment,
31 : : StartCdataSection,
32 : : EndCdataSection,
33 : : Default,
34 : : DefaultHandlerExpand,
35 : : NotStandalone,
36 : : ExternalEntityRef,
37 : : StartDoctypeDecl,
38 : : EndDoctypeDecl,
39 : : EntityDecl,
40 : : XmlDecl,
41 : : ElementDecl,
42 : : AttlistDecl,
43 : : #if XML_COMBINED_VERSION >= 19504
44 : : SkippedEntity,
45 : : #endif
46 : : _DummyDecl
47 : : };
48 : :
49 : : typedef struct {
50 : : PyTypeObject *xml_parse_type;
51 : : PyObject *error;
52 : : PyObject *str_read;
53 : : } pyexpat_state;
54 : :
55 : : static inline pyexpat_state*
56 : 18 : pyexpat_get_state(PyObject *module)
57 : : {
58 : 18 : void *state = PyModule_GetState(module);
59 : : assert(state != NULL);
60 : 18 : return (pyexpat_state *)state;
61 : : }
62 : :
63 : : /* ----------------------------------------------------- */
64 : :
65 : : /* Declarations for objects of type xmlparser */
66 : :
67 : : typedef struct {
68 : : PyObject_HEAD
69 : :
70 : : XML_Parser itself;
71 : : int ordered_attributes; /* Return attributes as a list. */
72 : : int specified_attributes; /* Report only specified attributes. */
73 : : int in_callback; /* Is a callback active? */
74 : : int ns_prefixes; /* Namespace-triplets mode? */
75 : : XML_Char *buffer; /* Buffer used when accumulating characters */
76 : : /* NULL if not enabled */
77 : : int buffer_size; /* Size of buffer, in XML_Char units */
78 : : int buffer_used; /* Buffer units in use */
79 : : PyObject *intern; /* Dictionary to intern strings */
80 : : PyObject **handlers;
81 : : } xmlparseobject;
82 : :
83 : : #include "clinic/pyexpat.c.h"
84 : :
85 : : #define CHARACTER_DATA_BUFFER_SIZE 8192
86 : :
87 : : typedef void (*xmlhandlersetter)(XML_Parser self, void *meth);
88 : : typedef void* xmlhandler;
89 : :
90 : : struct HandlerInfo {
91 : : const char *name;
92 : : xmlhandlersetter setter;
93 : : xmlhandler handler;
94 : : PyGetSetDef getset;
95 : : };
96 : :
97 : : static struct HandlerInfo handler_info[64];
98 : :
99 : : /* Set an integer attribute on the error object; return true on success,
100 : : * false on an exception.
101 : : */
102 : : static int
103 : 0 : set_error_attr(PyObject *err, const char *name, int value)
104 : : {
105 : 0 : PyObject *v = PyLong_FromLong(value);
106 : :
107 [ # # # # ]: 0 : if (v == NULL || PyObject_SetAttrString(err, name, v) == -1) {
108 : 0 : Py_XDECREF(v);
109 : 0 : return 0;
110 : : }
111 : 0 : Py_DECREF(v);
112 : 0 : return 1;
113 : : }
114 : :
115 : : /* Build and set an Expat exception, including positioning
116 : : * information. Always returns NULL.
117 : : */
118 : : static PyObject *
119 : 0 : set_error(pyexpat_state *state, xmlparseobject *self, enum XML_Error code)
120 : : {
121 : : PyObject *err;
122 : : PyObject *buffer;
123 : 0 : XML_Parser parser = self->itself;
124 : 0 : int lineno = XML_GetErrorLineNumber(parser);
125 : 0 : int column = XML_GetErrorColumnNumber(parser);
126 : :
127 : 0 : buffer = PyUnicode_FromFormat("%s: line %i, column %i",
128 : : XML_ErrorString(code), lineno, column);
129 [ # # ]: 0 : if (buffer == NULL)
130 : 0 : return NULL;
131 : 0 : err = PyObject_CallOneArg(state->error, buffer);
132 : 0 : Py_DECREF(buffer);
133 [ # # ]: 0 : if ( err != NULL
134 [ # # ]: 0 : && set_error_attr(err, "code", code)
135 [ # # ]: 0 : && set_error_attr(err, "offset", column)
136 [ # # ]: 0 : && set_error_attr(err, "lineno", lineno)) {
137 : 0 : PyErr_SetObject(state->error, err);
138 : : }
139 : 0 : Py_XDECREF(err);
140 : 0 : return NULL;
141 : : }
142 : :
143 : : static int
144 : 0 : have_handler(xmlparseobject *self, int type)
145 : : {
146 : 0 : PyObject *handler = self->handlers[type];
147 : 0 : return handler != NULL;
148 : : }
149 : :
150 : : /* Convert a string of XML_Chars into a Unicode string.
151 : : Returns None if str is a null pointer. */
152 : :
153 : : static PyObject *
154 : 0 : conv_string_to_unicode(const XML_Char *str)
155 : : {
156 : : /* XXX currently this code assumes that XML_Char is 8-bit,
157 : : and hence in UTF-8. */
158 : : /* UTF-8 from Expat, Unicode desired */
159 [ # # ]: 0 : if (str == NULL) {
160 : 0 : Py_RETURN_NONE;
161 : : }
162 : 0 : return PyUnicode_DecodeUTF8(str, strlen(str), "strict");
163 : : }
164 : :
165 : : static PyObject *
166 : 0 : conv_string_len_to_unicode(const XML_Char *str, int len)
167 : : {
168 : : /* XXX currently this code assumes that XML_Char is 8-bit,
169 : : and hence in UTF-8. */
170 : : /* UTF-8 from Expat, Unicode desired */
171 [ # # ]: 0 : if (str == NULL) {
172 : 0 : Py_RETURN_NONE;
173 : : }
174 : 0 : return PyUnicode_DecodeUTF8((const char *)str, len, "strict");
175 : : }
176 : :
177 : : /* Callback routines */
178 : :
179 : : static void clear_handlers(xmlparseobject *self, int initial);
180 : :
181 : : /* This handler is used when an error has been detected, in the hope
182 : : that actual parsing can be terminated early. This will only help
183 : : if an external entity reference is encountered. */
184 : : static int
185 : 0 : error_external_entity_ref_handler(XML_Parser parser,
186 : : const XML_Char *context,
187 : : const XML_Char *base,
188 : : const XML_Char *systemId,
189 : : const XML_Char *publicId)
190 : : {
191 : 0 : return 0;
192 : : }
193 : :
194 : : /* Dummy character data handler used when an error (exception) has
195 : : been detected, and the actual parsing can be terminated early.
196 : : This is needed since character data handler can't be safely removed
197 : : from within the character data handler, but can be replaced. It is
198 : : used only from the character data handler trampoline, and must be
199 : : used right after `flag_error()` is called. */
200 : : static void
201 : 0 : noop_character_data_handler(void *userData, const XML_Char *data, int len)
202 : : {
203 : : /* Do nothing. */
204 : 0 : }
205 : :
206 : : static void
207 : 0 : flag_error(xmlparseobject *self)
208 : : {
209 : 0 : clear_handlers(self, 0);
210 : 0 : XML_SetExternalEntityRefHandler(self->itself,
211 : : error_external_entity_ref_handler);
212 : 0 : }
213 : :
214 : : static PyObject*
215 : 0 : call_with_frame(const char *funcname, int lineno, PyObject* func, PyObject* args,
216 : : xmlparseobject *self)
217 : : {
218 : : PyObject *res;
219 : :
220 : 0 : res = PyObject_Call(func, args, NULL);
221 [ # # ]: 0 : if (res == NULL) {
222 : 0 : _PyTraceback_Add(funcname, __FILE__, lineno);
223 : 0 : XML_StopParser(self->itself, XML_FALSE);
224 : : }
225 : 0 : return res;
226 : : }
227 : :
228 : : static PyObject*
229 : 0 : string_intern(xmlparseobject *self, const char* str)
230 : : {
231 : 0 : PyObject *result = conv_string_to_unicode(str);
232 : : PyObject *value;
233 : : /* result can be NULL if the unicode conversion failed. */
234 [ # # ]: 0 : if (!result)
235 : 0 : return result;
236 [ # # ]: 0 : if (!self->intern)
237 : 0 : return result;
238 : 0 : value = PyDict_GetItemWithError(self->intern, result);
239 [ # # ]: 0 : if (!value) {
240 [ # # # # ]: 0 : if (!PyErr_Occurred() &&
241 : 0 : PyDict_SetItem(self->intern, result, result) == 0)
242 : : {
243 : 0 : return result;
244 : : }
245 : : else {
246 : 0 : Py_DECREF(result);
247 : 0 : return NULL;
248 : : }
249 : : }
250 : 0 : Py_INCREF(value);
251 : 0 : Py_DECREF(result);
252 : 0 : return value;
253 : : }
254 : :
255 : : /* Return 0 on success, -1 on exception.
256 : : * flag_error() will be called before return if needed.
257 : : */
258 : : static int
259 : 0 : call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len)
260 : : {
261 : : PyObject *args;
262 : : PyObject *temp;
263 : :
264 [ # # ]: 0 : if (!have_handler(self, CharacterData))
265 : 0 : return -1;
266 : :
267 : 0 : args = PyTuple_New(1);
268 [ # # ]: 0 : if (args == NULL)
269 : 0 : return -1;
270 : 0 : temp = (conv_string_len_to_unicode(buffer, len));
271 [ # # ]: 0 : if (temp == NULL) {
272 : 0 : Py_DECREF(args);
273 : 0 : flag_error(self);
274 : 0 : XML_SetCharacterDataHandler(self->itself,
275 : : noop_character_data_handler);
276 : 0 : return -1;
277 : : }
278 : 0 : PyTuple_SET_ITEM(args, 0, temp);
279 : : /* temp is now a borrowed reference; consider it unused. */
280 : 0 : self->in_callback = 1;
281 : 0 : temp = call_with_frame("CharacterData", __LINE__,
282 : 0 : self->handlers[CharacterData], args, self);
283 : : /* temp is an owned reference again, or NULL */
284 : 0 : self->in_callback = 0;
285 : 0 : Py_DECREF(args);
286 [ # # ]: 0 : if (temp == NULL) {
287 : 0 : flag_error(self);
288 : 0 : XML_SetCharacterDataHandler(self->itself,
289 : : noop_character_data_handler);
290 : 0 : return -1;
291 : : }
292 : 0 : Py_DECREF(temp);
293 : 0 : return 0;
294 : : }
295 : :
296 : : static int
297 : 0 : flush_character_buffer(xmlparseobject *self)
298 : : {
299 : : int rc;
300 [ # # # # ]: 0 : if (self->buffer == NULL || self->buffer_used == 0)
301 : 0 : return 0;
302 : 0 : rc = call_character_handler(self, self->buffer, self->buffer_used);
303 : 0 : self->buffer_used = 0;
304 : 0 : return rc;
305 : : }
306 : :
307 : : static void
308 : 0 : my_CharacterDataHandler(void *userData, const XML_Char *data, int len)
309 : : {
310 : 0 : xmlparseobject *self = (xmlparseobject *) userData;
311 : :
312 [ # # ]: 0 : if (PyErr_Occurred())
313 : 0 : return;
314 : :
315 [ # # ]: 0 : if (self->buffer == NULL)
316 : 0 : call_character_handler(self, data, len);
317 : : else {
318 [ # # ]: 0 : if ((self->buffer_used + len) > self->buffer_size) {
319 [ # # ]: 0 : if (flush_character_buffer(self) < 0)
320 : 0 : return;
321 : : /* handler might have changed; drop the rest on the floor
322 : : * if there isn't a handler anymore
323 : : */
324 [ # # ]: 0 : if (!have_handler(self, CharacterData))
325 : 0 : return;
326 : : }
327 [ # # ]: 0 : if (len > self->buffer_size) {
328 : 0 : call_character_handler(self, data, len);
329 : 0 : self->buffer_used = 0;
330 : : }
331 : : else {
332 : 0 : memcpy(self->buffer + self->buffer_used,
333 : : data, len * sizeof(XML_Char));
334 : 0 : self->buffer_used += len;
335 : : }
336 : : }
337 : : }
338 : :
339 : : static void
340 : 0 : my_StartElementHandler(void *userData,
341 : : const XML_Char *name, const XML_Char *atts[])
342 : : {
343 : 0 : xmlparseobject *self = (xmlparseobject *)userData;
344 : :
345 [ # # ]: 0 : if (have_handler(self, StartElement)) {
346 : : PyObject *container, *rv, *args;
347 : : int i, max;
348 : :
349 [ # # ]: 0 : if (PyErr_Occurred())
350 : 0 : return;
351 : :
352 [ # # ]: 0 : if (flush_character_buffer(self) < 0)
353 : 0 : return;
354 : : /* Set max to the number of slots filled in atts[]; max/2 is
355 : : * the number of attributes we need to process.
356 : : */
357 [ # # ]: 0 : if (self->specified_attributes) {
358 : 0 : max = XML_GetSpecifiedAttributeCount(self->itself);
359 : : }
360 : : else {
361 : 0 : max = 0;
362 [ # # ]: 0 : while (atts[max] != NULL)
363 : 0 : max += 2;
364 : : }
365 : : /* Build the container. */
366 [ # # ]: 0 : if (self->ordered_attributes)
367 : 0 : container = PyList_New(max);
368 : : else
369 : 0 : container = PyDict_New();
370 [ # # ]: 0 : if (container == NULL) {
371 : 0 : flag_error(self);
372 : 0 : return;
373 : : }
374 [ # # ]: 0 : for (i = 0; i < max; i += 2) {
375 : 0 : PyObject *n = string_intern(self, (XML_Char *) atts[i]);
376 : : PyObject *v;
377 [ # # ]: 0 : if (n == NULL) {
378 : 0 : flag_error(self);
379 : 0 : Py_DECREF(container);
380 : 0 : return;
381 : : }
382 : 0 : v = conv_string_to_unicode((XML_Char *) atts[i+1]);
383 [ # # ]: 0 : if (v == NULL) {
384 : 0 : flag_error(self);
385 : 0 : Py_DECREF(container);
386 : 0 : Py_DECREF(n);
387 : 0 : return;
388 : : }
389 [ # # ]: 0 : if (self->ordered_attributes) {
390 : 0 : PyList_SET_ITEM(container, i, n);
391 : 0 : PyList_SET_ITEM(container, i+1, v);
392 : : }
393 [ # # ]: 0 : else if (PyDict_SetItem(container, n, v)) {
394 : 0 : flag_error(self);
395 : 0 : Py_DECREF(n);
396 : 0 : Py_DECREF(v);
397 : 0 : Py_DECREF(container);
398 : 0 : return;
399 : : }
400 : : else {
401 : 0 : Py_DECREF(n);
402 : 0 : Py_DECREF(v);
403 : : }
404 : : }
405 : 0 : args = string_intern(self, name);
406 [ # # ]: 0 : if (args == NULL) {
407 : 0 : Py_DECREF(container);
408 : 0 : return;
409 : : }
410 : 0 : args = Py_BuildValue("(NN)", args, container);
411 [ # # ]: 0 : if (args == NULL) {
412 : 0 : return;
413 : : }
414 : : /* Container is now a borrowed reference; ignore it. */
415 : 0 : self->in_callback = 1;
416 : 0 : rv = call_with_frame("StartElement", __LINE__,
417 : 0 : self->handlers[StartElement], args, self);
418 : 0 : self->in_callback = 0;
419 : 0 : Py_DECREF(args);
420 [ # # ]: 0 : if (rv == NULL) {
421 : 0 : flag_error(self);
422 : 0 : return;
423 : : }
424 : 0 : Py_DECREF(rv);
425 : : }
426 : : }
427 : :
428 : : #define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \
429 : : RETURN, GETUSERDATA) \
430 : : static RC \
431 : : my_##NAME##Handler PARAMS {\
432 : : xmlparseobject *self = GETUSERDATA ; \
433 : : PyObject *args = NULL; \
434 : : PyObject *rv = NULL; \
435 : : INIT \
436 : : \
437 : : if (have_handler(self, NAME)) { \
438 : : if (PyErr_Occurred()) \
439 : : return RETURN; \
440 : : if (flush_character_buffer(self) < 0) \
441 : : return RETURN; \
442 : : args = Py_BuildValue PARAM_FORMAT ;\
443 : : if (!args) { flag_error(self); return RETURN;} \
444 : : self->in_callback = 1; \
445 : : rv = call_with_frame(#NAME,__LINE__, \
446 : : self->handlers[NAME], args, self); \
447 : : self->in_callback = 0; \
448 : : Py_DECREF(args); \
449 : : if (rv == NULL) { \
450 : : flag_error(self); \
451 : : return RETURN; \
452 : : } \
453 : : CONVERSION \
454 : : Py_DECREF(rv); \
455 : : } \
456 : : return RETURN; \
457 : : }
458 : :
459 : : #define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \
460 : : RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\
461 : : (xmlparseobject *)userData)
462 : :
463 : : #define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\
464 : : RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \
465 : : rc = PyLong_AsLong(rv);, rc, \
466 : : (xmlparseobject *)userData)
467 : :
468 [ # # # # : 0 : VOID_HANDLER(EndElement,
# # # # #
# ]
469 : : (void *userData, const XML_Char *name),
470 : : ("(N)", string_intern(self, name)))
471 : :
472 [ # # # # : 0 : VOID_HANDLER(ProcessingInstruction,
# # # # #
# ]
473 : : (void *userData,
474 : : const XML_Char *target,
475 : : const XML_Char *data),
476 : : ("(NO&)", string_intern(self, target), conv_string_to_unicode ,data))
477 : :
478 [ # # # # : 0 : VOID_HANDLER(UnparsedEntityDecl,
# # # # #
# ]
479 : : (void *userData,
480 : : const XML_Char *entityName,
481 : : const XML_Char *base,
482 : : const XML_Char *systemId,
483 : : const XML_Char *publicId,
484 : : const XML_Char *notationName),
485 : : ("(NNNNN)",
486 : : string_intern(self, entityName), string_intern(self, base),
487 : : string_intern(self, systemId), string_intern(self, publicId),
488 : : string_intern(self, notationName)))
489 : :
490 [ # # # # : 0 : VOID_HANDLER(EntityDecl,
# # # # #
# ]
491 : : (void *userData,
492 : : const XML_Char *entityName,
493 : : int is_parameter_entity,
494 : : const XML_Char *value,
495 : : int value_length,
496 : : const XML_Char *base,
497 : : const XML_Char *systemId,
498 : : const XML_Char *publicId,
499 : : const XML_Char *notationName),
500 : : ("NiNNNNN",
501 : : string_intern(self, entityName), is_parameter_entity,
502 : : (conv_string_len_to_unicode(value, value_length)),
503 : : string_intern(self, base), string_intern(self, systemId),
504 : : string_intern(self, publicId),
505 : : string_intern(self, notationName)))
506 : :
507 [ # # # # : 0 : VOID_HANDLER(XmlDecl,
# # # # #
# ]
508 : : (void *userData,
509 : : const XML_Char *version,
510 : : const XML_Char *encoding,
511 : : int standalone),
512 : : ("(O&O&i)",
513 : : conv_string_to_unicode ,version, conv_string_to_unicode ,encoding,
514 : : standalone))
515 : :
516 : : static PyObject *
517 : 0 : conv_content_model(XML_Content * const model,
518 : : PyObject *(*conv_string)(const XML_Char *))
519 : : {
520 : 0 : PyObject *result = NULL;
521 : 0 : PyObject *children = PyTuple_New(model->numchildren);
522 : : int i;
523 : :
524 [ # # ]: 0 : if (children != NULL) {
525 : : assert(model->numchildren < INT_MAX);
526 [ # # ]: 0 : for (i = 0; i < (int)model->numchildren; ++i) {
527 : 0 : PyObject *child = conv_content_model(&model->children[i],
528 : : conv_string);
529 [ # # ]: 0 : if (child == NULL) {
530 : 0 : Py_XDECREF(children);
531 : 0 : return NULL;
532 : : }
533 : 0 : PyTuple_SET_ITEM(children, i, child);
534 : : }
535 : 0 : result = Py_BuildValue("(iiO&N)",
536 : 0 : model->type, model->quant,
537 : : conv_string,model->name, children);
538 : : }
539 : 0 : return result;
540 : : }
541 : :
542 : : static void
543 : 0 : my_ElementDeclHandler(void *userData,
544 : : const XML_Char *name,
545 : : XML_Content *model)
546 : : {
547 : 0 : xmlparseobject *self = (xmlparseobject *)userData;
548 : 0 : PyObject *args = NULL;
549 : :
550 [ # # ]: 0 : if (have_handler(self, ElementDecl)) {
551 : 0 : PyObject *rv = NULL;
552 : : PyObject *modelobj, *nameobj;
553 : :
554 [ # # ]: 0 : if (PyErr_Occurred())
555 : 0 : return;
556 : :
557 [ # # ]: 0 : if (flush_character_buffer(self) < 0)
558 : 0 : goto finally;
559 : 0 : modelobj = conv_content_model(model, (conv_string_to_unicode));
560 [ # # ]: 0 : if (modelobj == NULL) {
561 : 0 : flag_error(self);
562 : 0 : goto finally;
563 : : }
564 : 0 : nameobj = string_intern(self, name);
565 [ # # ]: 0 : if (nameobj == NULL) {
566 : 0 : Py_DECREF(modelobj);
567 : 0 : flag_error(self);
568 : 0 : goto finally;
569 : : }
570 : 0 : args = Py_BuildValue("NN", nameobj, modelobj);
571 [ # # ]: 0 : if (args == NULL) {
572 : 0 : flag_error(self);
573 : 0 : goto finally;
574 : : }
575 : 0 : self->in_callback = 1;
576 : 0 : rv = call_with_frame("ElementDecl", __LINE__,
577 : 0 : self->handlers[ElementDecl], args, self);
578 : 0 : self->in_callback = 0;
579 [ # # ]: 0 : if (rv == NULL) {
580 : 0 : flag_error(self);
581 : 0 : goto finally;
582 : : }
583 : 0 : Py_DECREF(rv);
584 : : }
585 : 0 : finally:
586 : 0 : Py_XDECREF(args);
587 : 0 : XML_FreeContentModel(self->itself, model);
588 : 0 : return;
589 : : }
590 : :
591 [ # # # # : 0 : VOID_HANDLER(AttlistDecl,
# # # # #
# ]
592 : : (void *userData,
593 : : const XML_Char *elname,
594 : : const XML_Char *attname,
595 : : const XML_Char *att_type,
596 : : const XML_Char *dflt,
597 : : int isrequired),
598 : : ("(NNO&O&i)",
599 : : string_intern(self, elname), string_intern(self, attname),
600 : : conv_string_to_unicode ,att_type, conv_string_to_unicode ,dflt,
601 : : isrequired))
602 : :
603 : : #if XML_COMBINED_VERSION >= 19504
604 [ # # # # : 0 : VOID_HANDLER(SkippedEntity,
# # # # #
# ]
605 : : (void *userData,
606 : : const XML_Char *entityName,
607 : : int is_parameter_entity),
608 : : ("Ni",
609 : : string_intern(self, entityName), is_parameter_entity))
610 : : #endif
611 : :
612 [ # # # # : 0 : VOID_HANDLER(NotationDecl,
# # # # #
# ]
613 : : (void *userData,
614 : : const XML_Char *notationName,
615 : : const XML_Char *base,
616 : : const XML_Char *systemId,
617 : : const XML_Char *publicId),
618 : : ("(NNNN)",
619 : : string_intern(self, notationName), string_intern(self, base),
620 : : string_intern(self, systemId), string_intern(self, publicId)))
621 : :
622 [ # # # # : 0 : VOID_HANDLER(StartNamespaceDecl,
# # # # #
# ]
623 : : (void *userData,
624 : : const XML_Char *prefix,
625 : : const XML_Char *uri),
626 : : ("(NN)",
627 : : string_intern(self, prefix), string_intern(self, uri)))
628 : :
629 [ # # # # : 0 : VOID_HANDLER(EndNamespaceDecl,
# # # # #
# ]
630 : : (void *userData,
631 : : const XML_Char *prefix),
632 : : ("(N)", string_intern(self, prefix)))
633 : :
634 [ # # # # : 0 : VOID_HANDLER(Comment,
# # # # #
# ]
635 : : (void *userData, const XML_Char *data),
636 : : ("(O&)", conv_string_to_unicode ,data))
637 : :
638 [ # # # # : 0 : VOID_HANDLER(StartCdataSection,
# # # # #
# ]
639 : : (void *userData),
640 : : ("()"))
641 : :
642 [ # # # # : 0 : VOID_HANDLER(EndCdataSection,
# # # # #
# ]
643 : : (void *userData),
644 : : ("()"))
645 : :
646 [ # # # # : 0 : VOID_HANDLER(Default,
# # # # #
# ]
647 : : (void *userData, const XML_Char *s, int len),
648 : : ("(N)", (conv_string_len_to_unicode(s,len))))
649 : :
650 [ # # # # : 0 : VOID_HANDLER(DefaultHandlerExpand,
# # # # #
# ]
651 : : (void *userData, const XML_Char *s, int len),
652 : : ("(N)", (conv_string_len_to_unicode(s,len))))
653 : : #define my_DefaultHandlerExpand my_DefaultHandlerExpandHandler
654 : :
655 [ # # # # : 0 : INT_HANDLER(NotStandalone,
# # # # #
# ]
656 : : (void *userData),
657 : : ("()"))
658 : :
659 [ # # # # : 0 : RC_HANDLER(int, ExternalEntityRef,
# # # # #
# ]
660 : : (XML_Parser parser,
661 : : const XML_Char *context,
662 : : const XML_Char *base,
663 : : const XML_Char *systemId,
664 : : const XML_Char *publicId),
665 : : int rc=0;,
666 : : ("(O&NNN)",
667 : : conv_string_to_unicode ,context, string_intern(self, base),
668 : : string_intern(self, systemId), string_intern(self, publicId)),
669 : : rc = PyLong_AsLong(rv);, rc,
670 : : XML_GetUserData(parser))
671 : :
672 : : /* XXX UnknownEncodingHandler */
673 : :
674 [ # # # # : 0 : VOID_HANDLER(StartDoctypeDecl,
# # # # #
# ]
675 : : (void *userData, const XML_Char *doctypeName,
676 : : const XML_Char *sysid, const XML_Char *pubid,
677 : : int has_internal_subset),
678 : : ("(NNNi)", string_intern(self, doctypeName),
679 : : string_intern(self, sysid), string_intern(self, pubid),
680 : : has_internal_subset))
681 : :
682 [ # # # # : 0 : VOID_HANDLER(EndDoctypeDecl, (void *userData), ("()"))
# # # # #
# ]
683 : :
684 : : /* ---------------------------------------------------------------- */
685 : : /*[clinic input]
686 : : class pyexpat.xmlparser "xmlparseobject *" "&Xmlparsetype"
687 : : [clinic start generated code]*/
688 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=2393162385232e1c]*/
689 : :
690 : :
691 : : static PyObject *
692 : 0 : get_parse_result(pyexpat_state *state, xmlparseobject *self, int rv)
693 : : {
694 [ # # ]: 0 : if (PyErr_Occurred()) {
695 : 0 : return NULL;
696 : : }
697 [ # # ]: 0 : if (rv == 0) {
698 : 0 : return set_error(state, self, XML_GetErrorCode(self->itself));
699 : : }
700 [ # # ]: 0 : if (flush_character_buffer(self) < 0) {
701 : 0 : return NULL;
702 : : }
703 : 0 : return PyLong_FromLong(rv);
704 : : }
705 : :
706 : : #define MAX_CHUNK_SIZE (1 << 20)
707 : :
708 : : /*[clinic input]
709 : : pyexpat.xmlparser.Parse
710 : :
711 : : cls: defining_class
712 : : data: object
713 : : isfinal: bool = False
714 : : /
715 : :
716 : : Parse XML data.
717 : :
718 : : `isfinal' should be true at end of input.
719 : : [clinic start generated code]*/
720 : :
721 : : static PyObject *
722 : 0 : pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls,
723 : : PyObject *data, int isfinal)
724 : : /*[clinic end generated code: output=8faffe07fe1f862a input=d0eb2a69fab3b9f1]*/
725 : : {
726 : : const char *s;
727 : : Py_ssize_t slen;
728 : : Py_buffer view;
729 : : int rc;
730 : 0 : pyexpat_state *state = PyType_GetModuleState(cls);
731 : :
732 [ # # ]: 0 : if (PyUnicode_Check(data)) {
733 : 0 : view.buf = NULL;
734 : 0 : s = PyUnicode_AsUTF8AndSize(data, &slen);
735 [ # # ]: 0 : if (s == NULL)
736 : 0 : return NULL;
737 : : /* Explicitly set UTF-8 encoding. Return code ignored. */
738 : 0 : (void)XML_SetEncoding(self->itself, "utf-8");
739 : : }
740 : : else {
741 [ # # ]: 0 : if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0)
742 : 0 : return NULL;
743 : 0 : s = view.buf;
744 : 0 : slen = view.len;
745 : : }
746 : :
747 : : static_assert(MAX_CHUNK_SIZE <= INT_MAX,
748 : : "MAX_CHUNK_SIZE is larger than INT_MAX");
749 [ # # ]: 0 : while (slen > MAX_CHUNK_SIZE) {
750 : 0 : rc = XML_Parse(self->itself, s, MAX_CHUNK_SIZE, 0);
751 [ # # ]: 0 : if (!rc)
752 : 0 : goto done;
753 : 0 : s += MAX_CHUNK_SIZE;
754 : 0 : slen -= MAX_CHUNK_SIZE;
755 : : }
756 : :
757 : : assert(slen <= INT_MAX);
758 : 0 : rc = XML_Parse(self->itself, s, (int)slen, isfinal);
759 : :
760 : 0 : done:
761 [ # # ]: 0 : if (view.buf != NULL) {
762 : 0 : PyBuffer_Release(&view);
763 : : }
764 : 0 : return get_parse_result(state, self, rc);
765 : : }
766 : :
767 : : /* File reading copied from cPickle */
768 : :
769 : : #define BUF_SIZE 2048
770 : :
771 : : static int
772 : 0 : readinst(char *buf, int buf_size, PyObject *meth)
773 : : {
774 : : PyObject *str;
775 : : Py_ssize_t len;
776 : : const char *ptr;
777 : :
778 : 0 : str = PyObject_CallFunction(meth, "i", buf_size);
779 [ # # ]: 0 : if (str == NULL)
780 : 0 : goto error;
781 : :
782 [ # # ]: 0 : if (PyBytes_Check(str))
783 : 0 : ptr = PyBytes_AS_STRING(str);
784 [ # # ]: 0 : else if (PyByteArray_Check(str))
785 : 0 : ptr = PyByteArray_AS_STRING(str);
786 : : else {
787 : 0 : PyErr_Format(PyExc_TypeError,
788 : : "read() did not return a bytes object (type=%.400s)",
789 : 0 : Py_TYPE(str)->tp_name);
790 : 0 : goto error;
791 : : }
792 : 0 : len = Py_SIZE(str);
793 [ # # ]: 0 : if (len > buf_size) {
794 : 0 : PyErr_Format(PyExc_ValueError,
795 : : "read() returned too much data: "
796 : : "%i bytes requested, %zd returned",
797 : : buf_size, len);
798 : 0 : goto error;
799 : : }
800 : 0 : memcpy(buf, ptr, len);
801 : 0 : Py_DECREF(str);
802 : : /* len <= buf_size <= INT_MAX */
803 : 0 : return (int)len;
804 : :
805 : 0 : error:
806 : 0 : Py_XDECREF(str);
807 : 0 : return -1;
808 : : }
809 : :
810 : : /*[clinic input]
811 : : pyexpat.xmlparser.ParseFile
812 : :
813 : : cls: defining_class
814 : : file: object
815 : : /
816 : :
817 : : Parse XML data from file-like object.
818 : : [clinic start generated code]*/
819 : :
820 : : static PyObject *
821 : 0 : pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls,
822 : : PyObject *file)
823 : : /*[clinic end generated code: output=34780a094c8ca3ae input=ba4bc9c541684793]*/
824 : : {
825 : 0 : int rv = 1;
826 : 0 : PyObject *readmethod = NULL;
827 : :
828 : 0 : pyexpat_state *state = PyType_GetModuleState(cls);
829 : :
830 [ # # ]: 0 : if (_PyObject_LookupAttr(file, state->str_read, &readmethod) < 0) {
831 : 0 : return NULL;
832 : : }
833 [ # # ]: 0 : if (readmethod == NULL) {
834 : 0 : PyErr_SetString(PyExc_TypeError,
835 : : "argument must have 'read' attribute");
836 : 0 : return NULL;
837 : : }
838 : 0 : for (;;) {
839 : : int bytes_read;
840 : 0 : void *buf = XML_GetBuffer(self->itself, BUF_SIZE);
841 [ # # ]: 0 : if (buf == NULL) {
842 : 0 : Py_XDECREF(readmethod);
843 : 0 : return get_parse_result(state, self, 0);
844 : : }
845 : :
846 : 0 : bytes_read = readinst(buf, BUF_SIZE, readmethod);
847 [ # # ]: 0 : if (bytes_read < 0) {
848 : 0 : Py_DECREF(readmethod);
849 : 0 : return NULL;
850 : : }
851 : 0 : rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0);
852 [ # # ]: 0 : if (PyErr_Occurred()) {
853 : 0 : Py_XDECREF(readmethod);
854 : 0 : return NULL;
855 : : }
856 : :
857 [ # # # # ]: 0 : if (!rv || bytes_read == 0)
858 : : break;
859 : : }
860 : 0 : Py_XDECREF(readmethod);
861 : 0 : return get_parse_result(state, self, rv);
862 : : }
863 : :
864 : : /*[clinic input]
865 : : pyexpat.xmlparser.SetBase
866 : :
867 : : base: str
868 : : /
869 : :
870 : : Set the base URL for the parser.
871 : : [clinic start generated code]*/
872 : :
873 : : static PyObject *
874 : 0 : pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base)
875 : : /*[clinic end generated code: output=c212ddceb607b539 input=c684e5de895ee1a8]*/
876 : : {
877 [ # # ]: 0 : if (!XML_SetBase(self->itself, base)) {
878 : 0 : return PyErr_NoMemory();
879 : : }
880 : 0 : Py_RETURN_NONE;
881 : : }
882 : :
883 : : /*[clinic input]
884 : : pyexpat.xmlparser.GetBase
885 : :
886 : : Return base URL string for the parser.
887 : : [clinic start generated code]*/
888 : :
889 : : static PyObject *
890 : 0 : pyexpat_xmlparser_GetBase_impl(xmlparseobject *self)
891 : : /*[clinic end generated code: output=2886cb21f9a8739a input=918d71c38009620e]*/
892 : : {
893 : 0 : return Py_BuildValue("z", XML_GetBase(self->itself));
894 : : }
895 : :
896 : : /*[clinic input]
897 : : pyexpat.xmlparser.GetInputContext
898 : :
899 : : Return the untranslated text of the input that caused the current event.
900 : :
901 : : If the event was generated by a large amount of text (such as a start tag
902 : : for an element with many attributes), not all of the text may be available.
903 : : [clinic start generated code]*/
904 : :
905 : : static PyObject *
906 : 0 : pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self)
907 : : /*[clinic end generated code: output=a88026d683fc22cc input=034df8712db68379]*/
908 : : {
909 [ # # ]: 0 : if (self->in_callback) {
910 : : int offset, size;
911 : : const char *buffer
912 : 0 : = XML_GetInputContext(self->itself, &offset, &size);
913 : :
914 [ # # ]: 0 : if (buffer != NULL)
915 : 0 : return PyBytes_FromStringAndSize(buffer + offset,
916 : 0 : size - offset);
917 : : else
918 : 0 : Py_RETURN_NONE;
919 : : }
920 : : else
921 : 0 : Py_RETURN_NONE;
922 : : }
923 : :
924 : : /*[clinic input]
925 : : pyexpat.xmlparser.ExternalEntityParserCreate
926 : :
927 : : cls: defining_class
928 : : context: str(accept={str, NoneType})
929 : : encoding: str = NULL
930 : : /
931 : :
932 : : Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler.
933 : : [clinic start generated code]*/
934 : :
935 : : static PyObject *
936 : 0 : pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self,
937 : : PyTypeObject *cls,
938 : : const char *context,
939 : : const char *encoding)
940 : : /*[clinic end generated code: output=01d4472b49cb3f92 input=ec70c6b9e6e9619a]*/
941 : : {
942 : : xmlparseobject *new_parser;
943 : : int i;
944 : :
945 : 0 : pyexpat_state *state = PyType_GetModuleState(cls);
946 : :
947 : 0 : new_parser = PyObject_GC_New(xmlparseobject, state->xml_parse_type);
948 [ # # ]: 0 : if (new_parser == NULL) {
949 : 0 : return NULL;
950 : : }
951 : :
952 : 0 : new_parser->buffer_size = self->buffer_size;
953 : 0 : new_parser->buffer_used = 0;
954 : 0 : new_parser->buffer = NULL;
955 : 0 : new_parser->ordered_attributes = self->ordered_attributes;
956 : 0 : new_parser->specified_attributes = self->specified_attributes;
957 : 0 : new_parser->in_callback = 0;
958 : 0 : new_parser->ns_prefixes = self->ns_prefixes;
959 : 0 : new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context,
960 : : encoding);
961 : 0 : new_parser->handlers = 0;
962 : 0 : new_parser->intern = Py_XNewRef(self->intern);
963 : :
964 [ # # ]: 0 : if (self->buffer != NULL) {
965 : 0 : new_parser->buffer = PyMem_Malloc(new_parser->buffer_size);
966 [ # # ]: 0 : if (new_parser->buffer == NULL) {
967 : 0 : Py_DECREF(new_parser);
968 : 0 : return PyErr_NoMemory();
969 : : }
970 : : }
971 [ # # ]: 0 : if (!new_parser->itself) {
972 : 0 : Py_DECREF(new_parser);
973 : 0 : return PyErr_NoMemory();
974 : : }
975 : :
976 : 0 : XML_SetUserData(new_parser->itself, (void *)new_parser);
977 : :
978 : : /* allocate and clear handlers first */
979 [ # # ]: 0 : for (i = 0; handler_info[i].name != NULL; i++)
980 : : /* do nothing */;
981 : :
982 [ # # ]: 0 : new_parser->handlers = PyMem_New(PyObject *, i);
983 [ # # ]: 0 : if (!new_parser->handlers) {
984 : 0 : Py_DECREF(new_parser);
985 : 0 : return PyErr_NoMemory();
986 : : }
987 : 0 : clear_handlers(new_parser, 1);
988 : :
989 : : /* then copy handlers from self */
990 [ # # ]: 0 : for (i = 0; handler_info[i].name != NULL; i++) {
991 : 0 : PyObject *handler = self->handlers[i];
992 [ # # ]: 0 : if (handler != NULL) {
993 : 0 : new_parser->handlers[i] = Py_NewRef(handler);
994 : 0 : handler_info[i].setter(new_parser->itself,
995 : : handler_info[i].handler);
996 : : }
997 : : }
998 : :
999 : 0 : PyObject_GC_Track(new_parser);
1000 : 0 : return (PyObject *)new_parser;
1001 : : }
1002 : :
1003 : : /*[clinic input]
1004 : : pyexpat.xmlparser.SetParamEntityParsing
1005 : :
1006 : : flag: int
1007 : : /
1008 : :
1009 : : Controls parsing of parameter entities (including the external DTD subset).
1010 : :
1011 : : Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER,
1012 : : XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and
1013 : : XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag
1014 : : was successful.
1015 : : [clinic start generated code]*/
1016 : :
1017 : : static PyObject *
1018 : 0 : pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag)
1019 : : /*[clinic end generated code: output=18668ee8e760d64c input=8aea19b4b15e9af1]*/
1020 : : {
1021 : 0 : flag = XML_SetParamEntityParsing(self->itself, flag);
1022 : 0 : return PyLong_FromLong(flag);
1023 : : }
1024 : :
1025 : :
1026 : : #if XML_COMBINED_VERSION >= 19505
1027 : : /*[clinic input]
1028 : : pyexpat.xmlparser.UseForeignDTD
1029 : :
1030 : : cls: defining_class
1031 : : flag: bool = True
1032 : : /
1033 : :
1034 : : Allows the application to provide an artificial external subset if one is not specified as part of the document instance.
1035 : :
1036 : : This readily allows the use of a 'default' document type controlled by the
1037 : : application, while still getting the advantage of providing document type
1038 : : information to the parser. 'flag' defaults to True if not provided.
1039 : : [clinic start generated code]*/
1040 : :
1041 : : static PyObject *
1042 : 0 : pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls,
1043 : : int flag)
1044 : : /*[clinic end generated code: output=d7d98252bd25a20f input=23440ecb0573fb29]*/
1045 : : {
1046 : 0 : pyexpat_state *state = PyType_GetModuleState(cls);
1047 : : enum XML_Error rc;
1048 : :
1049 : 0 : rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE);
1050 [ # # ]: 0 : if (rc != XML_ERROR_NONE) {
1051 : 0 : return set_error(state, self, rc);
1052 : : }
1053 : 0 : Py_RETURN_NONE;
1054 : : }
1055 : : #endif
1056 : :
1057 : : static struct PyMethodDef xmlparse_methods[] = {
1058 : : PYEXPAT_XMLPARSER_PARSE_METHODDEF
1059 : : PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF
1060 : : PYEXPAT_XMLPARSER_SETBASE_METHODDEF
1061 : : PYEXPAT_XMLPARSER_GETBASE_METHODDEF
1062 : : PYEXPAT_XMLPARSER_GETINPUTCONTEXT_METHODDEF
1063 : : PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF
1064 : : PYEXPAT_XMLPARSER_SETPARAMENTITYPARSING_METHODDEF
1065 : : #if XML_COMBINED_VERSION >= 19505
1066 : : PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
1067 : : #endif
1068 : : {NULL, NULL} /* sentinel */
1069 : : };
1070 : :
1071 : : /* ---------- */
1072 : :
1073 : :
1074 : :
1075 : : /* pyexpat international encoding support.
1076 : : Make it as simple as possible.
1077 : : */
1078 : :
1079 : : static int
1080 : 0 : PyUnknownEncodingHandler(void *encodingHandlerData,
1081 : : const XML_Char *name,
1082 : : XML_Encoding *info)
1083 : : {
1084 : : static unsigned char template_buffer[256] = {0};
1085 : : PyObject* u;
1086 : : int i;
1087 : : const void *data;
1088 : : int kind;
1089 : :
1090 [ # # ]: 0 : if (PyErr_Occurred())
1091 : 0 : return XML_STATUS_ERROR;
1092 : :
1093 [ # # ]: 0 : if (template_buffer[1] == 0) {
1094 [ # # ]: 0 : for (i = 0; i < 256; i++)
1095 : 0 : template_buffer[i] = i;
1096 : : }
1097 : :
1098 : 0 : u = PyUnicode_Decode((char*) template_buffer, 256, name, "replace");
1099 [ # # # # ]: 0 : if (u == NULL || PyUnicode_READY(u)) {
1100 : 0 : Py_XDECREF(u);
1101 : 0 : return XML_STATUS_ERROR;
1102 : : }
1103 : :
1104 [ # # ]: 0 : if (PyUnicode_GET_LENGTH(u) != 256) {
1105 : 0 : Py_DECREF(u);
1106 : 0 : PyErr_SetString(PyExc_ValueError,
1107 : : "multi-byte encodings are not supported");
1108 : 0 : return XML_STATUS_ERROR;
1109 : : }
1110 : :
1111 : 0 : kind = PyUnicode_KIND(u);
1112 : 0 : data = PyUnicode_DATA(u);
1113 [ # # ]: 0 : for (i = 0; i < 256; i++) {
1114 : 0 : Py_UCS4 ch = PyUnicode_READ(kind, data, i);
1115 [ # # ]: 0 : if (ch != Py_UNICODE_REPLACEMENT_CHARACTER)
1116 : 0 : info->map[i] = ch;
1117 : : else
1118 : 0 : info->map[i] = -1;
1119 : : }
1120 : :
1121 : 0 : info->data = NULL;
1122 : 0 : info->convert = NULL;
1123 : 0 : info->release = NULL;
1124 : 0 : Py_DECREF(u);
1125 : :
1126 : 0 : return XML_STATUS_OK;
1127 : : }
1128 : :
1129 : :
1130 : : static PyObject *
1131 : 0 : newxmlparseobject(pyexpat_state *state, const char *encoding,
1132 : : const char *namespace_separator, PyObject *intern)
1133 : : {
1134 : : int i;
1135 : : xmlparseobject *self;
1136 : :
1137 : 0 : self = PyObject_GC_New(xmlparseobject, state->xml_parse_type);
1138 [ # # ]: 0 : if (self == NULL)
1139 : 0 : return NULL;
1140 : :
1141 : 0 : self->buffer = NULL;
1142 : 0 : self->buffer_size = CHARACTER_DATA_BUFFER_SIZE;
1143 : 0 : self->buffer_used = 0;
1144 : 0 : self->ordered_attributes = 0;
1145 : 0 : self->specified_attributes = 0;
1146 : 0 : self->in_callback = 0;
1147 : 0 : self->ns_prefixes = 0;
1148 : 0 : self->handlers = NULL;
1149 : 0 : self->intern = Py_XNewRef(intern);
1150 : :
1151 : : /* namespace_separator is either NULL or contains one char + \0 */
1152 : 0 : self->itself = XML_ParserCreate_MM(encoding, &ExpatMemoryHandler,
1153 : : namespace_separator);
1154 [ # # ]: 0 : if (self->itself == NULL) {
1155 : 0 : PyErr_SetString(PyExc_RuntimeError,
1156 : : "XML_ParserCreate failed");
1157 : 0 : Py_DECREF(self);
1158 : 0 : return NULL;
1159 : : }
1160 : : #if XML_COMBINED_VERSION >= 20100
1161 : : /* This feature was added upstream in libexpat 2.1.0. */
1162 : 0 : XML_SetHashSalt(self->itself,
1163 : 0 : (unsigned long)_Py_HashSecret.expat.hashsalt);
1164 : : #endif
1165 : 0 : XML_SetUserData(self->itself, (void *)self);
1166 : 0 : XML_SetUnknownEncodingHandler(self->itself,
1167 : : (XML_UnknownEncodingHandler) PyUnknownEncodingHandler, NULL);
1168 : :
1169 [ # # ]: 0 : for (i = 0; handler_info[i].name != NULL; i++)
1170 : : /* do nothing */;
1171 : :
1172 [ # # ]: 0 : self->handlers = PyMem_New(PyObject *, i);
1173 [ # # ]: 0 : if (!self->handlers) {
1174 : 0 : Py_DECREF(self);
1175 : 0 : return PyErr_NoMemory();
1176 : : }
1177 : 0 : clear_handlers(self, 1);
1178 : :
1179 : 0 : PyObject_GC_Track(self);
1180 : 0 : return (PyObject*)self;
1181 : : }
1182 : :
1183 : : static int
1184 : 0 : xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
1185 : : {
1186 [ # # ]: 0 : for (int i = 0; handler_info[i].name != NULL; i++) {
1187 [ # # # # ]: 0 : Py_VISIT(op->handlers[i]);
1188 : : }
1189 [ # # # # ]: 0 : Py_VISIT(Py_TYPE(op));
1190 : 0 : return 0;
1191 : : }
1192 : :
1193 : : static int
1194 : 0 : xmlparse_clear(xmlparseobject *op)
1195 : : {
1196 : 0 : clear_handlers(op, 0);
1197 [ # # ]: 0 : Py_CLEAR(op->intern);
1198 : 0 : return 0;
1199 : : }
1200 : :
1201 : : static void
1202 : 0 : xmlparse_dealloc(xmlparseobject *self)
1203 : : {
1204 : 0 : PyObject_GC_UnTrack(self);
1205 : 0 : (void)xmlparse_clear(self);
1206 [ # # ]: 0 : if (self->itself != NULL)
1207 : 0 : XML_ParserFree(self->itself);
1208 : 0 : self->itself = NULL;
1209 : :
1210 [ # # ]: 0 : if (self->handlers != NULL) {
1211 : 0 : PyMem_Free(self->handlers);
1212 : 0 : self->handlers = NULL;
1213 : : }
1214 [ # # ]: 0 : if (self->buffer != NULL) {
1215 : 0 : PyMem_Free(self->buffer);
1216 : 0 : self->buffer = NULL;
1217 : : }
1218 : 0 : PyTypeObject *tp = Py_TYPE(self);
1219 : 0 : PyObject_GC_Del(self);
1220 : 0 : Py_DECREF(tp);
1221 : 0 : }
1222 : :
1223 : :
1224 : : static PyObject *
1225 : 0 : xmlparse_handler_getter(xmlparseobject *self, struct HandlerInfo *hi)
1226 : : {
1227 : : assert((hi - handler_info) < (Py_ssize_t)Py_ARRAY_LENGTH(handler_info));
1228 : 0 : int handlernum = (int)(hi - handler_info);
1229 : 0 : PyObject *result = self->handlers[handlernum];
1230 [ # # ]: 0 : if (result == NULL)
1231 : 0 : result = Py_None;
1232 : 0 : return Py_NewRef(result);
1233 : : }
1234 : :
1235 : : static int
1236 : 0 : xmlparse_handler_setter(xmlparseobject *self, PyObject *v, struct HandlerInfo *hi)
1237 : : {
1238 : : assert((hi - handler_info) < (Py_ssize_t)Py_ARRAY_LENGTH(handler_info));
1239 : 0 : int handlernum = (int)(hi - handler_info);
1240 [ # # ]: 0 : if (v == NULL) {
1241 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1242 : 0 : return -1;
1243 : : }
1244 [ # # ]: 0 : if (handlernum == CharacterData) {
1245 : : /* If we're changing the character data handler, flush all
1246 : : * cached data with the old handler. Not sure there's a
1247 : : * "right" thing to do, though, but this probably won't
1248 : : * happen.
1249 : : */
1250 [ # # ]: 0 : if (flush_character_buffer(self) < 0)
1251 : 0 : return -1;
1252 : : }
1253 : :
1254 : 0 : xmlhandler c_handler = NULL;
1255 [ # # ]: 0 : if (v == Py_None) {
1256 : : /* If this is the character data handler, and a character
1257 : : data handler is already active, we need to be more
1258 : : careful. What we can safely do is replace the existing
1259 : : character data handler callback function with a no-op
1260 : : function that will refuse to call Python. The downside
1261 : : is that this doesn't completely remove the character
1262 : : data handler from the C layer if there's any callback
1263 : : active, so Expat does a little more work than it
1264 : : otherwise would, but that's really an odd case. A more
1265 : : elaborate system of handlers and state could remove the
1266 : : C handler more effectively. */
1267 [ # # # # ]: 0 : if (handlernum == CharacterData && self->in_callback)
1268 : 0 : c_handler = noop_character_data_handler;
1269 : 0 : v = NULL;
1270 : : }
1271 [ # # ]: 0 : else if (v != NULL) {
1272 : 0 : Py_INCREF(v);
1273 : 0 : c_handler = handler_info[handlernum].handler;
1274 : : }
1275 : 0 : Py_XSETREF(self->handlers[handlernum], v);
1276 : 0 : handler_info[handlernum].setter(self->itself, c_handler);
1277 : 0 : return 0;
1278 : : }
1279 : :
1280 : : #define INT_GETTER(name) \
1281 : : static PyObject * \
1282 : : xmlparse_##name##_getter(xmlparseobject *self, void *closure) \
1283 : : { \
1284 : : return PyLong_FromLong((long) XML_Get##name(self->itself)); \
1285 : : }
1286 : 0 : INT_GETTER(ErrorCode)
1287 : 0 : INT_GETTER(ErrorLineNumber)
1288 : 0 : INT_GETTER(ErrorColumnNumber)
1289 : 0 : INT_GETTER(ErrorByteIndex)
1290 : 0 : INT_GETTER(CurrentLineNumber)
1291 : 0 : INT_GETTER(CurrentColumnNumber)
1292 : 0 : INT_GETTER(CurrentByteIndex)
1293 : :
1294 : : #undef INT_GETTER
1295 : :
1296 : : static PyObject *
1297 : 0 : xmlparse_buffer_text_getter(xmlparseobject *self, void *closure)
1298 : : {
1299 : 0 : return PyBool_FromLong(self->buffer != NULL);
1300 : : }
1301 : :
1302 : : static int
1303 : 0 : xmlparse_buffer_text_setter(xmlparseobject *self, PyObject *v, void *closure)
1304 : : {
1305 [ # # ]: 0 : if (v == NULL) {
1306 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1307 : 0 : return -1;
1308 : : }
1309 : 0 : int b = PyObject_IsTrue(v);
1310 [ # # ]: 0 : if (b < 0)
1311 : 0 : return -1;
1312 [ # # ]: 0 : if (b) {
1313 [ # # ]: 0 : if (self->buffer == NULL) {
1314 : 0 : self->buffer = PyMem_Malloc(self->buffer_size);
1315 [ # # ]: 0 : if (self->buffer == NULL) {
1316 : 0 : PyErr_NoMemory();
1317 : 0 : return -1;
1318 : : }
1319 : 0 : self->buffer_used = 0;
1320 : : }
1321 : : }
1322 [ # # ]: 0 : else if (self->buffer != NULL) {
1323 [ # # ]: 0 : if (flush_character_buffer(self) < 0)
1324 : 0 : return -1;
1325 : 0 : PyMem_Free(self->buffer);
1326 : 0 : self->buffer = NULL;
1327 : : }
1328 : 0 : return 0;
1329 : : }
1330 : :
1331 : : static PyObject *
1332 : 0 : xmlparse_buffer_size_getter(xmlparseobject *self, void *closure)
1333 : : {
1334 : 0 : return PyLong_FromLong((long) self->buffer_size);
1335 : : }
1336 : :
1337 : : static int
1338 : 0 : xmlparse_buffer_size_setter(xmlparseobject *self, PyObject *v, void *closure)
1339 : : {
1340 [ # # ]: 0 : if (v == NULL) {
1341 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1342 : 0 : return -1;
1343 : : }
1344 : : long new_buffer_size;
1345 [ # # ]: 0 : if (!PyLong_Check(v)) {
1346 : 0 : PyErr_SetString(PyExc_TypeError, "buffer_size must be an integer");
1347 : 0 : return -1;
1348 : : }
1349 : :
1350 : 0 : new_buffer_size = PyLong_AsLong(v);
1351 [ # # ]: 0 : if (new_buffer_size <= 0) {
1352 [ # # ]: 0 : if (!PyErr_Occurred())
1353 : 0 : PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero");
1354 : 0 : return -1;
1355 : : }
1356 : :
1357 : : /* trivial case -- no change */
1358 [ # # ]: 0 : if (new_buffer_size == self->buffer_size) {
1359 : 0 : return 0;
1360 : : }
1361 : :
1362 : : /* check maximum */
1363 [ # # ]: 0 : if (new_buffer_size > INT_MAX) {
1364 : 0 : PyErr_Format(PyExc_ValueError, "buffer_size must not be greater than %i", INT_MAX);
1365 : 0 : return -1;
1366 : : }
1367 : :
1368 [ # # ]: 0 : if (self->buffer != NULL) {
1369 : : /* there is already a buffer */
1370 [ # # ]: 0 : if (self->buffer_used != 0) {
1371 [ # # ]: 0 : if (flush_character_buffer(self) < 0) {
1372 : 0 : return -1;
1373 : : }
1374 : : }
1375 : : /* free existing buffer */
1376 : 0 : PyMem_Free(self->buffer);
1377 : : }
1378 : 0 : self->buffer = PyMem_Malloc(new_buffer_size);
1379 [ # # ]: 0 : if (self->buffer == NULL) {
1380 : 0 : PyErr_NoMemory();
1381 : 0 : return -1;
1382 : : }
1383 : 0 : self->buffer_size = new_buffer_size;
1384 : 0 : return 0;
1385 : : }
1386 : :
1387 : : static PyObject *
1388 : 0 : xmlparse_buffer_used_getter(xmlparseobject *self, void *closure)
1389 : : {
1390 : 0 : return PyLong_FromLong((long) self->buffer_used);
1391 : : }
1392 : :
1393 : : static PyObject *
1394 : 0 : xmlparse_namespace_prefixes_getter(xmlparseobject *self, void *closure)
1395 : : {
1396 : 0 : return PyBool_FromLong(self->ns_prefixes);
1397 : : }
1398 : :
1399 : : static int
1400 : 0 : xmlparse_namespace_prefixes_setter(xmlparseobject *self, PyObject *v, void *closure)
1401 : : {
1402 [ # # ]: 0 : if (v == NULL) {
1403 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1404 : 0 : return -1;
1405 : : }
1406 : 0 : int b = PyObject_IsTrue(v);
1407 [ # # ]: 0 : if (b < 0)
1408 : 0 : return -1;
1409 : 0 : self->ns_prefixes = b;
1410 : 0 : XML_SetReturnNSTriplet(self->itself, self->ns_prefixes);
1411 : 0 : return 0;
1412 : : }
1413 : :
1414 : : static PyObject *
1415 : 0 : xmlparse_ordered_attributes_getter(xmlparseobject *self, void *closure)
1416 : : {
1417 : 0 : return PyBool_FromLong(self->ordered_attributes);
1418 : : }
1419 : :
1420 : : static int
1421 : 0 : xmlparse_ordered_attributes_setter(xmlparseobject *self, PyObject *v, void *closure)
1422 : : {
1423 [ # # ]: 0 : if (v == NULL) {
1424 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1425 : 0 : return -1;
1426 : : }
1427 : 0 : int b = PyObject_IsTrue(v);
1428 [ # # ]: 0 : if (b < 0)
1429 : 0 : return -1;
1430 : 0 : self->ordered_attributes = b;
1431 : 0 : return 0;
1432 : : }
1433 : :
1434 : : static PyObject *
1435 : 0 : xmlparse_specified_attributes_getter(xmlparseobject *self, void *closure)
1436 : : {
1437 : 0 : return PyBool_FromLong((long) self->specified_attributes);
1438 : : }
1439 : :
1440 : : static int
1441 : 0 : xmlparse_specified_attributes_setter(xmlparseobject *self, PyObject *v, void *closure)
1442 : : {
1443 [ # # ]: 0 : if (v == NULL) {
1444 : 0 : PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
1445 : 0 : return -1;
1446 : : }
1447 : 0 : int b = PyObject_IsTrue(v);
1448 [ # # ]: 0 : if (b < 0)
1449 : 0 : return -1;
1450 : 0 : self->specified_attributes = b;
1451 : 0 : return 0;
1452 : : }
1453 : :
1454 : : static PyMemberDef xmlparse_members[] = {
1455 : : {"intern", T_OBJECT, offsetof(xmlparseobject, intern), READONLY, NULL},
1456 : : {NULL}
1457 : : };
1458 : :
1459 : : #define XMLPARSE_GETTER_DEF(name) \
1460 : : {#name, (getter)xmlparse_##name##_getter, NULL, NULL},
1461 : : #define XMLPARSE_GETTER_SETTER_DEF(name) \
1462 : : {#name, (getter)xmlparse_##name##_getter, \
1463 : : (setter)xmlparse_##name##_setter, NULL},
1464 : :
1465 : : static PyGetSetDef xmlparse_getsetlist[] = {
1466 : : XMLPARSE_GETTER_DEF(ErrorCode)
1467 : : XMLPARSE_GETTER_DEF(ErrorLineNumber)
1468 : : XMLPARSE_GETTER_DEF(ErrorColumnNumber)
1469 : : XMLPARSE_GETTER_DEF(ErrorByteIndex)
1470 : : XMLPARSE_GETTER_DEF(CurrentLineNumber)
1471 : : XMLPARSE_GETTER_DEF(CurrentColumnNumber)
1472 : : XMLPARSE_GETTER_DEF(CurrentByteIndex)
1473 : : XMLPARSE_GETTER_SETTER_DEF(buffer_size)
1474 : : XMLPARSE_GETTER_SETTER_DEF(buffer_text)
1475 : : XMLPARSE_GETTER_DEF(buffer_used)
1476 : : XMLPARSE_GETTER_SETTER_DEF(namespace_prefixes)
1477 : : XMLPARSE_GETTER_SETTER_DEF(ordered_attributes)
1478 : : XMLPARSE_GETTER_SETTER_DEF(specified_attributes)
1479 : : {NULL},
1480 : : };
1481 : :
1482 : : #undef XMLPARSE_GETTER_DEF
1483 : : #undef XMLPARSE_GETTER_SETTER_DEF
1484 : :
1485 : : PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
1486 : :
1487 : : static PyType_Slot _xml_parse_type_spec_slots[] = {
1488 : : {Py_tp_dealloc, xmlparse_dealloc},
1489 : : {Py_tp_doc, (void *)Xmlparsetype__doc__},
1490 : : {Py_tp_traverse, xmlparse_traverse},
1491 : : {Py_tp_clear, xmlparse_clear},
1492 : : {Py_tp_methods, xmlparse_methods},
1493 : : {Py_tp_members, xmlparse_members},
1494 : : {Py_tp_getset, xmlparse_getsetlist},
1495 : : {0, 0}
1496 : : };
1497 : :
1498 : : static PyType_Spec _xml_parse_type_spec = {
1499 : : .name = "pyexpat.xmlparser",
1500 : : .basicsize = sizeof(xmlparseobject),
1501 : : .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1502 : : Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE),
1503 : : .slots = _xml_parse_type_spec_slots,
1504 : : };
1505 : :
1506 : : /* End of code for xmlparser objects */
1507 : : /* -------------------------------------------------------- */
1508 : :
1509 : : /*[clinic input]
1510 : : pyexpat.ParserCreate
1511 : :
1512 : : encoding: str(accept={str, NoneType}) = None
1513 : : namespace_separator: str(accept={str, NoneType}) = None
1514 : : intern: object = NULL
1515 : :
1516 : : Return a new XML parser object.
1517 : : [clinic start generated code]*/
1518 : :
1519 : : static PyObject *
1520 : 0 : pyexpat_ParserCreate_impl(PyObject *module, const char *encoding,
1521 : : const char *namespace_separator, PyObject *intern)
1522 : : /*[clinic end generated code: output=295c0cf01ab1146c input=e8da8e8d7122cb5d]*/
1523 : : {
1524 : : PyObject *result;
1525 : 0 : int intern_decref = 0;
1526 : :
1527 [ # # ]: 0 : if (namespace_separator != NULL
1528 [ # # ]: 0 : && strlen(namespace_separator) > 1) {
1529 : 0 : PyErr_SetString(PyExc_ValueError,
1530 : : "namespace_separator must be at most one"
1531 : : " character, omitted, or None");
1532 : 0 : return NULL;
1533 : : }
1534 : : /* Explicitly passing None means no interning is desired.
1535 : : Not passing anything means that a new dictionary is used. */
1536 [ # # ]: 0 : if (intern == Py_None)
1537 : 0 : intern = NULL;
1538 [ # # ]: 0 : else if (intern == NULL) {
1539 : 0 : intern = PyDict_New();
1540 [ # # ]: 0 : if (!intern)
1541 : 0 : return NULL;
1542 : 0 : intern_decref = 1;
1543 : : }
1544 [ # # ]: 0 : else if (!PyDict_Check(intern)) {
1545 : 0 : PyErr_SetString(PyExc_TypeError, "intern must be a dictionary");
1546 : 0 : return NULL;
1547 : : }
1548 : :
1549 : 0 : pyexpat_state *state = pyexpat_get_state(module);
1550 : 0 : result = newxmlparseobject(state, encoding, namespace_separator, intern);
1551 [ # # ]: 0 : if (intern_decref) {
1552 : 0 : Py_DECREF(intern);
1553 : : }
1554 : 0 : return result;
1555 : : }
1556 : :
1557 : : /*[clinic input]
1558 : : pyexpat.ErrorString
1559 : :
1560 : : code: long
1561 : : /
1562 : :
1563 : : Returns string error for given number.
1564 : : [clinic start generated code]*/
1565 : :
1566 : : static PyObject *
1567 : 0 : pyexpat_ErrorString_impl(PyObject *module, long code)
1568 : : /*[clinic end generated code: output=2feae50d166f2174 input=cc67de010d9e62b3]*/
1569 : : {
1570 : 0 : return Py_BuildValue("z", XML_ErrorString((int)code));
1571 : : }
1572 : :
1573 : : /* List of methods defined in the module */
1574 : :
1575 : : static struct PyMethodDef pyexpat_methods[] = {
1576 : : PYEXPAT_PARSERCREATE_METHODDEF
1577 : : PYEXPAT_ERRORSTRING_METHODDEF
1578 : : {NULL, NULL} /* sentinel */
1579 : : };
1580 : :
1581 : : /* Module docstring */
1582 : :
1583 : : PyDoc_STRVAR(pyexpat_module_documentation,
1584 : : "Python wrapper for Expat parser.");
1585 : :
1586 : : /* Initialization function for the module */
1587 : :
1588 : : #ifndef MODULE_NAME
1589 : : #define MODULE_NAME "pyexpat"
1590 : : #endif
1591 : :
1592 : 2 : static int init_handler_descrs(pyexpat_state *state)
1593 : : {
1594 : : int i;
1595 : : assert(!PyType_HasFeature(state->xml_parse_type, Py_TPFLAGS_VALID_VERSION_TAG));
1596 [ + + ]: 46 : for (i = 0; handler_info[i].name != NULL; i++) {
1597 : 44 : struct HandlerInfo *hi = &handler_info[i];
1598 : 44 : hi->getset.name = hi->name;
1599 : 44 : hi->getset.get = (getter)xmlparse_handler_getter;
1600 : 44 : hi->getset.set = (setter)xmlparse_handler_setter;
1601 : 44 : hi->getset.closure = &handler_info[i];
1602 : :
1603 : 44 : PyObject *descr = PyDescr_NewGetSet(state->xml_parse_type, &hi->getset);
1604 [ - + ]: 44 : if (descr == NULL)
1605 : 0 : return -1;
1606 : :
1607 [ - + ]: 44 : if (PyDict_SetDefault(state->xml_parse_type->tp_dict, PyDescr_NAME(descr), descr) == NULL) {
1608 : 0 : Py_DECREF(descr);
1609 : 0 : return -1;
1610 : : }
1611 : 44 : Py_DECREF(descr);
1612 : : }
1613 : 2 : return 0;
1614 : : }
1615 : :
1616 : : static PyObject *
1617 : 4 : add_submodule(PyObject *mod, const char *fullname)
1618 : : {
1619 : 4 : const char *name = strrchr(fullname, '.') + 1;
1620 : :
1621 : 4 : PyObject *submodule = PyModule_New(fullname);
1622 [ - + ]: 4 : if (submodule == NULL) {
1623 : 0 : return NULL;
1624 : : }
1625 : :
1626 : 4 : PyObject *mod_name = PyUnicode_FromString(fullname);
1627 [ - + ]: 4 : if (mod_name == NULL) {
1628 : 0 : Py_DECREF(submodule);
1629 : 0 : return NULL;
1630 : : }
1631 : :
1632 [ - + ]: 4 : if (_PyImport_SetModule(mod_name, submodule) < 0) {
1633 : 0 : Py_DECREF(submodule);
1634 : 0 : Py_DECREF(mod_name);
1635 : 0 : return NULL;
1636 : : }
1637 : 4 : Py_DECREF(mod_name);
1638 : :
1639 : : /* gives away the reference to the submodule */
1640 [ - + ]: 4 : if (PyModule_AddObject(mod, name, submodule) < 0) {
1641 : 0 : Py_DECREF(submodule);
1642 : 0 : return NULL;
1643 : : }
1644 : :
1645 : 4 : return submodule;
1646 : : }
1647 : :
1648 : : struct ErrorInfo {
1649 : : const char * name; /* Error constant name, e.g. "XML_ERROR_NO_MEMORY" */
1650 : : const char * description; /* Error description as returned by XML_ErrorString(<int>) */
1651 : : };
1652 : :
1653 : : static
1654 : : struct ErrorInfo error_info_of[] = {
1655 : : {NULL, NULL}, /* XML_ERROR_NONE (value 0) is not exposed */
1656 : :
1657 : : {"XML_ERROR_NO_MEMORY", "out of memory"},
1658 : : {"XML_ERROR_SYNTAX", "syntax error"},
1659 : : {"XML_ERROR_NO_ELEMENTS", "no element found"},
1660 : : {"XML_ERROR_INVALID_TOKEN", "not well-formed (invalid token)"},
1661 : : {"XML_ERROR_UNCLOSED_TOKEN", "unclosed token"},
1662 : : {"XML_ERROR_PARTIAL_CHAR", "partial character"},
1663 : : {"XML_ERROR_TAG_MISMATCH", "mismatched tag"},
1664 : : {"XML_ERROR_DUPLICATE_ATTRIBUTE", "duplicate attribute"},
1665 : : {"XML_ERROR_JUNK_AFTER_DOC_ELEMENT", "junk after document element"},
1666 : : {"XML_ERROR_PARAM_ENTITY_REF", "illegal parameter entity reference"},
1667 : : {"XML_ERROR_UNDEFINED_ENTITY", "undefined entity"},
1668 : : {"XML_ERROR_RECURSIVE_ENTITY_REF", "recursive entity reference"},
1669 : : {"XML_ERROR_ASYNC_ENTITY", "asynchronous entity"},
1670 : : {"XML_ERROR_BAD_CHAR_REF", "reference to invalid character number"},
1671 : : {"XML_ERROR_BINARY_ENTITY_REF", "reference to binary entity"},
1672 : : {"XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", "reference to external entity in attribute"},
1673 : : {"XML_ERROR_MISPLACED_XML_PI", "XML or text declaration not at start of entity"},
1674 : : {"XML_ERROR_UNKNOWN_ENCODING", "unknown encoding"},
1675 : : {"XML_ERROR_INCORRECT_ENCODING", "encoding specified in XML declaration is incorrect"},
1676 : : {"XML_ERROR_UNCLOSED_CDATA_SECTION", "unclosed CDATA section"},
1677 : : {"XML_ERROR_EXTERNAL_ENTITY_HANDLING", "error in processing external entity reference"},
1678 : : {"XML_ERROR_NOT_STANDALONE", "document is not standalone"},
1679 : : {"XML_ERROR_UNEXPECTED_STATE", "unexpected parser state - please send a bug report"},
1680 : : {"XML_ERROR_ENTITY_DECLARED_IN_PE", "entity declared in parameter entity"},
1681 : : {"XML_ERROR_FEATURE_REQUIRES_XML_DTD", "requested feature requires XML_DTD support in Expat"},
1682 : : {"XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING", "cannot change setting once parsing has begun"},
1683 : :
1684 : : /* Added in Expat 1.95.7. */
1685 : : {"XML_ERROR_UNBOUND_PREFIX", "unbound prefix"},
1686 : :
1687 : : /* Added in Expat 1.95.8. */
1688 : : {"XML_ERROR_UNDECLARING_PREFIX", "must not undeclare prefix"},
1689 : : {"XML_ERROR_INCOMPLETE_PE", "incomplete markup in parameter entity"},
1690 : : {"XML_ERROR_XML_DECL", "XML declaration not well-formed"},
1691 : : {"XML_ERROR_TEXT_DECL", "text declaration not well-formed"},
1692 : : {"XML_ERROR_PUBLICID", "illegal character(s) in public id"},
1693 : : {"XML_ERROR_SUSPENDED", "parser suspended"},
1694 : : {"XML_ERROR_NOT_SUSPENDED", "parser not suspended"},
1695 : : {"XML_ERROR_ABORTED", "parsing aborted"},
1696 : : {"XML_ERROR_FINISHED", "parsing finished"},
1697 : : {"XML_ERROR_SUSPEND_PE", "cannot suspend in external parameter entity"},
1698 : :
1699 : : /* Added in 2.0.0. */
1700 : : {"XML_ERROR_RESERVED_PREFIX_XML", "reserved prefix (xml) must not be undeclared or bound to another namespace name"},
1701 : : {"XML_ERROR_RESERVED_PREFIX_XMLNS", "reserved prefix (xmlns) must not be declared or undeclared"},
1702 : : {"XML_ERROR_RESERVED_NAMESPACE_URI", "prefix must not be bound to one of the reserved namespace names"},
1703 : :
1704 : : /* Added in 2.2.1. */
1705 : : {"XML_ERROR_INVALID_ARGUMENT", "invalid argument"},
1706 : :
1707 : : /* Added in 2.3.0. */
1708 : : {"XML_ERROR_NO_BUFFER", "a successful prior call to function XML_GetBuffer is required"},
1709 : :
1710 : : /* Added in 2.4.0. */
1711 : : {"XML_ERROR_AMPLIFICATION_LIMIT_BREACH", "limit on input amplification factor (from DTD and entities) breached"}
1712 : : };
1713 : :
1714 : : static int
1715 : 86 : add_error(PyObject *errors_module, PyObject *codes_dict,
1716 : : PyObject *rev_codes_dict, size_t error_index)
1717 : : {
1718 : 86 : const char * const name = error_info_of[error_index].name;
1719 : 86 : const int error_code = (int)error_index;
1720 : :
1721 : : /* NOTE: This keeps the source of truth regarding error
1722 : : * messages with libexpat and (by definition) in bulletproof sync
1723 : : * with the other uses of the XML_ErrorString function
1724 : : * elsewhere within this file. pyexpat's copy of the messages
1725 : : * only acts as a fallback in case of outdated runtime libexpat,
1726 : : * where it returns NULL. */
1727 : 86 : const char *error_string = XML_ErrorString(error_code);
1728 [ - + ]: 86 : if (error_string == NULL) {
1729 : 0 : error_string = error_info_of[error_index].description;
1730 : : }
1731 : :
1732 [ - + ]: 86 : if (PyModule_AddStringConstant(errors_module, name, error_string) < 0) {
1733 : 0 : return -1;
1734 : : }
1735 : :
1736 : 86 : PyObject *num = PyLong_FromLong(error_code);
1737 [ - + ]: 86 : if (num == NULL) {
1738 : 0 : return -1;
1739 : : }
1740 : :
1741 [ - + ]: 86 : if (PyDict_SetItemString(codes_dict, error_string, num) < 0) {
1742 : 0 : Py_DECREF(num);
1743 : 0 : return -1;
1744 : : }
1745 : :
1746 : 86 : PyObject *str = PyUnicode_FromString(error_string);
1747 [ - + ]: 86 : if (str == NULL) {
1748 : 0 : Py_DECREF(num);
1749 : 0 : return -1;
1750 : : }
1751 : :
1752 : 86 : int res = PyDict_SetItem(rev_codes_dict, num, str);
1753 : 86 : Py_DECREF(str);
1754 : 86 : Py_DECREF(num);
1755 [ - + ]: 86 : if (res < 0) {
1756 : 0 : return -1;
1757 : : }
1758 : :
1759 : 86 : return 0;
1760 : : }
1761 : :
1762 : : static int
1763 : 2 : add_errors_module(PyObject *mod)
1764 : : {
1765 : 2 : PyObject *errors_module = add_submodule(mod, MODULE_NAME ".errors");
1766 [ - + ]: 2 : if (errors_module == NULL) {
1767 : 0 : return -1;
1768 : : }
1769 : :
1770 : 2 : PyObject *codes_dict = PyDict_New();
1771 : 2 : PyObject *rev_codes_dict = PyDict_New();
1772 [ + - - + ]: 2 : if (codes_dict == NULL || rev_codes_dict == NULL) {
1773 : 0 : goto error;
1774 : : }
1775 : :
1776 : 2 : size_t error_index = 0;
1777 [ + + ]: 90 : for (; error_index < sizeof(error_info_of) / sizeof(struct ErrorInfo); error_index++) {
1778 [ + + ]: 88 : if (error_info_of[error_index].name == NULL) {
1779 : 2 : continue;
1780 : : }
1781 : :
1782 [ - + ]: 86 : if (add_error(errors_module, codes_dict, rev_codes_dict, error_index) < 0) {
1783 : 0 : goto error;
1784 : : }
1785 : : }
1786 : :
1787 [ - + ]: 2 : if (PyModule_AddStringConstant(errors_module, "__doc__",
1788 : : "Constants used to describe "
1789 : : "error conditions.") < 0) {
1790 : 0 : goto error;
1791 : : }
1792 : :
1793 [ - + ]: 2 : if (PyModule_AddObject(errors_module, "codes", Py_NewRef(codes_dict)) < 0) {
1794 : 0 : Py_DECREF(codes_dict);
1795 : 0 : goto error;
1796 : : }
1797 [ + - ]: 2 : Py_CLEAR(codes_dict);
1798 : :
1799 [ - + ]: 2 : if (PyModule_AddObject(errors_module, "messages", Py_NewRef(rev_codes_dict)) < 0) {
1800 : 0 : Py_DECREF(rev_codes_dict);
1801 : 0 : goto error;
1802 : : }
1803 [ + - ]: 2 : Py_CLEAR(rev_codes_dict);
1804 : :
1805 : 2 : return 0;
1806 : :
1807 : 0 : error:
1808 : 0 : Py_XDECREF(codes_dict);
1809 : 0 : Py_XDECREF(rev_codes_dict);
1810 : 0 : return -1;
1811 : : }
1812 : :
1813 : : static int
1814 : 2 : add_model_module(PyObject *mod)
1815 : : {
1816 : 2 : PyObject *model_module = add_submodule(mod, MODULE_NAME ".model");
1817 [ - + ]: 2 : if (model_module == NULL) {
1818 : 0 : return -1;
1819 : : }
1820 : :
1821 : : #define MYCONST(c) do { \
1822 : : if (PyModule_AddIntConstant(model_module, #c, c) < 0) { \
1823 : : return -1; \
1824 : : } \
1825 : : } while(0)
1826 : :
1827 [ - + ]: 2 : if (PyModule_AddStringConstant(
1828 : : model_module, "__doc__",
1829 : : "Constants used to interpret content model information.") < 0) {
1830 : 0 : return -1;
1831 : : }
1832 : :
1833 [ - + ]: 2 : MYCONST(XML_CTYPE_EMPTY);
1834 [ - + ]: 2 : MYCONST(XML_CTYPE_ANY);
1835 [ - + ]: 2 : MYCONST(XML_CTYPE_MIXED);
1836 [ - + ]: 2 : MYCONST(XML_CTYPE_NAME);
1837 [ - + ]: 2 : MYCONST(XML_CTYPE_CHOICE);
1838 [ - + ]: 2 : MYCONST(XML_CTYPE_SEQ);
1839 : :
1840 [ - + ]: 2 : MYCONST(XML_CQUANT_NONE);
1841 [ - + ]: 2 : MYCONST(XML_CQUANT_OPT);
1842 [ - + ]: 2 : MYCONST(XML_CQUANT_REP);
1843 [ - + ]: 2 : MYCONST(XML_CQUANT_PLUS);
1844 : : #undef MYCONST
1845 : 2 : return 0;
1846 : : }
1847 : :
1848 : : #if XML_COMBINED_VERSION > 19505
1849 : : static int
1850 : 2 : add_features(PyObject *mod)
1851 : : {
1852 : 2 : PyObject *list = PyList_New(0);
1853 [ - + ]: 2 : if (list == NULL) {
1854 : 0 : return -1;
1855 : : }
1856 : :
1857 : 2 : const XML_Feature *features = XML_GetFeatureList();
1858 [ + + ]: 16 : for (size_t i = 0; features[i].feature != XML_FEATURE_END; ++i) {
1859 : 14 : PyObject *item = Py_BuildValue("si", features[i].name,
1860 : 14 : features[i].value);
1861 [ - + ]: 14 : if (item == NULL) {
1862 : 0 : goto error;
1863 : : }
1864 : 14 : int ok = PyList_Append(list, item);
1865 : 14 : Py_DECREF(item);
1866 [ - + ]: 14 : if (ok < 0) {
1867 : 0 : goto error;
1868 : : }
1869 : : }
1870 [ - + ]: 2 : if (PyModule_AddObject(mod, "features", list) < 0) {
1871 : 0 : goto error;
1872 : : }
1873 : 2 : return 0;
1874 : :
1875 : 0 : error:
1876 : 0 : Py_DECREF(list);
1877 : 0 : return -1;
1878 : : }
1879 : : #endif
1880 : :
1881 : : static void
1882 : 2 : pyexpat_capsule_destructor(PyObject *capsule)
1883 : : {
1884 : 2 : void *p = PyCapsule_GetPointer(capsule, PyExpat_CAPSULE_NAME);
1885 [ - + ]: 2 : if (p == NULL) {
1886 : 0 : PyErr_WriteUnraisable(capsule);
1887 : 0 : return;
1888 : : }
1889 : 2 : PyMem_Free(p);
1890 : : }
1891 : :
1892 : :
1893 : : static int
1894 : 2 : pyexpat_exec(PyObject *mod)
1895 : : {
1896 : 2 : pyexpat_state *state = pyexpat_get_state(mod);
1897 : 2 : state->str_read = PyUnicode_InternFromString("read");
1898 [ - + ]: 2 : if (state->str_read == NULL) {
1899 : 0 : return -1;
1900 : : }
1901 : 2 : state->xml_parse_type = (PyTypeObject *)PyType_FromModuleAndSpec(
1902 : : mod, &_xml_parse_type_spec, NULL);
1903 : :
1904 [ - + ]: 2 : if (state->xml_parse_type == NULL) {
1905 : 0 : return -1;
1906 : : }
1907 : :
1908 [ - + ]: 2 : if (init_handler_descrs(state) < 0) {
1909 : 0 : return -1;
1910 : : }
1911 : 2 : state->error = PyErr_NewException("xml.parsers.expat.ExpatError",
1912 : : NULL, NULL);
1913 [ - + ]: 2 : if (state->error == NULL) {
1914 : 0 : return -1;
1915 : : }
1916 : :
1917 : : /* Add some symbolic constants to the module */
1918 : :
1919 [ - + ]: 2 : if (PyModule_AddObjectRef(mod, "error", state->error) < 0) {
1920 : 0 : return -1;
1921 : : }
1922 : :
1923 [ - + ]: 2 : if (PyModule_AddObjectRef(mod, "ExpatError", state->error) < 0) {
1924 : 0 : return -1;
1925 : : }
1926 : :
1927 [ - + ]: 2 : if (PyModule_AddObjectRef(mod, "XMLParserType",
1928 : 2 : (PyObject *) state->xml_parse_type) < 0) {
1929 : 0 : return -1;
1930 : : }
1931 : :
1932 [ - + ]: 2 : if (PyModule_AddStringConstant(mod, "EXPAT_VERSION",
1933 : 2 : XML_ExpatVersion()) < 0) {
1934 : 0 : return -1;
1935 : : }
1936 : : {
1937 : 2 : XML_Expat_Version info = XML_ExpatVersionInfo();
1938 : 2 : PyObject *versionInfo = Py_BuildValue("(iii)",
1939 : : info.major,
1940 : : info.minor,
1941 : : info.micro);
1942 [ - + ]: 2 : if (PyModule_AddObject(mod, "version_info", versionInfo) < 0) {
1943 : 0 : Py_DECREF(versionInfo);
1944 : 0 : return -1;
1945 : : }
1946 : : }
1947 : : /* XXX When Expat supports some way of figuring out how it was
1948 : : compiled, this should check and set native_encoding
1949 : : appropriately.
1950 : : */
1951 [ - + ]: 2 : if (PyModule_AddStringConstant(mod, "native_encoding", "UTF-8") < 0) {
1952 : 0 : return -1;
1953 : : }
1954 : :
1955 [ - + ]: 2 : if (add_errors_module(mod) < 0) {
1956 : 0 : return -1;
1957 : : }
1958 : :
1959 [ - + ]: 2 : if (add_model_module(mod) < 0) {
1960 : 0 : return -1;
1961 : : }
1962 : :
1963 : : #if XML_COMBINED_VERSION > 19505
1964 [ - + ]: 2 : if (add_features(mod) < 0) {
1965 : 0 : return -1;
1966 : : }
1967 : : #endif
1968 : :
1969 : : #define MYCONST(c) do { \
1970 : : if (PyModule_AddIntConstant(mod, #c, c) < 0) { \
1971 : : return -1; \
1972 : : } \
1973 : : } while(0)
1974 : :
1975 [ - + ]: 2 : MYCONST(XML_PARAM_ENTITY_PARSING_NEVER);
1976 [ - + ]: 2 : MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1977 [ - + ]: 2 : MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS);
1978 : : #undef MYCONST
1979 : :
1980 : 2 : struct PyExpat_CAPI *capi = PyMem_Malloc(sizeof(*capi));
1981 [ - + ]: 2 : if (capi == NULL) {
1982 : 0 : PyErr_NoMemory();
1983 : 0 : return -1;
1984 : : }
1985 : : /* initialize pyexpat dispatch table */
1986 : 2 : capi->size = sizeof(*capi);
1987 : 2 : capi->magic = PyExpat_CAPI_MAGIC;
1988 : 2 : capi->MAJOR_VERSION = XML_MAJOR_VERSION;
1989 : 2 : capi->MINOR_VERSION = XML_MINOR_VERSION;
1990 : 2 : capi->MICRO_VERSION = XML_MICRO_VERSION;
1991 : 2 : capi->ErrorString = XML_ErrorString;
1992 : 2 : capi->GetErrorCode = XML_GetErrorCode;
1993 : 2 : capi->GetErrorColumnNumber = XML_GetErrorColumnNumber;
1994 : 2 : capi->GetErrorLineNumber = XML_GetErrorLineNumber;
1995 : 2 : capi->Parse = XML_Parse;
1996 : 2 : capi->ParserCreate_MM = XML_ParserCreate_MM;
1997 : 2 : capi->ParserFree = XML_ParserFree;
1998 : 2 : capi->SetCharacterDataHandler = XML_SetCharacterDataHandler;
1999 : 2 : capi->SetCommentHandler = XML_SetCommentHandler;
2000 : 2 : capi->SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand;
2001 : 2 : capi->SetElementHandler = XML_SetElementHandler;
2002 : 2 : capi->SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler;
2003 : 2 : capi->SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler;
2004 : 2 : capi->SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
2005 : 2 : capi->SetUserData = XML_SetUserData;
2006 : 2 : capi->SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler;
2007 : 2 : capi->SetEncoding = XML_SetEncoding;
2008 : 2 : capi->DefaultUnknownEncodingHandler = PyUnknownEncodingHandler;
2009 : : #if XML_COMBINED_VERSION >= 20100
2010 : 2 : capi->SetHashSalt = XML_SetHashSalt;
2011 : : #else
2012 : : capi->SetHashSalt = NULL;
2013 : : #endif
2014 : :
2015 : : /* export using capsule */
2016 : 2 : PyObject *capi_object = PyCapsule_New(capi, PyExpat_CAPSULE_NAME,
2017 : : pyexpat_capsule_destructor);
2018 [ - + ]: 2 : if (capi_object == NULL) {
2019 : 0 : PyMem_Free(capi);
2020 : 0 : return -1;
2021 : : }
2022 : :
2023 [ - + ]: 2 : if (PyModule_AddObject(mod, "expat_CAPI", capi_object) < 0) {
2024 : 0 : Py_DECREF(capi_object);
2025 : 0 : return -1;
2026 : : }
2027 : :
2028 : 2 : return 0;
2029 : : }
2030 : :
2031 : : static int
2032 : 12 : pyexpat_traverse(PyObject *module, visitproc visit, void *arg)
2033 : : {
2034 : 12 : pyexpat_state *state = pyexpat_get_state(module);
2035 [ + - - + ]: 12 : Py_VISIT(state->xml_parse_type);
2036 [ + - - + ]: 12 : Py_VISIT(state->error);
2037 [ + - - + ]: 12 : Py_VISIT(state->str_read);
2038 : 12 : return 0;
2039 : : }
2040 : :
2041 : : static int
2042 : 4 : pyexpat_clear(PyObject *module)
2043 : : {
2044 : 4 : pyexpat_state *state = pyexpat_get_state(module);
2045 [ + + ]: 4 : Py_CLEAR(state->xml_parse_type);
2046 [ + + ]: 4 : Py_CLEAR(state->error);
2047 [ + + ]: 4 : Py_CLEAR(state->str_read);
2048 : 4 : return 0;
2049 : : }
2050 : :
2051 : : static void
2052 : 2 : pyexpat_free(void *module)
2053 : : {
2054 : 2 : pyexpat_clear((PyObject *)module);
2055 : 2 : }
2056 : :
2057 : : static PyModuleDef_Slot pyexpat_slots[] = {
2058 : : {Py_mod_exec, pyexpat_exec},
2059 : : {0, NULL}
2060 : : };
2061 : :
2062 : : static struct PyModuleDef pyexpatmodule = {
2063 : : PyModuleDef_HEAD_INIT,
2064 : : .m_name = MODULE_NAME,
2065 : : .m_doc = pyexpat_module_documentation,
2066 : : .m_size = sizeof(pyexpat_state),
2067 : : .m_methods = pyexpat_methods,
2068 : : .m_slots = pyexpat_slots,
2069 : : .m_traverse = pyexpat_traverse,
2070 : : .m_clear = pyexpat_clear,
2071 : : .m_free = pyexpat_free
2072 : : };
2073 : :
2074 : : PyMODINIT_FUNC
2075 : 2 : PyInit_pyexpat(void)
2076 : : {
2077 : 2 : return PyModuleDef_Init(&pyexpatmodule);
2078 : : }
2079 : :
2080 : : static void
2081 : 0 : clear_handlers(xmlparseobject *self, int initial)
2082 : : {
2083 : 0 : int i = 0;
2084 : :
2085 [ # # ]: 0 : for (; handler_info[i].name != NULL; i++) {
2086 [ # # ]: 0 : if (initial)
2087 : 0 : self->handlers[i] = NULL;
2088 : : else {
2089 [ # # ]: 0 : Py_CLEAR(self->handlers[i]);
2090 : 0 : handler_info[i].setter(self->itself, NULL);
2091 : : }
2092 : : }
2093 : 0 : }
2094 : :
2095 : : static struct HandlerInfo handler_info[] = {
2096 : :
2097 : : #define HANDLER_INFO(name) \
2098 : : {#name, (xmlhandlersetter)XML_Set##name, (xmlhandler)my_##name},
2099 : :
2100 : : HANDLER_INFO(StartElementHandler)
2101 : : HANDLER_INFO(EndElementHandler)
2102 : : HANDLER_INFO(ProcessingInstructionHandler)
2103 : : HANDLER_INFO(CharacterDataHandler)
2104 : : HANDLER_INFO(UnparsedEntityDeclHandler)
2105 : : HANDLER_INFO(NotationDeclHandler)
2106 : : HANDLER_INFO(StartNamespaceDeclHandler)
2107 : : HANDLER_INFO(EndNamespaceDeclHandler)
2108 : : HANDLER_INFO(CommentHandler)
2109 : : HANDLER_INFO(StartCdataSectionHandler)
2110 : : HANDLER_INFO(EndCdataSectionHandler)
2111 : : HANDLER_INFO(DefaultHandler)
2112 : : HANDLER_INFO(DefaultHandlerExpand)
2113 : : HANDLER_INFO(NotStandaloneHandler)
2114 : : HANDLER_INFO(ExternalEntityRefHandler)
2115 : : HANDLER_INFO(StartDoctypeDeclHandler)
2116 : : HANDLER_INFO(EndDoctypeDeclHandler)
2117 : : HANDLER_INFO(EntityDeclHandler)
2118 : : HANDLER_INFO(XmlDeclHandler)
2119 : : HANDLER_INFO(ElementDeclHandler)
2120 : : HANDLER_INFO(AttlistDeclHandler)
2121 : : #if XML_COMBINED_VERSION >= 19504
2122 : : HANDLER_INFO(SkippedEntityHandler)
2123 : : #endif
2124 : :
2125 : : #undef HANDLER_INFO
2126 : :
2127 : : {NULL, NULL, NULL} /* sentinel */
2128 : : };
|