Bug Summary

File:epan/dissectors/packet-xml.c
Warning:line 1373, column 10
Null pointer passed to 1st parameter expecting 'nonnull'

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 packet-xml.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 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-20/lib/clang/20 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-20/lib/clang/20/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 -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-09-13-101102-3933-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-xml.c
1/* packet-xml.c
2 * wireshark's xml dissector .
3 *
4 * (C) 2005, Luis E. Garcia Ontanon.
5 *
6 * Refer to the AUTHORS file or the AUTHORS section in the man page
7 * for contacting the author(s) of this file.
8 *
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <[email protected]>
11 * Copyright 1998 Gerald Combs
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16#include "config.h"
17
18#include <string.h>
19#include <errno(*__errno_location ()).h>
20
21#include <epan/packet.h>
22#include <epan/tvbparse.h>
23#include <epan/proto_data.h>
24#include <wsutil/filesystem.h>
25#include <epan/prefs.h>
26#include <epan/expert.h>
27#include <epan/iana_charsets.h>
28#include <epan/asn1.h>
29#include <epan/read_keytab_file.h>
30#include <wsutil/str_util.h>
31#include <wsutil/report_message.h>
32#include <wsutil/wsgcrypt.h>
33#include <wsutil/array.h>
34#include "packet-kerberos.h"
35
36#include <libxml/parser.h>
37
38#include "packet-xml.h"
39#include "packet-acdr.h"
40
41void proto_register_xml(void);
42void proto_reg_handoff_xml(void);
43
44struct _attr_reg_data {
45 wmem_array_t *hf;
46 const char *basename;
47};
48
49
50static int ett_dtd;
51static int ett_xmpli;
52
53static int hf_unknowwn_attrib;
54static int hf_comment;
55static int hf_xmlpi;
56static int hf_dtd_tag;
57static int hf_doctype;
58static int hf_cdatasection;
59
60static expert_field ei_xml_closing_unopened_tag;
61static expert_field ei_xml_closing_unopened_xmpli_tag;
62static expert_field ei_xml_unrecognized_text;
63
64/* dissector handles */
65static dissector_handle_t xml_handle;
66static dissector_handle_t gssapi_handle;
67
68/* Port 3702 is IANA-registered for Web Service Discovery, which uses
69 * SOAP-over-UDP to send XML */
70#define XML_UDP_PORT_RANGE"3702" "3702"
71
72/* parser definitions */
73static tvbparse_wanted_t *want;
74static tvbparse_wanted_t *want_ignore;
75static tvbparse_wanted_t *want_heur;
76
77static wmem_map_t *xmpli_names;
78static wmem_map_t *media_types;
79
80
81typedef struct _xml_ns_t {
82 /* the name of this namespace */
83 char* name;
84
85 /* its fully qualified name */
86 const char* fqn;
87
88 /* the contents of the whole element from <> to </> */
89 int hf_tag;
90
91 /* chunks of cdata from <> to </> excluding sub tags */
92 int hf_cdata;
93
94 /* the subtree for its sub items */
95 int ett;
96
97 wmem_map_t* attributes;
98 /* key: the attribute name
99 value: hf_id of what's between quotes */
100
101 /* the namespace's namespaces */
102 wmem_map_t* elements;
103 /* key: the element name
104 value: the child namespace */
105
106 GList* element_names;
107 /* imported directly from the parser and used while building the namespace */
108
109} xml_ns_t;
110
111static xml_ns_t xml_ns = {"xml", "/", 0, 0, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0)};
112static xml_ns_t unknown_ns = {"unknown", "?", 0, 0, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0)};
113static xml_ns_t *root_ns;
114
115static bool_Bool pref_heuristic_unicode;
116static int pref_default_encoding = IANA_CS_UTF_8;
117
118
119#define XML_CDATA-1000 -1000
120#define XML_SCOPED_NAME-1001 -1001
121
122
123typedef struct _dtd_named_list_t {
124 char* name;
125 GList* list;
126} dtd_named_list_t;
127
128typedef struct _dtd_build_data_t {
129 char* proto_name;
130 char* media_type;
131 char* description;
132 char* proto_root;
133 bool_Bool recursion;
134
135 GPtrArray* elements;
136 GPtrArray* attributes;
137
138 GString* error;
139
140} dtd_build_data_t;
141
142static wmem_array_t *hf_arr;
143static GArray *ett_arr;
144static GRegex* encoding_pattern;
145
146static const char *default_media_types[] = {
147 "text/xml",
148 "text/vnd.wap.wml",
149 "text/vnd.wap.si",
150 "text/vnd.wap.sl",
151 "text/vnd.wap.co",
152 "text/vnd.wap.emn",
153 "application/3gpp-ims+xml",
154 "application/atom+xml",
155 "application/auth-policy+xml",
156 "application/ccmp+xml",
157 "application/conference-info+xml", /*RFC4575*/
158 "application/cpim-pidf+xml",
159 "application/cpl+xml",
160 "application/dds-web+xml",
161 "application/im-iscomposing+xml", /*RFC3994*/
162 "application/load-control+xml", /*RFC7200*/
163 "application/mathml+xml",
164 "application/media_control+xml",
165 "application/note+xml",
166 "application/pidf+xml",
167 "application/pidf-diff+xml",
168 "application/poc-settings+xml",
169 "application/rdf+xml",
170 "application/reginfo+xml",
171 "application/resource-lists+xml",
172 "application/rlmi+xml",
173 "application/rls-services+xml",
174 "application/rss+xml",
175 "application/rs-metadata+xml",
176 "application/smil",
177 "application/simple-filter+xml",
178 "application/simple-message-summary+xml", /*RFC3842*/
179 "application/simservs+xml",
180 "application/soap+xml",
181 "application/vnd.etsi.aoc+xml",
182 "application/vnd.etsi.cug+xml",
183 "application/vnd.etsi.iptvcommand+xml",
184 "application/vnd.etsi.iptvdiscovery+xml",
185 "application/vnd.etsi.iptvprofile+xml",
186 "application/vnd.etsi.iptvsad-bc+xml",
187 "application/vnd.etsi.iptvsad-cod+xml",
188 "application/vnd.etsi.iptvsad-npvr+xml",
189 "application/vnd.etsi.iptvservice+xml",
190 "application/vnd.etsi.iptvsync+xml",
191 "application/vnd.etsi.iptvueprofile+xml",
192 "application/vnd.etsi.mcid+xml",
193 "application/vnd.etsi.overload-control-policy-dataset+xml",
194 "application/vnd.etsi.pstn+xml",
195 "application/vnd.etsi.sci+xml",
196 "application/vnd.etsi.simservs+xml",
197 "application/vnd.etsi.tsl+xml",
198 "application/vnd.oma.xdm-apd+xml",
199 "application/vnd.oma.fnl+xml",
200 "application/vnd.oma.access-permissions-list+xml",
201 "application/vnd.oma.alias-principals-list+xml",
202 "application/upp-directory+xml", /*OMA-ERELD-XDM-V2_2_1-20170124-A*/
203 "application/vnd.oma.xdm-hi+xml",
204 "application/vnd.oma.xdm-rhi+xml",
205 "application/vnd.oma.xdm-prefs+xml",
206 "application/vnd.oma.xdcp+xml",
207 "application/vnd.oma.bcast.associated-procedure-parameter+xml",
208 "application/vnd.oma.bcast.drm-trigger+xml",
209 "application/vnd.oma.bcast.imd+xml",
210 "application/vnd.oma.bcast.notification+xml",
211 "application/vnd.oma.bcast.sgdd+xml",
212 "application/vnd.oma.bcast.smartcard-trigger+xml",
213 "application/vnd.oma.bcast.sprov+xml",
214 "application/vnd.oma.cab-address-book+xml",
215 "application/vnd.oma.cab-feature-handler+xml",
216 "application/vnd.oma.cab-pcc+xml",
217 "application/vnd.oma.cab-subs-invite+xml",
218 "application/vnd.oma.cab-user-prefs+xml",
219 "application/vnd.oma.dd2+xml",
220 "application/vnd.oma.drm.risd+xml",
221 "application/vnd.oma.group-usage-list+xml",
222 "application/vnd.oma.pal+xml",
223 "application/vnd.oma.poc.detailed-progress-report+xml",
224 "application/vnd.oma.poc.final-report+xml",
225 "application/vnd.oma.poc.groups+xml",
226 "application/vnd.oma.poc.invocation-descriptor+xml",
227 "application/vnd.oma.poc.optimized-progress-report+xml",
228 "application/vnd.oma.scidm.messages+xml",
229 "application/vnd.oma.suppnot+xml", /*OMA-ERELD-Presence_SIMPLE-V2_0-20120710-A*/
230 "application/vnd.oma.xcap-directory+xml",
231 "application/vnd.omads-email+xml",
232 "application/vnd.omads-file+xml",
233 "application/vnd.omads-folder+xml",
234 "application/vnd.3gpp.access-transfer-events+xml",
235 "application/vnd.3gpp.bsf+xml",
236 "application/vnd.3gpp.comm-div-info+xml", /*3GPP TS 24.504 version 8.19.0*/
237 "application/vnd.3gpp.cw+xml",
238 "application/vnd.3gpp.iut+xml", /*3GPP TS 24.337*/
239 "application/vnc.3gpp.iut-config+xml", /*3GPP TS 24.337*/
240 "application/vnd.3gpp.mcptt-info+xml", /*3GPP TS 24.379 version 17.6.0*/
241 "application/vnd.3gpp.mcptt-mbms-usage-info+xml", /*3GPP TS 24.379 version 17.6.0*/
242 "application/vnd.3gpp.mcptt-location-info+xml", /*3GPP TS 24.379 version 17.6.0*/
243 "application/vnd.3gpp.mcptt-affiliation-command+xml", /*3GPP TS 24.379 version 17.6.0*/
244 "application/vnd.3gpp.mcptt-floor-request+xml", /*3GPP TS 24.379 version 17.6.0*/
245 "application/vnd.3gpp.mcptt-signed+xml", /*3GPP TS 24.379 version 17.6.0*/
246 "application/vnd.3gpp.mcptt-regroup+xml", /*3GPP TS 24.379 version 17.6.0*/
247 "application/vnd.3gpp.mcdata-info+xml", /*3GPP TS 24.282 version 17.6.2*/
248 "application/vnd.3gpp.mcdata-mbms-usage-info+xml", /*3GPP TS 24.282 version 17.6.2*/
249 "application/vnd.3gpp.mcdata-location-info+xml", /*3GPP TS 24.282 version 17.6.2*/
250 "application/vnd.3gpp.mcdata-affiliation-command+xml", /*3GPP TS 24.282 version 17.6.2*/
251 "application/vnd.3gpp.mcdata-regroup+xml", /*3GPP TS 24.282 version 17.6.2*/
252 "application/vnd.3gpp.mcvideo-info+xml", /*3GPP TS 24.281 version 17.6.0*/
253 "application/vnd.3gpp.mcvideo-mbms-usage-info+xml", /*3GPP TS 24.281 version 17.6.0*/
254 "application/vnd.3gpp.mcvideo-location-info+xml", /*3GPP TS 24.281 version 17.6.0*/
255 "application/vnd.3gpp.mcvideo-affiliation-command+xml",/*3GPP TS 24.281 version 17.6.0*/
256 "application/vnd.3gpp.transmission-request+xml", /*3GPP TS 24.281 version 17.6.0*/
257 "application/vnd.3gpp.mcptt-ue-init-config+xml", /*3GPP TS 24.484 version 17.5.0*/
258 "application/vnd.3gpp.mcptt-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
259 "application/vnd.3gpp.mcptt-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
260 "application/vnd.3gpp.mcptt-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
261 "application/vnd.3gpp.mcdata-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
262 "application/vnd.3gpp.mcvideo-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
263 "application/vnd.3gpp.mcvideo-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
264 "application/vnd.3gpp.mcvideo-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
265 "application/vnd.3gpp.mcdata-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
266 "application/vnd.3gpp.mcdata-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
267 "application/vnd.3gpp.mid-call+xml",
268 "application/vnd.3gpp-prose-pc3ch+xml",
269 "application/vnd.3gpp-prose+xml",
270 "application/vnd.3gpp.replication+xml", /*3GPP TS 24.337*/
271 "application/vnd.3gpp.sms+xml",
272 "application/vnd.3gpp.srvcc-info+xml",
273 "application/vnd.3gpp.srvcc-ext+xml",
274 "application/vnd.3gpp.state-and-event-info+xml",
275 "application/vnd.3gpp.ussd+xml",
276 "application/vnd.3gpp2.bcmcsinfo+xml",
277 "application/vnd.wv.csp+xml",
278 "application/vnd.wv.csp.xml",
279 "application/watcherinfo+xml",
280 "application/xcap-att+xml",
281 "application/xcap-caps+xml",
282 "application/xcap-diff+xml",
283 "application/xcap-el+xml",
284 "application/xcap-error+xml",
285 "application/xcap-ns+xml",
286 "application/xml",
287 "application/xml-dtd",
288 "application/xpidf+xml",
289 "application/xslt+xml",
290 "application/x-crd+xml",
291 "application/x-wms-logconnectstats",
292 "application/x-wms-logplaystats",
293 "application/x-wms-sendevent",
294 "image/svg+xml",
295 "message/imdn+xml", /*RFC5438*/
296};
297
298static void insert_xml_frame(xml_frame_t *parent, xml_frame_t *new_child)
299{
300 new_child->first_child = NULL((void*)0);
301 new_child->last_child = NULL((void*)0);
302
303 new_child->parent = parent;
304 new_child->next_sibling = NULL((void*)0);
305 new_child->prev_sibling = NULL((void*)0);
306 if (parent == NULL((void*)0)) return; /* root */
307
308 if (parent->first_child == NULL((void*)0)) { /* the 1st child */
309 parent->first_child = new_child;
310 } else { /* following children */
311 parent->last_child->next_sibling = new_child;
312 new_child->prev_sibling = parent->last_child;
313 }
314 parent->last_child = new_child;
315}
316
317/* Try to get the 'encoding' attribute from XML declaration, and convert it to
318 * Wireshark character encoding.
319 */
320static unsigned
321get_char_encoding(tvbuff_t* tvb, packet_info* pinfo, char** ret_encoding_name) {
322 uint32_t iana_charset_id;
323 unsigned ws_encoding_id;
324 char* encoding_str;
325 GMatchInfo* match_info;
326 const char* xmldecl = (char*)tvb_get_string_enc(pinfo->pool, tvb, 0,
327 MIN(100, tvb_captured_length(tvb))(((100) < (tvb_captured_length(tvb))) ? (100) : (tvb_captured_length
(tvb)))
, ENC_UTF_80x00000002);
328
329 g_regex_match(encoding_pattern, xmldecl, 0, &match_info);
330 if (g_match_info_matches(match_info)) {
331 char* match_ret = g_match_info_fetch(match_info, 1);
332 encoding_str = ascii_strup_inplace(wmem_strdup(pinfo->pool, match_ret));
333 g_free(match_ret);
334 /* Get the iana charset enum number by the name of the charset. */
335 iana_charset_id = str_to_val(encoding_str,
336 VALUE_STRING_EXT_VS_P(&mibenum_vals_character_sets_ext)(&mibenum_vals_character_sets_ext)->_vs_p, IANA_CS_US_ASCII);
337 } else {
338 /* Use default encoding preference if this xml does not contains 'encoding' attribute. */
339 iana_charset_id = pref_default_encoding;
340 encoding_str = val_to_str_ext(pinfo->pool, iana_charset_id,
341 &mibenum_vals_character_sets_ext, "UNKNOWN");
342 }
343 g_match_info_free(match_info);
344
345 ws_encoding_id = mibenum_charset_to_encoding((unsigned)iana_charset_id);
346
347 /* UTF-8 compatible with ASCII */
348 if (ws_encoding_id == (ENC_NA0x00000000 | ENC_ASCII0x00000000)) {
349 ws_encoding_id = ENC_UTF_80x00000002;
350 *ret_encoding_name = wmem_strdup(pinfo->pool, "UTF-8");
351 } else {
352 *ret_encoding_name = encoding_str;
353 }
354
355 return ws_encoding_id;
356}
357
358static int
359dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
360{
361 tvbparse_t *tt;
362 static GPtrArray *stack;
363 xml_frame_t *current_frame;
364 const char *colinfo_str;
365 tvbuff_t *decoded;
366 uint16_t try_bom;
367
368 if (stack != NULL((void*)0))
369 g_ptr_array_free(stack, true1);
370
371 stack = g_ptr_array_new();
372 current_frame = wmem_new(pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((pinfo->pool), sizeof(xml_frame_t
)))
;
373 current_frame->type = XML_FRAME_ROOT0;
374 current_frame->name = NULL((void*)0);
375 current_frame->name_orig_case = NULL((void*)0);
376 current_frame->value = NULL((void*)0);
377 current_frame->pinfo = pinfo;
378 insert_xml_frame(NULL((void*)0), current_frame);
379 g_ptr_array_add(stack, current_frame);
380
381 /* Detect and act on possible byte-order mark (BOM) */
382 try_bom = tvb_get_ntohs(tvb, 0);
383 if (try_bom == 0xFEFF) {
384 /* UTF-16BE */
385 const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000);
386 size_t l = strlen(data_str);
387 decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l);
388 add_new_data_source(pinfo, decoded, "Decoded UTF-16BE text");
389 }
390 else if(try_bom == 0xFFFE) {
391 /* UTF-16LE (or possibly UTF-32LE, but Wireshark doesn't support UTF-32) */
392 const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_160x00000004|ENC_LITTLE_ENDIAN0x80000000);
393 size_t l = strlen(data_str);
394 decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l);
395 add_new_data_source(pinfo, decoded, "Decoded UTF-16LE text");
396 }
397 /* Could also test if try_bom is 0xnn00 or 0x00nn to guess endianness if we wanted */
398 else {
399 /* Get character encoding according to XML declaration or preference. */
400 char* encoding_name;
401 unsigned encoding = get_char_encoding(tvb, pinfo, &encoding_name);
402
403 /* Encoding string with encoding, either with or without BOM */
404 const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), encoding);
405 size_t l = strlen(data_str);
406 decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l);
407 add_new_data_source(pinfo, decoded, wmem_strdup_printf(pinfo->pool, "Decoded %s text", encoding_name));
408 }
409
410 tt = tvbparse_init(pinfo->pool, decoded, 0, -1, stack, want_ignore);
411 current_frame->start_offset = 0;
412 current_frame->length = tvb_captured_length(decoded);
413
414 current_frame->decryption_keys = wmem_map_new(pinfo->pool, g_str_hash, g_str_equal);
415
416 root_ns = NULL((void*)0);
417
418 if (pinfo->match_string)
419 root_ns = (xml_ns_t *)wmem_map_lookup(media_types, pinfo->match_string);
420
421 if (! root_ns ) {
422 root_ns = &xml_ns;
423 colinfo_str = "/XML";
424 } else {
425 char *colinfo_str_buf;
426 colinfo_str_buf = wmem_strconcat(pinfo->pool, "/", root_ns->name, NULL((void*)0));
427 ascii_strup_inplace(colinfo_str_buf);
428 colinfo_str = colinfo_str_buf;
429 }
430
431 col_append_str(pinfo->cinfo, COL_PROTOCOL, colinfo_str);
432
433 current_frame->ns = root_ns;
434
435 current_frame->item = proto_tree_add_item(tree, current_frame->ns->hf_tag, decoded, 0, -1, ENC_UTF_80x00000002|ENC_NA0x00000000);
436 current_frame->tree = proto_item_add_subtree(current_frame->item, current_frame->ns->ett);
437 current_frame->last_item = current_frame->item;
438
439 while(tvbparse_get(tt, want)) ;
440
441 /* Save XML structure in case it is useful for the caller */
442 p_add_proto_data(pinfo->pool, pinfo, xml_ns.hf_tag, 0, current_frame);
443
444 return tvb_captured_length(tvb);
445}
446
447static bool_Bool dissect_xml_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
448{
449 if (tvbparse_peek(tvbparse_init(pinfo->pool, tvb, 0, -1, NULL((void*)0), want_ignore), want_heur)) {
450 dissect_xml(tvb, pinfo, tree, data);
451 return true1;
452 } else if (pref_heuristic_unicode) {
453 const uint8_t *data_str;
454 tvbuff_t *unicode_tvb;
455 uint16_t try_bom;
456 /* XXX - UCS-2, or UTF-16? */
457 int enc = ENC_UCS_20x00000006|ENC_LITTLE_ENDIAN0x80000000;
458 size_t l;
459
460 try_bom = tvb_get_ntohs(tvb, 0);
461 if (try_bom == 0xFEFF) {
462 enc = ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000;
463 }
464 else if(try_bom == 0xFFFE) {
465 enc = ENC_UTF_160x00000004|ENC_LITTLE_ENDIAN0x80000000;
466 }
467
468 data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), enc);
469 l = strlen(data_str);
470 unicode_tvb = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l);
471 if (tvbparse_peek(tvbparse_init(pinfo->pool, unicode_tvb, 0, -1, NULL((void*)0), want_ignore), want_heur)) {
472 add_new_data_source(pinfo, unicode_tvb, "UTF8");
473 dissect_xml(unicode_tvb, pinfo, tree, data);
474 return true1;
475 }
476 }
477 return false0;
478}
479
480xml_frame_t *xml_get_tag(xml_frame_t *frame, const char *name)
481{
482 xml_frame_t *tag = NULL((void*)0);
483
484 xml_frame_t *xml_item = frame->first_child;
485 while (xml_item) {
486 if (xml_item->type == XML_FRAME_TAG1) {
487 if (!name) { /* get the 1st tag */
488 tag = xml_item;
489 break;
490 } else if (xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) {
491 tag = xml_item;
492 break;
493 }
494 }
495 xml_item = xml_item->next_sibling;
496 }
497
498 return tag;
499}
500
501xml_frame_t *xml_get_attrib(xml_frame_t *frame, const char *name)
502{
503 xml_frame_t *attr = NULL((void*)0);
504
505 xml_frame_t *xml_item = frame->first_child;
506 while (xml_item) {
507 if ((xml_item->type == XML_FRAME_ATTRIB4) &&
508 xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) {
509 attr = xml_item;
510 break;
511 }
512 xml_item = xml_item->next_sibling;
513 }
514
515 return attr;
516}
517
518xml_frame_t *xml_get_cdata(xml_frame_t *frame)
519{
520 xml_frame_t *cdata = NULL((void*)0);
521
522 xml_frame_t *xml_item = frame->first_child;
523 while (xml_item) {
524 if (xml_item->type == XML_FRAME_CDATA5) {
525 cdata = xml_item;
526 break;
527 }
528 xml_item = xml_item->next_sibling;
529 }
530
531 return cdata;
532}
533
534static void after_token(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
535{
536 GPtrArray *stack = (GPtrArray *)tvbparse_data;
537 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
538 int hfid;
539 bool_Bool is_cdata = false0;
540 proto_item *pi;
541 xml_frame_t *new_frame = NULL((void*)0);
542 char *text = NULL((void*)0);
543
544 if (tok->id == XML_CDATA-1000) {
545 hfid = current_frame->ns ? current_frame->ns->hf_cdata : xml_ns.hf_cdata;
546 is_cdata = true1;
547 } else if ( tok->id > 0) {
548 hfid = tok->id;
549 } else {
550 hfid = xml_ns.hf_cdata;
551 }
552
553 pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000);
554
555 text = tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len);
556 proto_item_set_text(pi, "%s", text);
557
558 if (is_cdata) {
559 new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool),
sizeof(xml_frame_t)))
;
560 new_frame->type = XML_FRAME_CDATA5;
561 new_frame->name = NULL((void*)0);
562 new_frame->name_orig_case = NULL((void*)0);
563 new_frame->value = tvb_new_subset_length(tok->tvb, tok->offset, tok->len);
564 insert_xml_frame(current_frame, new_frame);
565 new_frame->item = pi;
566 new_frame->last_item = pi;
567 new_frame->tree = NULL((void*)0);
568 new_frame->start_offset = tok->offset;
569 new_frame->length = tok->len;
570 new_frame->ns = NULL((void*)0);
571 new_frame->pinfo = current_frame->pinfo;
572 }
573
574 if (new_frame != NULL((void*)0) &&
575 current_frame != NULL((void*)0) &&
576 current_frame->name_orig_case != NULL((void*)0) &&
577 strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0)
578 {
579 xml_frame_t *value_type = NULL((void*)0);
580
581 value_type = xml_get_attrib(current_frame, "ValueType");
582 if (value_type != NULL((void*)0)) {
583 const char *s = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
584 size_t l = strlen(s);
585 int c;
586 c = tvb_strneql(value_type->value, 0, s, l);
587 if (c == 0) {
588 tvbuff_t *ssp_tvb = base64_to_tvb(new_frame->value, text);
589 add_new_data_source(current_frame->pinfo, ssp_tvb, "GSSAPI Data");
590 call_dissector(gssapi_handle, ssp_tvb,
591 current_frame->pinfo, current_frame->tree);
592 }
593 }
594 }
595}
596
597static void before_xmpli(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
598{
599 GPtrArray *stack = (GPtrArray *)tvbparse_data;
600 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
601 proto_item *pi;
602 proto_tree *pt;
603 tvbparse_elem_t *name_tok = tok->sub->next;
604 char *name = tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb, name_tok->offset, name_tok->len, ENC_ASCII0x00000000);
605 xml_ns_t *ns = (xml_ns_t *)wmem_map_lookup(xmpli_names, name);
606 xml_frame_t *new_frame;
607
608 int hf_tag;
609 int ett;
610
611 ascii_strdown_inplace(name);
612 if (!ns) {
613 hf_tag = hf_xmlpi;
614 ett = ett_xmpli;
615 } else {
616 hf_tag = ns->hf_tag;
617 ett = ns->ett;
618 }
619
620 pi = proto_tree_add_item(current_frame->tree, hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000);
621
622 proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, (name_tok->offset - tok->offset) + name_tok->len));
623
624 pt = proto_item_add_subtree(pi, ett);
625
626 new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool),
sizeof(xml_frame_t)))
;
627 new_frame->type = XML_FRAME_XMPLI2;
628 new_frame->name = name;
629 new_frame->name_orig_case = name;
630 new_frame->value = NULL((void*)0);
631 insert_xml_frame(current_frame, new_frame);
632 new_frame->item = pi;
633 new_frame->last_item = pi;
634 new_frame->tree = pt;
635 new_frame->start_offset = tok->offset;
636 new_frame->length = tok->len;
637 new_frame->ns = ns;
638 new_frame->pinfo = current_frame->pinfo;
639
640 g_ptr_array_add(stack, new_frame);
641
642}
643
644static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
645{
646 GPtrArray *stack = (GPtrArray *)tvbparse_data;
647 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
648
649 proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len);
650
651 if (stack->len > 1) {
652 g_ptr_array_remove_index_fast(stack, stack->len - 1);
653 } else {
654 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_xmpli_tag,
655 tok->tvb, tok->offset, tok->len);
656 }
657}
658
659static void before_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
660{
661 GPtrArray *stack = (GPtrArray *)tvbparse_data;
662 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
663 tvbparse_elem_t *name_tok = tok->sub->next;
664 char *root_name;
665 char *name = NULL((void*)0), *name_orig_case = NULL((void*)0);
666 xml_ns_t *ns;
667 xml_frame_t *new_frame;
668 proto_item *pi;
669 proto_tree *pt;
670
671 if (name_tok->sub->id == XML_SCOPED_NAME-1001) {
672 tvbparse_elem_t *root_tok = name_tok->sub->sub;
673 tvbparse_elem_t *leaf_tok = name_tok->sub->sub->next->next;
674 xml_ns_t *nameroot_ns;
675
676 root_name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, root_tok->tvb, root_tok->offset, root_tok->len, ENC_ASCII0x00000000);
677 name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, leaf_tok->tvb, leaf_tok->offset, leaf_tok->len, ENC_ASCII0x00000000);
678 name_orig_case = name;
679
680 nameroot_ns = (xml_ns_t *)wmem_map_lookup(xml_ns.elements, root_name);
681
682 if(nameroot_ns) {
683 ns = (xml_ns_t *)wmem_map_lookup(nameroot_ns->elements, name);
684 if (!ns) {
685 ns = &unknown_ns;
686 }
687 } else {
688 ns = &unknown_ns;
689 }
690
691 } else {
692 name = tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb, name_tok->offset, name_tok->len, ENC_ASCII0x00000000);
693 name_orig_case = wmem_strdup(current_frame->pinfo->pool, name);
694 ascii_strdown_inplace(name);
695
696 if(current_frame->ns) {
697 ns = (xml_ns_t *)wmem_map_lookup(current_frame->ns->elements, name);
698
699 if (!ns) {
700 if (! ( ns = (xml_ns_t *)wmem_map_lookup(root_ns->elements, name) ) ) {
701 ns = &unknown_ns;
702 }
703 }
704 } else {
705 ns = &unknown_ns;
706 }
707 }
708
709 pi = proto_tree_add_item(current_frame->tree, ns->hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000);
710 proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb,
711 tok->offset,
712 (name_tok->offset - tok->offset) + name_tok->len));
713
714 pt = proto_item_add_subtree(pi, ns->ett);
715
716 new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool),
sizeof(xml_frame_t)))
;
717 new_frame->type = XML_FRAME_TAG1;
718 new_frame->name = name;
719 new_frame->name_orig_case = name_orig_case;
720 new_frame->value = NULL((void*)0);
721 insert_xml_frame(current_frame, new_frame);
722 new_frame->item = pi;
723 new_frame->last_item = pi;
724 new_frame->tree = pt;
725 new_frame->start_offset = tok->offset;
726 new_frame->length = tok->len;
727 new_frame->ns = ns;
728 new_frame->pinfo = current_frame->pinfo;
729
730 g_ptr_array_add(stack, new_frame);
731
732}
733
734static void after_open_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused)))
735{
736 GPtrArray *stack = (GPtrArray *)tvbparse_data;
737 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
738
739 proto_item_append_text(current_frame->last_item, ">");
740}
741
742static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
743{
744 GPtrArray *stack = (GPtrArray *)tvbparse_data;
745 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
746
747 proto_item_append_text(current_frame->last_item, "/>");
748
749 if (stack->len > 1) {
750 g_ptr_array_remove_index_fast(stack, stack->len - 1);
751 } else {
752 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
753 tok->tvb, tok->offset, tok->len);
754 }
755}
756
757#ifdef HAVE_KERBEROS1
758struct decryption_key {
759 char *id;
760 size_t key_length;
761 uint8_t key[HASH_SHA1_LENGTH20];
762};
763
764static void P_SHA1(const uint8_t *Secret, size_t Secret_len,
765 const uint8_t *Seed, size_t Seed_len,
766 uint8_t Result[HASH_SHA1_LENGTH20])
767{
768 gcry_md_hd_t hd = NULL((void*)0);
769 uint8_t *digest = NULL((void*)0);
770
771 /*
772 * https://social.microsoft.com/Forums/en-US/c485d98b-6e0b-49e7-ab34-8ecf8d694d31/signing-soap-message-request-via-adfs?forum=crmdevelopment#6cee9fa8-dc24-4524-a5a2-c3d17e05d50e
773 */
774 gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
775 gcry_md_setkey(hd, Secret, Secret_len);
776 gcry_md_write(hd, Seed, Seed_len);
777 digest = gcry_md_read(hd, GCRY_MD_SHA1);
778 memcpy(Result, digest, HASH_SHA1_LENGTH20);
779
780 gcry_md_close(hd);
781}
782#endif /* HAVE_KERBEROS */
783
784static void after_untag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
785{
786 GPtrArray *stack = (GPtrArray *)tvbparse_data;
787 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
788#ifdef HAVE_KERBEROS1
789 xml_frame_t *top_frame = (xml_frame_t *)g_ptr_array_index(stack, 0)((stack)->pdata)[0];
790#endif /* HAVE_KERBEROS */
791
792 proto_item_set_len(current_frame->item, (tok->offset - current_frame->start_offset) + tok->len);
793 current_frame->length = (tok->offset - current_frame->start_offset) + tok->len;
794
795 proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len);
796
797 if (stack->len > 1) {
798 g_ptr_array_remove_index_fast(stack, stack->len - 1);
799 } else {
800 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
801 tok->tvb, tok->offset, tok->len);
802 }
803
804#ifdef HAVE_KERBEROS1
805 if (current_frame->name_orig_case == NULL((void*)0)) {
806 return;
807 }
808
809 if (strcmp(current_frame->name_orig_case, "DerivedKeyToken") == 0) {
810 xml_frame_t *id_frame = xml_get_attrib(current_frame, "u:Id");
811 xml_frame_t *nonce_frame = xml_get_tag(current_frame, "Nonce");
812 xml_frame_t *nonce_cdata = NULL((void*)0);
813 tvbuff_t *nonce_tvb = NULL((void*)0);
814 const enc_key_t *ek = NULL((void*)0);
815 uint8_t seed[64];
816 size_t seed_length = 16; // TODO
817 const size_t key_length = 16; //TODO
818
819 if (id_frame != NULL((void*)0) && nonce_frame != NULL((void*)0)) {
820 nonce_cdata = xml_get_cdata(nonce_frame);
821 }
822 if (nonce_cdata != NULL((void*)0)) {
823 char *text = tvb_format_text(current_frame->pinfo->pool, nonce_cdata->value, 0,
824 tvb_reported_length(nonce_cdata->value));
825 nonce_tvb = base64_to_tvb(nonce_cdata->value, text);
826 }
827 if (nonce_tvb != NULL((void*)0)) {
828 seed_length = tvb_reported_length(nonce_tvb);
829 seed_length = MIN(seed_length, sizeof(seed))(((seed_length) < (sizeof(seed))) ? (seed_length) : (sizeof
(seed)))
;
830 tvb_memcpy(nonce_tvb, seed, 0, seed_length);
831
832 if (krb_decrypt) {
833 read_keytab_file_from_preferences();
834 }
835
836 for (ek=keytab_get_enc_key_list();ek;ek=ek->next) {
837 if (ek->fd_num == (int)current_frame->pinfo->num) {
838 break;
839 }
840 }
841 }
842 if (ek != NULL((void*)0)) {
843 struct decryption_key *key;
844 char *id_str;
845
846 id_str = tvb_format_text(current_frame->pinfo->pool,
847 id_frame->value, 0,
848 tvb_reported_length(id_frame->value));
849
850 key = wmem_new0(current_frame->pinfo->pool, struct decryption_key)((struct decryption_key*)wmem_alloc0((current_frame->pinfo
->pool), sizeof(struct decryption_key)))
;
851 key->id = wmem_strdup_printf(current_frame->pinfo->pool, "#%s", id_str);
852 P_SHA1(ek->keyvalue, ek->keylength, seed, seed_length, key->key);
853 key->key_length = key_length;
854
855 wmem_map_insert(top_frame->decryption_keys, key->id, key);
856 }
857 }
858 if (strcmp(current_frame->name_orig_case, "CipherValue") == 0) {
859 xml_frame_t *encrypted_frame = current_frame->parent->parent;
860 xml_frame_t *key_info_frame = NULL((void*)0);
861 xml_frame_t *token_frame = NULL((void*)0);
862 xml_frame_t *reference_frame = NULL((void*)0);
863 xml_frame_t *uri_frame = NULL((void*)0);
864 const struct decryption_key *key = NULL((void*)0);
865 xml_frame_t *cdata_frame = NULL((void*)0);
866 tvbuff_t *crypt_tvb = NULL((void*)0);
867 tvbuff_t *plain_tvb = NULL((void*)0);
868
869 key_info_frame = xml_get_tag(encrypted_frame, "KeyInfo");
870 if (key_info_frame != NULL((void*)0)) {
871 token_frame = xml_get_tag(key_info_frame, "SecurityTokenReference");
872 }
873 if (token_frame != NULL((void*)0)) {
874 reference_frame = xml_get_tag(token_frame, "Reference");
875 }
876 if (reference_frame != NULL((void*)0)) {
877 uri_frame = xml_get_attrib(reference_frame, "URI");
878 }
879
880 if (uri_frame != NULL((void*)0)) {
881 char *key_id = tvb_format_text(current_frame->pinfo->pool, uri_frame->value, 0,
882 tvb_reported_length(uri_frame->value));
883
884 key = (const struct decryption_key *)wmem_map_lookup(top_frame->decryption_keys, key_id);
885 }
886 if (key != NULL((void*)0)) {
887 cdata_frame = xml_get_cdata(current_frame);
888 }
889 if (cdata_frame != NULL((void*)0)) {
890 char *text = tvb_format_text(current_frame->pinfo->pool, cdata_frame->value, 0,
891 tvb_reported_length(cdata_frame->value));
892 crypt_tvb = base64_to_tvb(cdata_frame->value, text);
893 }
894 if (crypt_tvb != NULL((void*)0)) {
895 gcry_cipher_hd_t cipher_hd = NULL((void*)0);
896 uint8_t *data = NULL((void*)0);
897 unsigned data_length = tvb_reported_length(crypt_tvb);
898
899 data = (uint8_t *)tvb_memdup(current_frame->pinfo->pool,
900 crypt_tvb, 0, data_length);
901
902 /* Open the cipher. */
903 gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
904
905 gcry_cipher_setkey(cipher_hd, key->key, key->key_length);
906 gcry_cipher_encrypt(cipher_hd, data, data_length, NULL((void*)0), 0);
907 gcry_cipher_close(cipher_hd);
908
909 plain_tvb = tvb_new_child_real_data(crypt_tvb, data,
910 data_length, data_length);
911 add_new_data_source(current_frame->pinfo, plain_tvb, "Decrypted Data");
912 }
913 }
914#endif /* HAVE_KERBEROS */
915}
916
917static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
918{
919 GPtrArray *stack = (GPtrArray *)tvbparse_data;
920 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
921 xml_frame_t *new_frame;
922 tvbparse_elem_t *name_tok = tok->sub->next->next->next->sub->sub;
923 proto_tree *dtd_item = proto_tree_add_item(current_frame->tree, hf_doctype,
924 name_tok->tvb, name_tok->offset,
925 name_tok->len, ENC_ASCII0x00000000);
926
927 proto_item_set_text(dtd_item, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len));
928
929 new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool),
sizeof(xml_frame_t)))
;
930 new_frame->type = XML_FRAME_DTD_DOCTYPE3;
931 new_frame->name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb,
932 name_tok->offset,
933 name_tok->len, ENC_ASCII0x00000000);
934 new_frame->name_orig_case = new_frame->name;
935 new_frame->value = NULL((void*)0);
936 insert_xml_frame(current_frame, new_frame);
937 new_frame->item = dtd_item;
938 new_frame->last_item = dtd_item;
939 new_frame->tree = proto_item_add_subtree(dtd_item, ett_dtd);
940 new_frame->start_offset = tok->offset;
941 new_frame->length = tok->len;
942 new_frame->ns = NULL((void*)0);
943 new_frame->pinfo = current_frame->pinfo;
944
945 g_ptr_array_add(stack, new_frame);
946}
947
948static void pop_stack(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused)))
949{
950 GPtrArray *stack = (GPtrArray *)tvbparse_data;
951 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
952
953 if (stack->len > 1) {
954 g_ptr_array_remove_index_fast(stack, stack->len - 1);
955 } else {
956 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
957 tok->tvb, tok->offset, tok->len);
958 }
959}
960
961static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
962{
963 GPtrArray *stack = (GPtrArray *)tvbparse_data;
964 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
965
966 proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len);
967 if (stack->len > 1) {
968 g_ptr_array_remove_index_fast(stack, stack->len - 1);
969 } else {
970 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
971 tok->tvb, tok->offset, tok->len);
972 }
973}
974
975static void get_attrib_value(void *tvbparse_data _U___attribute__((unused)), const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
976{
977 tok->data = tok->sub;
978}
979
980static void after_attrib(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok)
981{
982 GPtrArray *stack = (GPtrArray *)tvbparse_data;
983 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
984 char *name, *name_orig_case;
985 tvbparse_elem_t *value;
986 tvbparse_elem_t *value_part = (tvbparse_elem_t *)tok->sub->next->next->data;
987 int *hfidp;
988 int hfid;
989 proto_item *pi;
990 xml_frame_t *new_frame;
991
992 name = tvb_get_string_enc(current_frame->pinfo->pool, tok->sub->tvb, tok->sub->offset, tok->sub->len, ENC_ASCII0x00000000);
993 name_orig_case = wmem_strdup(current_frame->pinfo->pool, name);
994 ascii_strdown_inplace(name);
995
996 if(current_frame->ns && (hfidp = (int *)wmem_map_lookup(current_frame->ns->attributes, name) )) {
997 hfid = *hfidp;
998 value = value_part;
999 } else {
1000 hfid = hf_unknowwn_attrib;
1001 value = tok;
1002 }
1003
1004 pi = proto_tree_add_item(current_frame->tree, hfid, value->tvb, value->offset, value->len, ENC_UTF_80x00000002|ENC_NA0x00000000);
1005 proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len));
1006
1007 current_frame->last_item = pi;
1008
1009 new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool),
sizeof(xml_frame_t)))
;
1010 new_frame->type = XML_FRAME_ATTRIB4;
1011 new_frame->name = name;
1012 new_frame->name_orig_case = name_orig_case;
1013 new_frame->value = tvb_new_subset_length(value_part->tvb, value_part->offset,
1014 value_part->len);
1015 insert_xml_frame(current_frame, new_frame);
1016 new_frame->item = pi;
1017 new_frame->last_item = pi;
1018 new_frame->tree = NULL((void*)0);
1019 new_frame->start_offset = tok->offset;
1020 new_frame->length = tok->len;
1021 new_frame->ns = NULL((void*)0);
1022 new_frame->pinfo = current_frame->pinfo;
1023
1024}
1025
1026static void unrecognized_token(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused)))
1027{
1028 GPtrArray *stack = (GPtrArray *)tvbparse_data;
1029 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1];
1030
1031 proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_unrecognized_text,
1032 tok->tvb, tok->offset, tok->len);
1033
1034}
1035
1036
1037
1038static void init_xml_parser(void)
1039{
1040 tvbparse_wanted_t *want_name =
1041 tvbparse_chars(-1, 1, 0,
1042 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
1043 NULL((void*)0), NULL((void*)0), NULL((void*)0));
1044 tvbparse_wanted_t *want_attr_name =
1045 tvbparse_chars(-1, 1, 0,
1046 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:",
1047 NULL((void*)0), NULL((void*)0), NULL((void*)0));
1048
1049 tvbparse_wanted_t *want_scoped_name = tvbparse_set_seq(XML_SCOPED_NAME-1001, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1050 want_name,
1051 tvbparse_char(-1, ":", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1052 want_name,
1053 NULL((void*)0));
1054
1055 tvbparse_wanted_t *want_tag_name = tvbparse_set_oneof(0, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1056 want_scoped_name,
1057 want_name,
1058 NULL((void*)0));
1059
1060 tvbparse_wanted_t *want_attrib_value = tvbparse_set_oneof(0, NULL((void*)0), NULL((void*)0), get_attrib_value,
1061 tvbparse_quoted(-1, NULL((void*)0), NULL((void*)0), tvbparse_shrink_token_cb, '\"', '\\'),
1062 tvbparse_quoted(-1, NULL((void*)0), NULL((void*)0), tvbparse_shrink_token_cb, '\'', '\\'),
1063 tvbparse_chars(-1, 1, 0, "0123456789", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1064 want_name,
1065 NULL((void*)0));
1066
1067 tvbparse_wanted_t *want_attributes = tvbparse_one_or_more(-1, NULL, NULL, NULL,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
1068 tvbparse_set_seq(-1, NULL, NULL, after_attrib,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
1069 want_attr_name,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
1070 tvbparse_char(-1, "=", NULL, NULL, NULL),tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
1071 want_attrib_value,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
1072 NULL))tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void
*)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib
, want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*)
0), ((void*)0)), want_attrib_value, ((void*)0)))
;
1073
1074 tvbparse_wanted_t *want_stoptag = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1075 tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), after_open_tag),
1076 tvbparse_string(-1, "/>", NULL((void*)0), NULL((void*)0), after_closed_tag),
1077 NULL((void*)0));
1078
1079 tvbparse_wanted_t *want_stopxmlpi = tvbparse_string(-1, "?>", NULL((void*)0), NULL((void*)0), after_xmlpi);
1080
1081 tvbparse_wanted_t *want_comment = tvbparse_set_seq(hf_comment, NULL((void*)0), NULL((void*)0), after_token,
1082 tvbparse_string(-1, "<!--", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1083 tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1084 tvbparse_string(-1, "-->", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1085 TP_UNTIL_INCLUDE),
1086 NULL((void*)0));
1087
1088 tvbparse_wanted_t *want_cdatasection = tvbparse_set_seq(hf_cdatasection, NULL((void*)0), NULL((void*)0), after_token,
1089 tvbparse_string(-1, "<![CDATA[", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1090 tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1091 tvbparse_string(-1, "]]>", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1092 TP_UNTIL_INCLUDE),
1093 NULL((void*)0));
1094
1095 tvbparse_wanted_t *want_xmlpi = tvbparse_set_seq(hf_xmlpi, NULL((void*)0), before_xmpli, NULL((void*)0),
1096 tvbparse_string(-1, "<?", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1097 want_name,
1098 tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1099 want_stopxmlpi,
1100 tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1101 want_attributes,
1102 want_stopxmlpi,
1103 NULL((void*)0)),
1104 NULL((void*)0)),
1105 NULL((void*)0));
1106
1107 tvbparse_wanted_t *want_closing_tag = tvbparse_set_seq(0, NULL((void*)0), NULL((void*)0), after_untag,
1108 tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1109 tvbparse_char(-1, "/", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1110 want_tag_name,
1111 tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1112 NULL((void*)0));
1113
1114 tvbparse_wanted_t *want_doctype_start = tvbparse_set_seq(-1, NULL((void*)0), before_dtd_doctype, NULL((void*)0),
1115 tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1116 tvbparse_char(-1, "!", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1117 tvbparse_casestring(-1, "DOCTYPE", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1118 tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1119 tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1120 want_name,
1121 tvbparse_char(-1, "[", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1122 NULL((void*)0)),
1123 tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), pop_stack,
1124 want_name,
1125 tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1126 tvbparse_casestring(-1, "PUBLIC", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1127 tvbparse_casestring(-1, "SYSTEM", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1128 NULL((void*)0)),
1129 tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1130 tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1131 TP_UNTIL_INCLUDE),
1132 NULL((void*)0)),
1133 NULL((void*)0)),
1134 NULL((void*)0));
1135
1136 tvbparse_wanted_t *want_dtd_tag = tvbparse_set_seq(hf_dtd_tag, NULL((void*)0), NULL((void*)0), after_token,
1137 tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1138 tvbparse_char(-1, "!", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1139 tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1140 tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1141 TP_UNTIL_INCLUDE),
1142 NULL((void*)0));
1143
1144 tvbparse_wanted_t *want_tag = tvbparse_set_seq(-1, NULL((void*)0), before_tag, NULL((void*)0),
1145 tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1146 want_tag_name,
1147 tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1148 tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1149 want_attributes,
1150 want_stoptag,
1151 NULL((void*)0)),
1152 want_stoptag,
1153 NULL((void*)0)),
1154 NULL((void*)0));
1155
1156 tvbparse_wanted_t *want_dtd_close = tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), after_dtd_close,
1157 tvbparse_char(-1, "]", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1158 tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)),
1159 NULL((void*)0));
1160
1161 want_ignore = tvbparse_chars(-1, 1, 0, " \t\r\n", NULL((void*)0), NULL((void*)0), NULL((void*)0));
1162
1163
1164 want = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1165 want_comment,
1166 want_cdatasection,
1167 want_xmlpi,
1168 want_closing_tag,
1169 want_doctype_start,
1170 want_dtd_close,
1171 want_dtd_tag,
1172 want_tag,
1173 tvbparse_not_chars(XML_CDATA-1000, 1, 0, "<", NULL((void*)0), NULL((void*)0), after_token),
1174 tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL((void*)0), NULL((void*)0), unrecognized_token),
1175 NULL((void*)0));
1176
1177 want_heur = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0),
1178 want_comment,
1179 want_cdatasection,
1180 want_xmlpi,
1181 want_doctype_start,
1182 want_dtd_tag,
1183 want_tag,
1184 NULL((void*)0));
1185
1186}
1187
1188
1189static xml_ns_t *xml_new_namespace(wmem_map_t *hash, const char *name, ...)
1190{
1191 xml_ns_t *ns = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t))
)
;
1192 va_list ap;
1193 char *attr_name;
1194
1195 ns->name = wmem_strdup(wmem_epan_scope(), name);
1196 ns->hf_tag = 0;
1197 ns->hf_cdata = 0;
1198 ns->ett = 0;
1199 ns->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1200 ns->elements = NULL((void*)0);
1201
1202 va_start(ap, name)__builtin_va_start(ap, name);
1203
1204 while(( attr_name = va_arg(ap, char *)__builtin_va_arg(ap, char *) )) {
1205 int *hfp = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int)));
1206 *hfp = 0;
1207 wmem_map_insert(ns->attributes, wmem_strdup(wmem_epan_scope(), attr_name), hfp);
1208 };
1209
1210 va_end(ap)__builtin_va_end(ap);
1211
1212 wmem_map_insert(hash, ns->name, ns);
1213
1214 return ns;
1215}
1216
1217
1218static void add_xml_field(wmem_array_t *hfs, int *p_id, const char *name, const char *fqn)
1219{
1220 hf_register_info hfri;
1221
1222 hfri.p_id = p_id;
1223 hfri.hfinfo.name = name;
1224 hfri.hfinfo.abbrev = fqn;
1225 hfri.hfinfo.type = FT_STRING;
1226 hfri.hfinfo.display = BASE_NONE;
1227 hfri.hfinfo.strings = NULL((void*)0);
1228 hfri.hfinfo.bitmask = 0x0;
1229 hfri.hfinfo.blurb = NULL((void*)0);
1230 HFILL_INIT(hfri)(hfri).hfinfo.id = -1; (hfri).hfinfo.parent = 0; (hfri).hfinfo
.ref_type = HF_REF_TYPE_NONE; (hfri).hfinfo.same_name_prev_id
= -1; (hfri).hfinfo.same_name_next = ((void*)0);
;
1231
1232 wmem_array_append_one(hfs, hfri)wmem_array_append((hfs), &(hfri), 1);
1233}
1234
1235static char* fully_qualified_name(const char* name, const char* parent_name)
1236{
1237 return wmem_strdup_printf(wmem_epan_scope(), "%s.%s", parent_name, name);
1238}
1239
1240static void add_xml_attribute_names(void *k, void *v, void *p)
1241{
1242 struct _attr_reg_data *d = (struct _attr_reg_data *)p;
1243 const char *basename = wmem_strconcat(wmem_epan_scope(), d->basename, ".", (char *)k, NULL((void*)0));
1244
1245 add_xml_field(d->hf, (int*) v, (char *)k, basename);
1246}
1247
1248typedef struct _xml_element_iter_data
1249{
1250 xml_ns_t* root_element;
1251 wmem_array_t* hfs;
1252 GArray* etts;
1253} xml_element_iter_data;
1254
1255static void add_xml_flat_element_names(void* k, void* v, void* p)
1256{
1257 char* name = (char*)k;
1258 xml_ns_t* fresh = (xml_ns_t*)v;
1259 xml_element_iter_data* data = (xml_element_iter_data*)p;
1260 struct _attr_reg_data d;
1261 int* ett_p;
1262
1263 fresh->fqn = fully_qualified_name(name, data->root_element->name);
1264
1265 add_xml_field(data->hfs, &(fresh->hf_tag), name, fresh->fqn);
1266 add_xml_field(data->hfs, &(fresh->hf_cdata), name, fresh->fqn);
1267
1268 d.basename = fresh->fqn;
1269 d.hf = data->hfs;
1270
1271 wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d);
1272
1273 ett_p = &fresh->ett;
1274 g_array_append_val(data->etts, ett_p)g_array_append_vals (data->etts, &(ett_p), 1);
1275
1276 wmem_map_insert(data->root_element->elements, (void*)fresh->name, fresh);
1277}
1278
1279static void add_xmlpi_namespace(void *k _U___attribute__((unused)), void *v, void *p)
1280{
1281 xml_ns_t *ns = (xml_ns_t *)v;
1282 const char *basename = wmem_strconcat(wmem_epan_scope(), (char *)p, ".", ns->name, NULL((void*)0));
1283 int *ett_p = &(ns->ett);
1284 struct _attr_reg_data d;
1285
1286 add_xml_field(hf_arr, &(ns->hf_tag), basename, basename);
1287
1288 g_array_append_val(ett_arr, ett_p)g_array_append_vals (ett_arr, &(ett_p), 1);
1289
1290 d.basename = basename;
1291 d.hf = hf_arr;
1292
1293 wmem_map_foreach(ns->attributes, add_xml_attribute_names, &d);
1294
1295}
1296
1297static void destroy_dtd_data(dtd_build_data_t* dtd_data)
1298{
1299 g_string_free(dtd_data->error, true)(__builtin_constant_p (1) ? ((1) ? (g_string_free) ((dtd_data
->error), (1)) : g_string_free_and_steal (dtd_data->error
)) : (g_string_free) ((dtd_data->error), (1)))
;
1300
1301 while (dtd_data->elements->len) {
1302 dtd_named_list_t* nl = (dtd_named_list_t*)g_ptr_array_remove_index_fast(dtd_data->elements, 0);
1303 g_list_free(nl->list);
1304 g_free(nl);
1305 }
1306
1307 g_ptr_array_free(dtd_data->elements, true1);
1308
1309 while (dtd_data->attributes->len) {
1310 dtd_named_list_t* nl = (dtd_named_list_t*)g_ptr_array_remove_index_fast(dtd_data->attributes, 0);
1311 g_list_free(nl->list);
1312 g_free(nl);
1313 }
1314
1315 g_ptr_array_free(dtd_data->attributes, true1);
1316
1317 g_free(dtd_data);
1318}
1319
1320static void copy_attrib_item(void *k, void *v _U___attribute__((unused)), void *p)
1321{
1322 char *key = (char *)wmem_strdup(wmem_epan_scope(), (const char *)k);
1323 int *value = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int)));
1324 wmem_map_t *dst = (wmem_map_t *)p;
1325
1326 *value = 0;
1327 wmem_map_insert(dst, key, value);
1328
1329}
1330
1331static wmem_map_t *copy_attributes_hash(wmem_map_t *src)
1332{
1333 wmem_map_t *dst = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1334
1335 wmem_map_foreach(src, copy_attrib_item, dst);
1336
1337 return dst;
1338}
1339
1340static xml_ns_t *duplicate_element(xml_ns_t *orig)
1341{
1342 xml_ns_t *new_item = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t))
)
;
1343
1344 new_item->name = wmem_strdup(wmem_epan_scope(), orig->name);
1345 new_item->hf_tag = 0;
1346 new_item->hf_cdata = 0;
1347 new_item->ett = 0;
1348 new_item->attributes = copy_attributes_hash(orig->attributes);
1349 new_item->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1350 new_item->element_names = NULL((void*)0); // Not used for duplication
1351
1352 return new_item;
1353}
1354
1355
1356// NOLINTNEXTLINE(misc-no-recursion)
1357static xml_ns_t *make_xml_hier(char *elem_name,
1358 xml_ns_t *root,
1359 wmem_map_t *elements,
1360 GQueue *hier,
1361 GString *error,
1362 wmem_array_t *hfs,
1363 GArray *etts,
1364 const char *parent_name)
1365{
1366 xml_ns_t *fresh;
1367 xml_ns_t *orig;
1368 char *fqn;
1369 int *ett_p;
1370 unsigned depth;
1371 struct _attr_reg_data d;
1372
1373 if ( g_str_equal(elem_name, root->name)(strcmp ((const char *) (elem_name), (const char *) (root->
name)) == 0)
) {
14
Null pointer passed to 1st parameter expecting 'nonnull'
1374 return NULL((void*)0);
1375 }
1376
1377 if (! ( orig = (xml_ns_t *)wmem_map_lookup(elements, elem_name) )) {
1378 g_string_append_printf(error, "element '%s' is not defined\n", elem_name);
1379 return NULL((void*)0);
1380 }
1381
1382 depth = g_queue_get_length(hier);
1383 if (depth >= prefs.gui_max_tree_depth) {
1384 g_string_append_printf(error, "hierarchy too deep: %u\n", depth);
1385 return NULL((void*)0);
1386 }
1387
1388 for (GList* list = hier->head; list != NULL((void*)0); list = list->next) {
1389 if( (elem_name) && (strcmp(elem_name, (char *)list->data) == 0 )) {
1390 /* Already handled */
1391 return NULL((void*)0);
1392 }
1393 }
1394
1395 fqn = fully_qualified_name(elem_name, parent_name);
1396
1397 if (depth > 1) {
1398 fresh = duplicate_element(orig);
1399 } else {
1400 fresh = orig;
1401 }
1402 fresh->fqn = fqn;
1403
1404 add_xml_field(hfs, &(fresh->hf_tag), elem_name, fqn);
1405 add_xml_field(hfs, &(fresh->hf_cdata), elem_name, fqn);
1406
1407 ett_p = &fresh->ett;
1408 g_array_append_val(etts, ett_p)g_array_append_vals (etts, &(ett_p), 1);
1409
1410 d.basename = fqn;
1411 d.hf = hfs;
1412
1413 wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d);
1414
1415 for (GList* current_element = orig->element_names; current_element != NULL((void*)0); current_element = current_element->next) {
1416 char* child_name = (char*)current_element->data;
1417 xml_ns_t* child_element = NULL((void*)0);
1418
1419 g_queue_push_head(hier, elem_name);
1420 child_element = make_xml_hier(child_name, root, elements, hier, error, hfs, etts, fqn);
1421 g_queue_pop_head(hier);
1422
1423 if (child_element) {
1424 wmem_map_insert(fresh->elements, child_element->name, child_element);
1425 }
1426 }
1427 return fresh;
1428}
1429
1430static void free_elements(void* k _U___attribute__((unused)), void* v, void* p _U___attribute__((unused)))
1431{
1432 xml_ns_t* e = (xml_ns_t*)v;
1433
1434 g_list_free(e->element_names);
1435 e->element_names = NULL((void*)0);
1436}
1437
1438static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
1439{
1440 wmem_map_t *elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1441 char *root_name = NULL((void*)0);
1
'root_name' initialized to a null pointer value
1442 xml_ns_t *root_element = NULL((void*)0);
1443 wmem_array_t *hfs;
1444 GArray *etts;
1445 char *curr_name;
1446 GList *element_names = NULL((void*)0);
1447
1448 /* we first populate elements with the those coming from the parser */
1449 while(dtd_data->elements->len) {
2
Loop condition is false. Execution continues on line 1477
1450 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->elements, 0);
1451 xml_ns_t *element = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t))
)
;
1452
1453 /* we will use the first element found as root in case no other one was given. */
1454 if (root_name == NULL((void*)0))
1455 root_name = nl->name;
1456
1457 element->name = nl->name;
1458 element->element_names = nl->list;
1459 element->hf_tag = 0;
1460 element->hf_cdata = 0;
1461 element->ett = 0;
1462 element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1463 element->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1464
1465 if( wmem_map_lookup(elements, element->name) ) {
1466 g_string_append_printf(errors, "element %s defined more than once\n", element->name);
1467 free_elements(NULL((void*)0), element, NULL((void*)0));
1468 } else {
1469 wmem_map_insert(elements, element->name, element);
1470 element_names = g_list_prepend(element_names, element->name);
1471 }
1472
1473 g_free(nl);
1474 }
1475
1476 /* then we add the attributes to its relative elements */
1477 while(dtd_data->attributes->len) {
3
Loop condition is false. Execution continues on line 1499
1478 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->attributes, 0);
1479 xml_ns_t *element = (xml_ns_t *)wmem_map_lookup(elements, nl->name);
1480
1481 if (element) {
1482 for (GList* current_attribute = nl->list; current_attribute != NULL((void*)0); current_attribute = current_attribute->next) {
1483 char *name = (char *)current_attribute->data;
1484 int *id_p = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int)));
1485
1486 *id_p = 0;
1487 wmem_map_insert(element->attributes, name, id_p);
1488 }
1489 }
1490 else {
1491 g_string_append_printf(errors, "element %s is not defined\n", nl->name);
1492 }
1493
1494 g_list_free(nl->list);
1495 g_free(nl);
1496 }
1497
1498 /* if a proto_root is defined in the dtd we'll use that as root */
1499 if ( dtd_data->proto_root ) {
4
Assuming field 'proto_root' is null
5
Taking false branch
1500 root_name = dtd_data->proto_root;
1501 }
1502
1503 /*
1504 * if a proto name was given in the dtd the dtd will be used as a protocol
1505 * or else the dtd will be loaded as a branch of the xml namespace
1506 */
1507 if( ! dtd_data->proto_name ) {
6
Assuming field 'proto_name' is non-null
7
Taking false branch
1508 hfs = hf_arr;
1509 etts = ett_arr;
1510 } else {
1511 /*
1512 * if we were given a proto_name the namespace will be registered
1513 * as an independent protocol with its own hf and ett arrays.
1514 */
1515 hfs = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
1516 etts = g_array_new(false0, false0, sizeof(int *));
1517 }
1518
1519 /* the root element of the dtd's namespace */
1520 root_element = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t))
)
;
1521 root_element->name = wmem_strdup(wmem_epan_scope(), root_name);
1522 root_element->fqn = dtd_data->proto_name
7.1
Field 'proto_name' is non-null
? dtd_data->proto_name : root_element->name;
8
'?' condition is true
1523 root_element->hf_tag = 0;
1524 root_element->hf_cdata = 0;
1525 root_element->ett = 0;
1526 root_element->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1527 root_element->element_names = element_names;
1528
1529 /*
1530 * we can either create a namespace as a flat namespace
1531 * in which all the elements are at the root level
1532 * or we can create a recursive namespace
1533 */
1534 if (dtd_data->recursion) {
9
Assuming field 'recursion' is true
10
Taking true branch
1535 xml_ns_t *orig_root;
1536 GQueue* hier = g_queue_new(); /* Acts as a stack with the names to avoid recurring infinitely */
1537 if (!dtd_data->proto_name
10.1
Field 'proto_name' is non-null
)
11
Taking false branch
1538 g_queue_push_head(hier, "xml");
1539
1540 make_xml_hier(root_name, root_element, elements, hier, errors, hfs, etts, dtd_data->proto_name);
12
Passing null pointer value via 1st parameter 'elem_name'
13
Calling 'make_xml_hier'
1541
1542 wmem_map_insert(root_element->elements, (void *)root_element->name, root_element);
1543
1544 orig_root = (xml_ns_t *)wmem_map_lookup(elements, root_name);
1545
1546 /* if the root element was defined copy its attrlist to the child */
1547 if(orig_root) {
1548 struct _attr_reg_data d;
1549
1550 d.basename = dtd_data->proto_name;
1551 d.hf = hfs;
1552
1553 root_element->attributes = copy_attributes_hash(orig_root->attributes);
1554 wmem_map_foreach(root_element->attributes, add_xml_attribute_names, &d);
1555 } else {
1556 root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1557 }
1558
1559 /* we then create all the sub hierarchies to catch the recurred cases */
1560 g_queue_push_head(hier, root_name);
1561
1562 while (root_element->element_names != NULL((void*)0))
1563 {
1564 curr_name = (char*)root_element->element_names->data;
1565 root_element->element_names = g_list_remove(root_element->element_names, curr_name);
1566
1567 if (!wmem_map_lookup(root_element->elements, curr_name)) {
1568 xml_ns_t* fresh = make_xml_hier(curr_name, root_element, elements, hier, errors,
1569 hfs, etts, dtd_data->proto_name);
1570 wmem_map_insert(root_element->elements, (void*)fresh->name, fresh);
1571 }
1572 }
1573
1574 /* No longer need the hierarchy check */
1575 g_queue_free(hier);
1576
1577 } else {
1578 /* a flat namespace */
1579 xml_element_iter_data iterdata = {
1580 .root_element = root_element,
1581 .hfs = hfs,
1582 .etts = etts
1583 };
1584
1585 root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1586 wmem_map_foreach(elements, add_xml_flat_element_names, &iterdata);
1587 }
1588
1589 /*
1590 * if we were given a proto_name the namespace will be registered
1591 * as an independent protocol.
1592 * XXX - Should these be PINOs? The standard xml_handle is called,
1593 * which means that enabling and disabling the protocols has no
1594 * effect.
1595 */
1596 if ( dtd_data->proto_name ) {
1597 int *ett_p;
1598 char *full_name, *short_name;
1599
1600 if (dtd_data->description) {
1601 full_name = dtd_data->description;
1602 } else {
1603 full_name = root_name;
1604 }
1605 short_name = dtd_data->proto_name;
1606
1607 ett_p = &root_element->ett;
1608 g_array_append_val(etts, ett_p)g_array_append_vals (etts, &(ett_p), 1);
1609
1610 /* Ensure the cdata field (a FT_STRING) has a different abbrev
1611 * than the FT_PROTOCOL. (XXX - Maybe we should do this for all
1612 * the cdata fields?) */
1613 char *cdata_name = wmem_strdup_printf(wmem_epan_scope(), "%s.cdata", root_element->fqn);
1614 add_xml_field(hfs, &root_element->hf_cdata, root_element->name, cdata_name);
1615
1616 root_element->hf_tag = proto_register_protocol(full_name, short_name, short_name);
1617 proto_register_field_array(root_element->hf_tag, (hf_register_info*)wmem_array_get_raw(hfs), wmem_array_get_count(hfs));
1618 proto_register_subtree_array((int **)etts->data, etts->len);
1619
1620 if (dtd_data->media_type) {
1621 wmem_map_insert(media_types, dtd_data->media_type, root_element);
1622 }
1623
1624 g_array_free(etts, true1);
1625 }
1626
1627 wmem_map_insert(xml_ns.elements, root_element->name, root_element);
1628 wmem_map_foreach(elements, free_elements, NULL((void*)0));
1629 free_elements(NULL((void*)0), root_element, NULL((void*)0));
1630
1631 destroy_dtd_data(dtd_data);
1632}
1633
1634static dtd_build_data_t* g_build_data;
1635
1636static void dtd_pi_cb(void* ctx _U___attribute__((unused)), const xmlChar* target, const xmlChar* data)
1637{
1638 if (strcmp(target, "wireshark-protocol") == 0) {
1639
1640 xmlDocPtr fake_doc;
1641 char* fake_element;
1642
1643 //libxml2 doesn't parse this content into attributes, so create a dummy element
1644 //to parse out the Wireshark data
1645 fake_element = wmem_strdup_printf(NULL((void*)0), "<fake_root %s />", data);
1646 fake_doc = xmlReadMemory(fake_element, (int)strlen(fake_element), NULL((void*)0), NULL((void*)0), 0);
1647 if (fake_doc != NULL((void*)0))
1648 {
1649 if (fake_doc->children != NULL((void*)0))
1650 {
1651 xmlChar* value;
1652 for (xmlAttrPtr attr = fake_doc->children->properties; attr != NULL((void*)0); attr = attr->next)
1653 {
1654 if (xmlStrcmp(attr->name, (const xmlChar*)"proto_name") == 0) {
1655 value = xmlNodeListGetString(fake_doc, attr->children, 1);
1656 char* lower_proto = g_ascii_strdown(value, -1);
1657 g_build_data->proto_name = wmem_strdup(wmem_epan_scope(), lower_proto);
1658 g_free(lower_proto);
1659 xmlFree(value);
1660 }
1661 if (xmlStrcmp(attr->name, (const xmlChar*)"root") == 0) {
1662 value = xmlNodeListGetString(fake_doc, attr->children, 1);
1663 g_build_data->proto_root = g_ascii_strdown(value, -1);
1664 xmlFree(value);
1665 }
1666 else if (xmlStrcmp(attr->name, (const xmlChar*)"media") == 0) {
1667 value = xmlNodeListGetString(fake_doc, attr->children, 1);
1668 g_build_data->media_type = wmem_strdup(wmem_epan_scope(), value);
1669 xmlFree(value);
1670 }
1671 else if (xmlStrcmp(attr->name, (const xmlChar*)"description") == 0) {
1672 value = xmlNodeListGetString(fake_doc, attr->children, 1);
1673 g_build_data->description = wmem_strdup(wmem_epan_scope(), value);
1674 xmlFree(value);
1675 }
1676 else if (xmlStrcmp(attr->name, (const xmlChar*)"hierarchy") == 0) {
1677 value = xmlNodeListGetString(fake_doc, attr->children, 1);
1678 g_build_data->recursion = (g_ascii_strcasecmp(value, "yes") == 0) ? true1 : false0;
1679 xmlFree(value);
1680 }
1681 }
1682 }
1683
1684 //TODO: Error checking for required attributes?
1685 }
1686 xmlFreeDoc(fake_doc);
1687 wmem_free(NULL((void*)0), fake_element);
1688 }
1689}
1690
1691static void dtd_internalSubset_cb(void* ctx _U___attribute__((unused)), const xmlChar* name, const xmlChar* publicId _U___attribute__((unused)), const xmlChar* systemId _U___attribute__((unused)))
1692{
1693 wmem_free(wmem_epan_scope(), g_build_data->proto_root);
1694 g_build_data->proto_root = wmem_ascii_strdown(wmem_epan_scope(), (const char*)name, -1);
1695 if (!g_build_data->proto_name) {
1696 g_build_data->proto_name = g_build_data->proto_root;
1697 }
1698}
1699
1700// NOLINTNEXTLINE(misc-no-recursion)
1701static GList* dtd_elementDecl_add_list(GList* list, xmlElementContent* content)
1702{
1703 if (content != NULL((void*)0)) {
1704 if (content->c1 != NULL((void*)0)) {
1705 if (content->c1->name != NULL((void*)0)) {
1706 list = g_list_prepend(list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->c1->name, -1));
1707 }
1708 list = dtd_elementDecl_add_list(list, content->c1);
1709 }
1710 if (content->c2 != NULL((void*)0)) {
1711 if (content->c2->name != NULL((void*)0)) {
1712 list = g_list_prepend(list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->c2->name, -1));
1713 }
1714 list = dtd_elementDecl_add_list(list, content->c2);
1715 }
1716 }
1717
1718 return list;
1719}
1720
1721static void dtd_elementDecl_cb(void* ctx _U___attribute__((unused)), const xmlChar* name, int type _U___attribute__((unused)), xmlElementContent* content _U___attribute__((unused)))
1722{
1723 dtd_named_list_t* new_element = g_new0(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc0_n ((1), sizeof (dtd_named_list_t
)))
;
1724
1725 new_element->name = wmem_ascii_strdown(wmem_epan_scope(), (const char*)name, -1);
1726 new_element->list = NULL((void*)0);
1727
1728 /* we will use the first element found as root in case no other one was given. */
1729 if (!g_build_data->proto_root) {
1730 g_build_data->proto_root = new_element->name;
1731 }
1732
1733 //Make list
1734 if ((content != NULL((void*)0)) && (content->name != NULL((void*)0))) {
1735 new_element->list = g_list_prepend(new_element->list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->name, -1));
1736 }
1737 new_element->list = dtd_elementDecl_add_list(new_element->list, content);
1738
1739 g_ptr_array_add(g_build_data->elements, new_element);
1740}
1741
1742static void dtd_attributeDecl_cb(void* ctx _U___attribute__((unused)), const xmlChar* elem, const xmlChar* fullname, int type _U___attribute__((unused)), int def _U___attribute__((unused)),
1743 const xmlChar* defaultValue _U___attribute__((unused)), xmlEnumerationPtr tree)
1744{
1745 /* See https://www.w3.org/TR/xml/#attdecls
1746 * elem is the name of the parent Element, which may not exist:
1747 * "At user option, an XML processor MAY issue a warning if attributes
1748 * are declared for an element type not itself declared, but this is
1749 * not an error... When more than one AttlistDecl is provided for a given
1750 * element type, the contents of all those provided are merged."
1751 */
1752 dtd_named_list_t* attribute;
1753 bool_Bool found = false0;
1754 char* elem_down = g_ascii_strdown((const char*)elem, -1);
1755 for (unsigned i = g_build_data->attributes->len; i > 0; i--) {
1756 attribute = g_build_data->attributes->pdata[i - 1];
1757 if (strcmp(attribute->name, elem_down) == 0) {
1758 found = true1;
1759 break;
1760 }
1761 }
1762 if (!found) {
1763 attribute = g_new0(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc0_n ((1), sizeof (dtd_named_list_t
)))
;
1764 attribute->name = wmem_strdup(wmem_epan_scope(), elem_down);
1765 attribute->list = NULL((void*)0);
1766 g_ptr_array_add(g_build_data->attributes, attribute);
1767 }
1768 g_free(elem_down);
1769
1770 attribute->list = g_list_prepend(attribute->list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)fullname, -1));
1771 // We don't use this. We're allowed to free it, as the default SAX2 handler
1772 // here does and it's not used after this by the main parser.
1773 if (tree != NULL((void*)0))
1774 xmlFreeEnumeration(tree);
1775}
1776
1777static void dtd_error_cb(void* ctx _U___attribute__((unused)), const char* msg, ...)
1778{
1779 char buf[40];
1780 va_list args;
1781 va_start(args, msg)__builtin_va_start(args, msg);
1782 va_list args2;
1783 va_copy(args2, args)__builtin_va_copy(args2, args);
1784 vsnprintf(buf, sizeof(buf), msg, args);
1785 va_end(args)__builtin_va_end(args);
1786 /* We allow (see dc.dtd and itunes.dtd) "DTDs" that have a DOCTYPE
1787 * declaration. That makes them not valid external DTDs. They also
1788 * aren't valid XML documents with internal DTDs (which is how libxml2
1789 * tried to parse them) because they have no tags.
1790 * Parsing them as a DTD gives the "Content error in the external subset"
1791 * error; parsing them as a document gives the "Start tag expected"
1792 * error.
1793 *
1794 * So we ignore those errors and report others. If those are the only
1795 * errors, then we'll call it valid and fully parse it later with the
1796 * lex-based parser.
1797 *
1798 * XXX - Can we achieve the same result while forcing the DTDs to
1799 * be normal standalone external DTDs? Make people use the "root"
1800 * attribute if necessary? Need to verify that it would parse the same,
1801 * but it would simplify the code. We could also insert an empty tag
1802 * or something to make libxml2 happy, but the flex-based parser complains
1803 * in that case.
1804 */
1805 if (!g_str_has_prefix(buf, "Start tag expected")(__builtin_constant_p ("Start tag expected")? __extension__ (
{ const char * const __str = (buf); const char * const __prefix
= ("Start tag expected"); gboolean __result = (0); if (__str
== ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (buf, "Start tag expected"
) )
&&
1806 !g_str_has_prefix(buf, "Content error in the external subset")(__builtin_constant_p ("Content error in the external subset"
)? __extension__ ({ const char * const __str = (buf); const char
* const __prefix = ("Content error in the external subset");
gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (buf, "Content error in the external subset"
) )
) {
1807 g_string_append_vprintf(g_build_data->error, msg, args2);
1808 }
1809 va_end(args2)__builtin_va_end(args2);
1810}
1811
1812static dtd_build_data_t*
1813dtd_parse_libxml2(char* filename)
1814{
1815 xmlSAXHandler saxHandler;
1816 xmlSAXVersion(&saxHandler, 2);
1817 saxHandler.processingInstruction = dtd_pi_cb;
1818 saxHandler.internalSubset = dtd_internalSubset_cb;
1819 saxHandler.elementDecl = dtd_elementDecl_cb;
1820 saxHandler.attributeDecl = dtd_attributeDecl_cb;
1821 saxHandler.error = dtd_error_cb;
1822
1823 xmlParserInputBuffer* buffer;
1824
1825 xmlDtdPtr dtd;
1826 xmlDocPtr doc;
1827 xmlParserCtxt* ctxt;
1828 bool_Bool external_dtd = false0;
1829
1830 // Initialize the build data
1831 g_build_data = g_new0(dtd_build_data_t, 1)((dtd_build_data_t *) g_malloc0_n ((1), sizeof (dtd_build_data_t
)))
;
1832 g_build_data->elements = g_ptr_array_new();
1833 g_build_data->attributes = g_ptr_array_new();
1834 g_build_data->error = g_string_new("");
1835
1836 buffer = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_UTF8);
1837
1838 // xmlCtxtParseDtd is introduced in 2.14.0; before that
1839 // there's no way to parse a DTD using a xmlParserCtxt
1840 // or userData, just with a saxHandler directly. That
1841 // also means that instead of using a dtd_build_data_t
1842 // as user data, we just use a global.
1843 dtd = xmlIOParseDTD(&saxHandler, buffer, XML_CHAR_ENCODING_UTF8);
1844 /* Is it a regular standalone external DTD? */
1845 if (dtd) {
1846 xmlFreeDtd(dtd);
1847 external_dtd = true1;
1848 }
1849 else {
1850 /* OK, it is a XML document with an internal DTD but
1851 * possibly lacking any tags? */
1852#if LIBXML_VERSION20914 >= 21100
1853 ctxt = xmlNewSAXParserCtxt(&saxHandler, NULL((void*)0) /*g_build_data*/);
1854#else
1855 ctxt = xmlNewParserCtxt();
1856 if (ctxt->sax != NULL((void*)0)) {
1857 xmlFree(ctxt->sax);
1858 }
1859 ctxt->sax = &saxHandler;
1860 //ctxt->userData = g_build_data;
1861#endif
1862 // We don't actually want the document here, so
1863 // we could use xmlParseDocument, but we need
1864 // to set the input (use xmlCreateURLParserCtxt
1865 // from parserInternals.h?)
1866 doc = xmlCtxtReadFile(ctxt, filename, NULL((void*)0), 0);
1867 // We don't need XML_PARSE_DTDLOAD because we don't
1868 // want *external* DTDs or entities. We might need
1869 // XML_PARSE_NOENT eventually though.
1870 xmlFreeDoc(doc);
1871#if LIBXML_VERSION20914 < 21100
1872 // sax not copied here, so remove it so it doesn't get
1873 // freed (it was declared on the stack).
1874 ctxt->sax = NULL((void*)0);
1875#endif
1876 xmlFreeParserCtxt(ctxt);
1877 }
1878
1879 //Add a root node for the doctype itself
1880 if (!external_dtd && (g_build_data->elements->len > 0)) {
1881
1882 dtd_named_list_t* new_element = g_new(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc_n ((1), sizeof (dtd_named_list_t
)))
;
1883 new_element->name = g_build_data->proto_name;
1884 new_element->list = NULL((void*)0);
1885 for (unsigned i = 0; i < g_build_data->elements->len; i++) {
1886 dtd_named_list_t* el = (dtd_named_list_t*)g_ptr_array_index(g_build_data->elements, i)((g_build_data->elements)->pdata)[i];
1887 new_element->list = g_list_prepend(new_element->list, el->name);
1888 }
1889
1890 g_ptr_array_add(g_build_data->elements, new_element);
1891 }
1892
1893 // xmlIOParseDTD: "input will be freed by the function"
1894 // (even on error), so no need for
1895 // xmlFreeParserInputBuffer(buffer);
1896
1897 return g_build_data;
1898}
1899
1900# define DIRECTORY_TGDir GDir
1901# define FILE_Tchar char
1902# define OPENDIR_OP(name)g_dir_open(name, 0, dummy) g_dir_open(name, 0, dummy)
1903# define DIRGETNEXT_OP(dir)g_dir_read_name(dir) g_dir_read_name(dir)
1904# define GETFNAME_OP(file)(file); (file);
1905# define CLOSEDIR_OP(dir)g_dir_close(dir) g_dir_close(dir)
1906
1907static void init_xml_names(void)
1908{
1909 unsigned i;
1910 DIRECTORY_TGDir *dir;
1911 const FILE_Tchar *file;
1912 const char *filename;
1913 char *dirname;
1914
1915 GError **dummy = wmem_new(wmem_epan_scope(), GError *)((GError **)wmem_alloc((wmem_epan_scope()), sizeof(GError *))
)
;
1916 *dummy = NULL((void*)0);
1917
1918 xmpli_names = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1919 media_types = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1920
1921 for(i=0;i<array_length(default_media_types)(sizeof (default_media_types) / sizeof (default_media_types)[
0])
;i++) {
1922 wmem_map_insert(media_types, (void *)default_media_types[i], &xml_ns);
1923 }
1924
1925 unknown_ns.elements = xml_ns.elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1926 unknown_ns.attributes = xml_ns.attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
1927
1928 xml_new_namespace(xmpli_names, "xml", "version", "encoding", "standalone", NULL((void*)0));
1929
1930 dirname = get_persconffile_path("dtds", false0);
1931
1932 if (test_for_directory(dirname) != EISDIR21) {
1933 /* Although dir isn't a directory it may still use memory */
1934 g_free(dirname);
1935 dirname = get_datafile_path("dtds");
1936 }
1937
1938 if (test_for_directory(dirname) == EISDIR21) {
1939 if ((dir = OPENDIR_OP(dirname)g_dir_open(dirname, 0, dummy)) != NULL((void*)0)) {
1940 GString *errors = g_string_new("");
1941
1942 while ((file = DIRGETNEXT_OP(dir)g_dir_read_name(dir)) != NULL((void*)0)) {
1943 unsigned namelen;
1944 filename = GETFNAME_OP(file)(file);;
1945
1946 namelen = (int)strlen(filename);
1947 if ( namelen > 4 && ( g_ascii_strcasecmp(filename+(namelen-4), ".dtd") == 0 ) ) {
1948 dtd_build_data_t* dtd_data;
1949
1950 char* full_file = wmem_strdup_printf(NULL((void*)0), "%s%c%s", dirname, G_DIR_SEPARATOR'/', filename);
1951 dtd_data = dtd_parse_libxml2(full_file);
1952
1953 if (dtd_data->error->len) {
1954 report_failure("Dtd Parser in file %s: %s", full_file, dtd_data->error->str);
1955 destroy_dtd_data(dtd_data);
1956 wmem_free(NULL((void*)0), full_file);
1957 continue;
1958 }
1959
1960 register_dtd(dtd_data, errors);
1961
1962 if (errors->len) {
1963 report_failure("Dtd Registration in file: %s: %s", full_file, errors->str);
1964 wmem_free(NULL((void*)0), full_file);
1965 continue;
1966 }
1967
1968 wmem_free(NULL((void*)0), full_file);
1969 }
1970 }
1971 g_string_free(errors, true)(__builtin_constant_p (1) ? ((1) ? (g_string_free) ((errors),
(1)) : g_string_free_and_steal (errors)) : (g_string_free) (
(errors), (1)))
;
1972
1973 CLOSEDIR_OP(dir)g_dir_close(dir);
1974 }
1975 }
1976
1977 g_free(dirname);
1978
1979 wmem_map_foreach(xmpli_names, add_xmlpi_namespace, (void *)"xml.xmlpi");
1980
1981 wmem_free(wmem_epan_scope(), dummy);
1982}
1983
1984static void
1985xml_shutdown_protocol(void) {
1986 g_regex_unref(encoding_pattern);
1987}
1988
1989void
1990proto_register_xml(void)
1991{
1992 static int *ett_base[] = {
1993 &unknown_ns.ett,
1994 &xml_ns.ett,
1995 &ett_dtd,
1996 &ett_xmpli
1997 };
1998
1999 static hf_register_info hf_base[] = {
2000 { &hf_xmlpi,
2001 {"XMLPI", "xml.xmlpi",
2002 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2003 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2004 },
2005 { &hf_cdatasection,
2006 {"CDATASection", "xml.cdatasection",
2007 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2008 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2009 },
2010 { &hf_comment,
2011 {"Comment", "xml.comment",
2012 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2013 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2014 },
2015 { &hf_unknowwn_attrib,
2016 {"Attribute", "xml.attribute",
2017 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2018 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2019 },
2020 { &hf_doctype,
2021 {"Doctype", "xml.doctype",
2022 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2023 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2024 },
2025 { &hf_dtd_tag,
2026 {"DTD Tag", "xml.dtdtag",
2027 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2028 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2029 },
2030 { &unknown_ns.hf_cdata,
2031 {"CDATA", "xml.cdata",
2032 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0),
2033 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2034 },
2035 { &unknown_ns.hf_tag,
2036 {"Tag", "xml.tag",
2037 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2038 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2039 },
2040 { &xml_ns.hf_cdata,
2041 {"Unknown", "xml.unknown",
2042 FT_STRING, BASE_NONE, NULL((void*)0), 0,
2043 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2044 }
2045 };
2046
2047 static ei_register_info ei[] = {
2048 { &ei_xml_closing_unopened_tag, { "xml.closing_unopened_tag", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Closing an unopened tag", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
2049 { &ei_xml_closing_unopened_xmpli_tag, { "xml.closing_unopened_xmpli_tag", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Closing an unopened xmpli tag", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
2050 { &ei_xml_unrecognized_text, { "xml.unrecognized_text", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Unrecognized text", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
2051 };
2052
2053 module_t *xml_module;
2054 expert_module_t* expert_xml;
2055
2056 hf_arr = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
2057 ett_arr = g_array_new(false0, false0, sizeof(int *));
2058
2059 wmem_array_append(hf_arr, hf_base, array_length(hf_base)(sizeof (hf_base) / sizeof (hf_base)[0]));
2060 g_array_append_vals(ett_arr, ett_base, array_length(ett_base)(sizeof (ett_base) / sizeof (ett_base)[0]));
2061
2062 init_xml_names();
2063
2064 xml_ns.hf_tag = proto_register_protocol("eXtensible Markup Language", "XML", xml_ns.name);
2065
2066 proto_register_field_array(xml_ns.hf_tag, (hf_register_info*)wmem_array_get_raw(hf_arr), wmem_array_get_count(hf_arr));
2067 proto_register_subtree_array((int **)ett_arr->data, ett_arr->len);
2068 expert_xml = expert_register_protocol(xml_ns.hf_tag);
2069 expert_register_field_array(expert_xml, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
2070
2071 xml_module = prefs_register_protocol(xml_ns.hf_tag, NULL((void*)0));
2072 prefs_register_obsolete_preference(xml_module, "heuristic");
2073 prefs_register_obsolete_preference(xml_module, "heuristic_tcp");
2074 prefs_register_obsolete_preference(xml_module, "heuristic_udp");
2075 /* XXX - UCS-2, or UTF-16? */
2076 prefs_register_bool_preference(xml_module, "heuristic_unicode", "Use Unicode in heuristics",
2077 "Try to recognize XML encoded in Unicode (UCS-2BE)",
2078 &pref_heuristic_unicode);
2079
2080 prefs_register_enum_preference(xml_module, "default_encoding", "Default character encoding",
2081 "Use this charset if the 'encoding' attribute of XML declaration is missing."
2082 "Unsupported encoding will be replaced by the default UTF-8.",
2083 &pref_default_encoding, ws_supported_mibenum_vals_character_sets_ev_array, false0);
2084
2085 // The longest encoding at https://www.iana.org/assignments/character-sets/character-sets.xml
2086 // is 45 characters (Extended_UNIX_Code_Packed_Format_for_Japanese).
2087 encoding_pattern = g_regex_new("^\\s*<[?]xml\\s+version\\s*=\\s*[\"']\\s*(?U:.+)\\s*[\"']\\s+encoding\\s*=\\s*[\"']\\s*((?U).{1,50})\\s*[\"']", G_REGEX_CASELESS, 0, 0);
2088 register_shutdown_routine(&xml_shutdown_protocol);
2089
2090 xml_handle = register_dissector("xml", dissect_xml, xml_ns.hf_tag);
2091
2092 init_xml_parser();
2093}
2094
2095static void
2096add_dissector_media(void *k, void *v _U___attribute__((unused)), void *p _U___attribute__((unused)))
2097{
2098 dissector_add_string("media_type", (char *)k, xml_handle);
2099}
2100
2101void
2102proto_reg_handoff_xml(void)
2103{
2104 wmem_map_foreach(media_types, add_dissector_media, NULL((void*)0));
2105 dissector_add_string("media_type.suffix", "xml", xml_handle); /* RFC 7303 9.6 */
2106 dissector_add_uint_range_with_preference("tcp.port", "", xml_handle);
2107 dissector_add_uint_range_with_preference("udp.port", XML_UDP_PORT_RANGE"3702", xml_handle);
2108
2109 gssapi_handle = find_dissector_add_dependency("gssapi", xml_ns.hf_tag);
2110
2111 heur_dissector_add("http", dissect_xml_heur, "XML in HTTP", "xml_http", xml_ns.hf_tag, HEURISTIC_DISABLE);
2112 heur_dissector_add("sip", dissect_xml_heur, "XML in SIP", "xml_sip", xml_ns.hf_tag, HEURISTIC_DISABLE);
2113 heur_dissector_add("media", dissect_xml_heur, "XML in media", "xml_media", xml_ns.hf_tag, HEURISTIC_DISABLE);
2114 heur_dissector_add("tcp", dissect_xml_heur, "XML over TCP", "xml_tcp", xml_ns.hf_tag, HEURISTIC_DISABLE);
2115 heur_dissector_add("udp", dissect_xml_heur, "XML over UDP", "xml_udp", xml_ns.hf_tag, HEURISTIC_DISABLE);
2116
2117 heur_dissector_add("wtap_file", dissect_xml_heur, "XML file", "xml_wtap", xml_ns.hf_tag, HEURISTIC_ENABLE);
2118
2119 dissector_add_uint("acdr.tls_application", TLS_APP_XML, xml_handle);
2120}
2121
2122/*
2123 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2124 *
2125 * Local variables:
2126 * c-basic-offset: 4
2127 * tab-width: 8
2128 * indent-tabs-mode: nil
2129 * End:
2130 *
2131 * vi: set shiftwidth=4 tabstop=8 expandtab:
2132 * :indentSize=4:tabSize=8:noTabs=true:
2133 */