Bug Summary

File:bindings/xml/expat_xmlparser.c
Warning:line 350, column 16
Read function called when stream is in EOF state. Function has no effect

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name expat_xmlparser.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-libdom -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-libdom -resource-dir /usr/lib/llvm-19/lib/clang/19 -D _BSD_SOURCE -D _DEFAULT_SOURCE -I /var/lib/jenkins/workspace/scan-build-libdom/include/ -I /var/lib/jenkins/workspace/scan-build-libdom/src -I /var/lib/jenkins/workspace/scan-build-libdom/binding -D _ALIGNED=__attribute__((aligned)) -D STMTEXPR=1 -D DEBUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Og -Wwrite-strings -Wno-error -std=c99 -fconst-strings -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-libdom/clangScanBuildReports/2025-11-29-164526-2895463-1 -x c bindings/xml/expat_xmlparser.c
1/*
2 * This file is part of libdom.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2012 Daniel Silverstone <dsilvers@netsurf-browser.org>
6 */
7
8#include <stdbool.h>
9#include <string.h>
10#include <assert.h>
11
12#include <stdlib.h>
13#include <stdio.h>
14
15#include <dom/dom.h>
16
17#include "xmlparser.h"
18#include "utils.h"
19
20#include <expat.h>
21
22/**
23 * expat XML parser object
24 */
25struct dom_xml_parser {
26 dom_msg msg; /**< Informational message function */
27 void *mctx; /**< Pointer to client data */
28 XML_Parser parser; /**< expat parser context */
29 struct dom_document *doc; /**< DOM Document we're building */
30 struct dom_node *current; /**< DOM node we're currently building */
31 bool_Bool is_cdata; /**< If the character data is cdata or text */
32};
33
34/* Binding functions */
35
36static void
37expat_xmlparser_start_element_handler(void *_parser,
38 const XML_Char *name,
39 const XML_Char **atts)
40{
41 dom_xml_parser *parser = _parser;
42 dom_exception err;
43 dom_element *elem, *ins_elem;
44 dom_string *tag_name;
45 dom_string *namespace = NULL((void*)0);
46 const XML_Char *ns_sep = strchr(name, '\n');
47
48 assert(parser->current)((parser->current) ? (void) (0) : __assert_fail ("parser->current"
, "bindings/xml/expat_xmlparser.c", 48, __extension__ __PRETTY_FUNCTION__
))
;
49
50 if (ns_sep != NULL((void*)0)) {
51 err = dom_string_create_interned((const uint8_t *)name,
52 ns_sep - name,
53 &namespace);
54 if (err != DOM_NO_ERR) {
55 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
56 "No memory for namespace name");
57 return;
58 }
59 name = ns_sep + 1;
60 }
61
62 err = dom_string_create_interned((const uint8_t *)name,
63 strlen(name),
64 &tag_name);
65 if (err != DOM_NO_ERR) {
66 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
67 "No memory for tag name");
68 if (namespace != NULL((void*)0))
69 dom_string_unref(namespace);
70 return;
71 }
72
73 if (namespace == NULL((void*)0))
74 err = dom_document_create_element(parser->doc,dom_document_create_element( (dom_document *) (parser->doc
), (tag_name), (struct dom_element **) (&elem))
75 tag_name, &elem)dom_document_create_element( (dom_document *) (parser->doc
), (tag_name), (struct dom_element **) (&elem))
;
76 else
77 err = dom_document_create_element_ns(parser->doc, namespace,dom_document_create_element_ns((dom_document *) (parser->doc
), (namespace), (tag_name), (struct dom_element **) (&elem
))
78 tag_name, &elem)dom_document_create_element_ns((dom_document *) (parser->doc
), (namespace), (tag_name), (struct dom_element **) (&elem
))
;
79 if (err != DOM_NO_ERR) {
80 if (namespace != NULL((void*)0))
81 dom_string_unref(namespace);
82 dom_string_unref(tag_name);
83 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
84 "Failed to create element '%s'", name);
85 return;
86 }
87
88 dom_string_unref(tag_name);
89 if (namespace != NULL((void*)0))
90 dom_string_unref(namespace);
91
92 /* Add attributes to the element */
93 while (*atts) {
94 dom_string *key, *value;
95 ns_sep = strchr(*atts, '\n');
96 if (ns_sep != NULL((void*)0)) {
97 err = dom_string_create_interned((const uint8_t *)(*atts),
98 ns_sep - (*atts),
99 &namespace);
100 if (err != DOM_NO_ERR) {
101 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
102 "No memory for attr namespace");
103 dom_node_unref(elem)dom_node_unref((dom_node *) (elem));
104 return;
105 }
106 } else
107 namespace = NULL((void*)0);
108 if (ns_sep == NULL((void*)0))
109 err = dom_string_create_interned((const uint8_t *)(*atts),
110 strlen(*atts), &key);
111 else
112 err = dom_string_create_interned((const uint8_t *)(ns_sep + 1),
113 strlen(ns_sep + 1),
114 &key);
115 if (err != DOM_NO_ERR) {
116 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
117 "No memory for attribute name");
118 if (namespace != NULL((void*)0))
119 dom_string_unref(namespace);
120 dom_node_unref(elem)dom_node_unref((dom_node *) (elem));
121 return;
122 }
123 atts++;
124 err = dom_string_create((const uint8_t *)(*atts),
125 strlen(*atts), &value);
126 if (err != DOM_NO_ERR) {
127 dom_node_unref(elem)dom_node_unref((dom_node *) (elem));
128 if (namespace != NULL((void*)0))
129 dom_string_unref(namespace);
130 dom_string_unref(key);
131 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
132 "No memory for attribute value");
133 return;
134 }
135 atts++;
136
137 if (namespace == NULL((void*)0))
138 err = dom_element_set_attribute(elem, key, value)dom_element_set_attribute( (dom_element *) (elem), (key), (value
))
;
139 else
140 err = dom_element_set_attribute_ns(elem, namespace,dom_element_set_attribute_ns((dom_element *) (elem), (namespace
), (key), (value))
141 key, value)dom_element_set_attribute_ns((dom_element *) (elem), (namespace
), (key), (value))
;
142 if (namespace != NULL((void*)0))
143 dom_string_unref(namespace);
144 dom_string_unref(key);
145 dom_string_unref(value);
146 if (err != DOM_NO_ERR) {
147 dom_node_unref(elem)dom_node_unref((dom_node *) (elem));
148 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
149 "No memory for setting attribute");
150 return;
151 }
152 }
153
154 err = dom_node_append_child(parser->current, (struct dom_node *) elem,dom_node_append_child( (dom_node *) (parser->current), (dom_node
*) ((struct dom_node *) elem), (dom_node **) ((struct dom_node
**) (void *) &ins_elem))
155 (struct dom_node **) (void *) &ins_elem)dom_node_append_child( (dom_node *) (parser->current), (dom_node
*) ((struct dom_node *) elem), (dom_node **) ((struct dom_node
**) (void *) &ins_elem))
;
156 if (err != DOM_NO_ERR) {
157 dom_node_unref(elem)dom_node_unref((dom_node *) (elem));
158 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
159 "No memory for appending child node");
160 return;
161 }
162
163 dom_node_unref(ins_elem)dom_node_unref((dom_node *) (ins_elem));
164
165 dom_node_unref(parser->current)dom_node_unref((dom_node *) (parser->current));
166 parser->current = (struct dom_node *)elem; /* Steal initial ref */
167}
168
169static void
170expat_xmlparser_end_element_handler(void *_parser,
171 const XML_Char *name)
172{
173 dom_xml_parser *parser = _parser;
174 dom_exception err;
175 dom_node *parent;
176
177 UNUSED(name)((void)(name));
178
179 assert(parser->current)((parser->current) ? (void) (0) : __assert_fail ("parser->current"
, "bindings/xml/expat_xmlparser.c", 179, __extension__ __PRETTY_FUNCTION__
))
;
180
181 err = dom_node_get_parent_node(parser->current, &parent)dom_node_get_parent_node( (dom_node *) (parser->current), (
dom_node **) (&parent))
;
182
183 if (parent == NULL((void*)0) || parent == (dom_node *)parser->doc) {
184 /* The XML has tried to close more than it should */
185 if (parent != NULL((void*)0))
186 dom_node_unref(parent)dom_node_unref((dom_node *) (parent));
187 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
188 "Attempted to close more than was opened.");
189 return;
190 }
191
192 if (err != DOM_NO_ERR) {
193 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
194 "Unable to find a parent while closing element.");
195 return;
196 }
197
198 dom_node_unref(parser->current)dom_node_unref((dom_node *) (parser->current));
199 parser->current = parent; /* Takes the ref given by get_parent_node */
200}
201
202static void
203expat_xmlparser_start_cdata_handler(void *_parser)
204{
205 dom_xml_parser *parser = _parser;
206
207 parser->is_cdata = true1;
208}
209
210static void
211expat_xmlparser_end_cdata_handler(void *_parser)
212{
213 dom_xml_parser *parser = _parser;
214
215 parser->is_cdata = false0;
216}
217
218static void
219expat_xmlparser_cdata_handler(void *_parser,
220 const XML_Char *s,
221 int len)
222{
223 dom_xml_parser *parser = _parser;
224 dom_string *data;
225 dom_exception err;
226 struct dom_node *cdata, *ins_cdata, *lastchild = NULL((void*)0);
227 dom_node_type ntype = 0;
228
229 assert(parser->current)((parser->current) ? (void) (0) : __assert_fail ("parser->current"
, "bindings/xml/expat_xmlparser.c", 229, __extension__ __PRETTY_FUNCTION__
))
;
230
231 err = dom_string_create((const uint8_t *)s, len, &data);
232 if (err != DOM_NO_ERR) {
233 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
234 "No memory for cdata section contents");
235 return;
236 }
237
238 err = dom_node_get_last_child(parser->current, &lastchild)dom_node_get_last_child( (dom_node *) (parser->current), (
dom_node **) (&lastchild))
;
239
240 if (err == DOM_NO_ERR && lastchild != NULL((void*)0)) {
241 err = dom_node_get_node_type(lastchild, &ntype)dom_node_get_node_type( (dom_node *) (lastchild), (dom_node_type
*) (&ntype))
;
242 }
243
244 if (err != DOM_NO_ERR) {
245 dom_string_unref(data);
246 if (lastchild != NULL((void*)0))
247 dom_node_unref(lastchild)dom_node_unref((dom_node *) (lastchild));
248 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
249 "No memory for cdata section");
250 return;
251 }
252
253 if (ntype == DOM_TEXT_NODE && parser->is_cdata == false0) {
254 /* We can append this text instead */
255 err = dom_characterdata_append_data(dom_characterdata_append_data( (struct dom_characterdata *) (
(dom_characterdata *)lastchild), (data))
256 (dom_characterdata *)lastchild, data)dom_characterdata_append_data( (struct dom_characterdata *) (
(dom_characterdata *)lastchild), (data))
;
257 dom_string_unref(data);
258 if (lastchild != NULL((void*)0))
259 dom_node_unref(lastchild)dom_node_unref((dom_node *) (lastchild));
260 if (err != DOM_NO_ERR) {
261 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
262 "No memory for cdata section");
263 }
264 return;
265 }
266
267 if (lastchild != NULL((void*)0))
268 dom_node_unref(lastchild)dom_node_unref((dom_node *) (lastchild));
269
270 /* We can't append directly, so make a new node */
271 err = parser->is_cdata ?
272 dom_document_create_cdata_section(parser->doc, data,dom_document_create_cdata_section((dom_document *) (parser->
doc), (data), (struct dom_cdata_section **) ((dom_cdata_section
**) (void *) &cdata))
273 (dom_cdata_section **) (void *) &cdata)dom_document_create_cdata_section((dom_document *) (parser->
doc), (data), (struct dom_cdata_section **) ((dom_cdata_section
**) (void *) &cdata))
:
274 dom_document_create_text_node(parser->doc, data,dom_document_create_text_node((dom_document *) (parser->doc
), (data), (struct dom_text **) ((dom_text **) (void *) &
cdata))
275 (dom_text **) (void *) &cdata)dom_document_create_text_node((dom_document *) (parser->doc
), (data), (struct dom_text **) ((dom_text **) (void *) &
cdata))
;
276 if (err != DOM_NO_ERR) {
277 dom_string_unref(data);
278 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
279 "No memory for cdata section");
280 return;
281 }
282
283 /* No longer need data */
284 dom_string_unref(data);
285
286 /* Append cdata section to parent */
287 err = dom_node_append_child(parser->current, cdata, &ins_cdata)dom_node_append_child( (dom_node *) (parser->current), (dom_node
*) (cdata), (dom_node **) (&ins_cdata))
;
288 if (err != DOM_NO_ERR) {
289 dom_node_unref((struct dom_node *) cdata)dom_node_unref((dom_node *) ((struct dom_node *) cdata));
290 parser->msg(DOM_MSG_ERROR, parser->mctx,
291 "Failed attaching cdata section");
292 return;
293 }
294
295 /* We're not interested in the inserted cdata section */
296 if (ins_cdata != NULL((void*)0))
297 dom_node_unref(ins_cdata)dom_node_unref((dom_node *) (ins_cdata));
298
299 /* No longer interested in cdata section */
300 dom_node_unref(cdata)dom_node_unref((dom_node *) (cdata));
301}
302
303static int
304expat_xmlparser_external_entity_ref_handler(XML_Parser parser,
1
[debug] analyzing from expat_xmlparser_external_entity_ref_handler
305 const XML_Char *context,
306 const XML_Char *base,
307 const XML_Char *system_id,
308 const XML_Char *public_id)
309{
310 FILE *fh;
311 XML_Parser subparser;
312 unsigned char data[1024];
313 size_t len;
314 enum XML_Status status;
315
316 UNUSED(base)((void)(base));
317 UNUSED(public_id)((void)(public_id));
318
319 if (system_id == NULL((void*)0))
2
Assuming 'system_id' is not equal to NULL
320 return XML_STATUS_OKXML_STATUS_OK;
321
322 /* If the ID is a network URI, return (see bug 2313 and below) */
323 if ((strncmp(system_id, "http://", 7) == 0) ||
3
Assuming the condition is false
5
Taking false branch
324 (strncmp(system_id, "https://", 8) == 0)) {
4
Assuming the condition is false
325 return XML_STATUS_OKXML_STATUS_OK;
326 }
327
328 /*\todo This needs fixing. Our system_id, if not
329 * absolute, needs to be made absolute relative to
330 * base before being opened. It should also be
331 * passed back to the client to be opened, as network
332 * addresses need special handling and local files
333 * should also have the file:// scheme, so fopen is
334 * not necessarily going to work. */
335 fh = fopen(system_id, "r");
336
337 if (fh
5.1
'fh' is not equal to NULL
== NULL((void*)0))
6
Taking false branch
338 return XML_STATUS_OKXML_STATUS_OK;
339
340 subparser = XML_ExternalEntityParserCreate(parser,
341 context,
342 NULL((void*)0));
343
344 if (subparser == NULL((void*)0)) {
7
Assuming 'subparser' is not equal to NULL
8
Taking false branch
345 fclose(fh);
346 return XML_STATUS_OKXML_STATUS_OK;
347 }
348
349 /* Parse the file bit by bit */
350 while ((len = fread(data, 1, 1024, fh)) > 0) {
9
Assuming stream reaches end-of-file here
10
Assuming the condition is true
11
Loop condition is true. Entering loop body
14
Read function called when stream is in EOF state. Function has no effect
351 status = XML_Parse(subparser, (const char *)data, len, 0);
352 if (status != XML_STATUS_OKXML_STATUS_OK) {
12
Assuming 'status' is equal to XML_STATUS_OK
13
Taking false branch
353 XML_ParserFree(subparser);
354 fclose(fh);
355 return XML_STATUS_OKXML_STATUS_OK;
356 }
357 }
358 XML_Parse(subparser, "", 0, 1);
359 XML_ParserFree(subparser);
360 fclose(fh);
361 return XML_STATUS_OKXML_STATUS_OK;
362}
363
364static void
365expat_xmlparser_comment_handler(void *_parser,
366 const XML_Char *_comment)
367{
368 dom_xml_parser *parser = _parser;
369 struct dom_comment *comment, *ins_comment = NULL((void*)0);
370 dom_string *data;
371 dom_exception err;
372
373 assert(parser->current)((parser->current) ? (void) (0) : __assert_fail ("parser->current"
, "bindings/xml/expat_xmlparser.c", 373, __extension__ __PRETTY_FUNCTION__
))
;
374
375 /* Create DOM string data for comment */
376 err = dom_string_create((const uint8_t *)_comment,
377 strlen((const char *) _comment), &data);
378 if (err != DOM_NO_ERR) {
379 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
380 "No memory for comment data");
381 return;
382 }
383
384 /* Create comment */
385 err = dom_document_create_comment(parser->doc, data, &comment)dom_document_create_comment( (dom_document *) (parser->doc
), (data), (struct dom_comment **) (&comment))
;
386 if (err != DOM_NO_ERR) {
387 dom_string_unref(data);
388 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
389 "No memory for comment node");
390 return;
391 }
392
393 /* No longer need data */
394 dom_string_unref(data);
395
396 /* Append comment to parent */
397 err = dom_node_append_child(parser->current, (struct dom_node *) comment,dom_node_append_child( (dom_node *) (parser->current), (dom_node
*) ((struct dom_node *) comment), (dom_node **) ((struct dom_node
**) (void *) &ins_comment))
398 (struct dom_node **) (void *) &ins_comment)dom_node_append_child( (dom_node *) (parser->current), (dom_node
*) ((struct dom_node *) comment), (dom_node **) ((struct dom_node
**) (void *) &ins_comment))
;
399 if (err != DOM_NO_ERR) {
400 dom_node_unref((struct dom_node *) comment)dom_node_unref((dom_node *) ((struct dom_node *) comment));
401 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
402 "Failed attaching comment node");
403 return;
404 }
405
406 /* We're not interested in the inserted comment */
407 if (ins_comment != NULL((void*)0))
408 dom_node_unref((struct dom_node *) ins_comment)dom_node_unref((dom_node *) ((struct dom_node *) ins_comment)
)
;
409
410 /* No longer interested in comment */
411 dom_node_unref((struct dom_node *) comment)dom_node_unref((dom_node *) ((struct dom_node *) comment));
412
413}
414
415static void
416expat_xmlparser_start_doctype_decl_handler(void *_parser,
417 const XML_Char *doctype_name,
418 const XML_Char *system_id,
419 const XML_Char *public_id,
420 int has_internal_subset)
421{
422 dom_xml_parser *parser = _parser;
423 struct dom_document_type *doctype, *ins_doctype = NULL((void*)0);
424 dom_exception err;
425
426 UNUSED(has_internal_subset)((void)(has_internal_subset));
427
428 err = dom_implementation_create_document_type(
429 doctype_name, system_id ? system_id : "",
430 public_id ? public_id : "",
431 &doctype);
432
433 if (err != DOM_NO_ERR) {
434 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
435 "Failed to create document type");
436 return;
437 }
438
439 /* Add doctype to document */
440 err = dom_node_append_child(parser->doc, (struct dom_node *) doctype,dom_node_append_child( (dom_node *) (parser->doc), (dom_node
*) ((struct dom_node *) doctype), (dom_node **) ((struct dom_node
**) (void *) &ins_doctype))
441 (struct dom_node **) (void *) &ins_doctype)dom_node_append_child( (dom_node *) (parser->doc), (dom_node
*) ((struct dom_node *) doctype), (dom_node **) ((struct dom_node
**) (void *) &ins_doctype))
;
442 if (err != DOM_NO_ERR) {
443 dom_node_unref((struct dom_node *) doctype)dom_node_unref((dom_node *) ((struct dom_node *) doctype));
444 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
445 "Failed attaching doctype");
446 return;
447 }
448
449 /* Not interested in inserted node */
450 if (ins_doctype != NULL((void*)0))
451 dom_node_unref((struct dom_node *) ins_doctype)dom_node_unref((dom_node *) ((struct dom_node *) ins_doctype)
)
;
452
453 /* No longer interested in doctype */
454 dom_node_unref((struct dom_node *) doctype)dom_node_unref((dom_node *) ((struct dom_node *) doctype));
455}
456
457static void
458expat_xmlparser_unknown_data_handler(void *_parser,
459 const XML_Char *s,
460 int len)
461{
462 UNUSED(_parser)((void)(_parser));
463 UNUSED(s)((void)(s));
464 UNUSED(len)((void)(len));
465}
466/**
467 * Create an XML parser instance
468 *
469 * \param enc Source charset, or NULL
470 * \param int_enc Desired charset of document buffer (UTF-8 or UTF-16)
471 * \param msg Informational message function
472 * \param mctx Pointer to client-specific private data
473 * \param document DOM Document
474 * \return Pointer to instance, or NULL on memory exhaustion
475 *
476 * int_enc is ignored due to it being made of bees.
477 */
478dom_xml_parser *
479dom_xml_parser_create(const char *enc, const char *int_enc,
480 dom_msg msg, void *mctx, dom_document **document)
481{
482 dom_xml_parser *parser;
483 dom_exception err;
484
485 UNUSED(int_enc)((void)(int_enc));
486
487 parser = calloc(1, sizeof(*parser));
488 if (parser == NULL((void*)0)) {
489 msg(DOM_MSG_CRITICAL, mctx, "No memory for parser");
490 return NULL((void*)0);
491 }
492
493 parser->msg = msg;
494 parser->mctx = mctx;
495
496 parser->parser = XML_ParserCreateNS(enc, '\n');
497
498 if (parser->parser == NULL((void*)0)) {
499 free(parser);
500 msg(DOM_MSG_CRITICAL, mctx, "No memory for parser");
501 return NULL((void*)0);
502 }
503
504 parser->doc = NULL((void*)0);
505
506 err = dom_implementation_create_document(
507 DOM_IMPLEMENTATION_XML,
508 /* namespace */ NULL((void*)0),
509 /* qname */ NULL((void*)0),
510 /* doctype */ NULL((void*)0),
511 NULL((void*)0),
512 NULL((void*)0),
513 document);
514
515 if (err != DOM_NO_ERR) {
516 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
517 "Failed creating document");
518 XML_ParserFree(parser->parser);
519 free(parser);
520 return NULL((void*)0);
521 }
522
523 parser->doc = (dom_document *) dom_node_ref(*document)dom_node_ref((dom_node *) (*document));
524
525 XML_SetUserData(parser->parser, parser);
526
527 XML_SetElementHandler(parser->parser,
528 expat_xmlparser_start_element_handler,
529 expat_xmlparser_end_element_handler);
530
531 XML_SetCdataSectionHandler(parser->parser,
532 expat_xmlparser_start_cdata_handler,
533 expat_xmlparser_end_cdata_handler);
534
535 XML_SetCharacterDataHandler(parser->parser,
536 expat_xmlparser_cdata_handler);
537
538 XML_SetParamEntityParsing(parser->parser,
539 XML_PARAM_ENTITY_PARSING_ALWAYS);
540
541 XML_SetExternalEntityRefHandler(parser->parser,
542 expat_xmlparser_external_entity_ref_handler);
543
544 XML_SetCommentHandler(parser->parser,
545 expat_xmlparser_comment_handler);
546
547 XML_SetStartDoctypeDeclHandler(parser->parser,
548 expat_xmlparser_start_doctype_decl_handler);
549
550 XML_SetDefaultHandlerExpand(parser->parser,
551 expat_xmlparser_unknown_data_handler);
552
553 parser->current = dom_node_ref(parser->doc)dom_node_ref((dom_node *) (parser->doc));
554
555 parser->is_cdata = false0;
556
557 return parser;
558}
559
560/**
561 * Destroy an XML parser instance
562 *
563 * \param parser The parser instance to destroy
564 */
565void
566dom_xml_parser_destroy(dom_xml_parser *parser)
567{
568 XML_ParserFree(parser->parser);
569 assert(parser->current)((parser->current) ? (void) (0) : __assert_fail ("parser->current"
, "bindings/xml/expat_xmlparser.c", 569, __extension__ __PRETTY_FUNCTION__
))
;
570 dom_node_unref(parser->current)dom_node_unref((dom_node *) (parser->current));
571 dom_node_unref(parser->doc)dom_node_unref((dom_node *) (parser->doc));
572 free(parser);
573}
574
575/**
576 * Parse a chunk of data
577 *
578 * \param parser The XML parser instance to use for parsing
579 * \param data Pointer to data chunk
580 * \param len Byte length of data chunk
581 * \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | expat error on failure
582 */
583dom_xml_error
584dom_xml_parser_parse_chunk(dom_xml_parser *parser, uint8_t *data, size_t len)
585{
586 enum XML_Status status;
587
588 status = XML_Parse(parser->parser, (const char *)data, len, 0);
589 if (status != XML_STATUS_OKXML_STATUS_OK) {
590 parser->msg(DOM_MSG_ERROR, parser->mctx,
591 "XML_Parse failed: %d", status);
592 return DOM_XML_EXTERNAL_ERR | status;
593 }
594
595 return DOM_XML_OK;
596}
597
598/**
599 * Notify parser that datastream is empty
600 *
601 * \param parser The XML parser instance to notify
602 * \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | expat error on failure
603 *
604 * This will force any remaining data through the parser
605 */
606dom_xml_error
607dom_xml_parser_completed(dom_xml_parser *parser)
608{
609 enum XML_Status status;
610
611 status = XML_Parse(parser->parser, "", 0, 1);
612 if (status != XML_STATUS_OKXML_STATUS_OK) {
613 parser->msg(DOM_MSG_ERROR, parser->mctx,
614 "XML_Parse failed: %d", status);
615 return DOM_XML_EXTERNAL_ERR | status;
616 }
617
618 return DOM_XML_OK;
619
620}