### Bug Summary

File: | builds/wireshark/wireshark/epan/dfilter/syntax-tree.c
Warning: | line 103, column 14 Value stored to 's' during its initialization is never read

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
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 syntax-tree.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-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D CARES_NO_DEPRECATED -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 -I /builds/wireshark/wireshark/epan/dfilter -I /builds/wireshark/wireshark/build/epan/dfilter -I /builds/wireshark/wireshark/epan -I /builds/wireshark/wireshark/tools/lemon -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../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-nonliteral -std=gnu17 -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 -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-07-02-100350-3577-1 -x c /builds/wireshark/wireshark/epan/dfilter/syntax-tree.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

1 | /*
2 | * Wireshark - Network traffic analyzer
3 | * By Gerald Combs <gerald@wireshark.org>
4 | * Copyright 2001 Gerald Combs
5 | *
6 | * SPDX-License-Identifier: GPL-2.0-or-later
7 | */
8 |
9 | #include "config.h"
10 | #define WS_LOG_DOMAIN"DFilter" LOG_DOMAIN_DFILTER"DFilter"
11 |
12 | #include "syntax-tree.h"
13 | #include <wsutil/wmem/wmem.h>
14 | #include <wsutil/str_util.h>
15 | #include <wsutil/glib-compat.h>
16 | #include "sttype-op.h"
17 | #include "sttype-function.h"
18 | #include "dfilter-int.h"
19 |
20 | /* Keep track of sttype_t's via their sttype_id_t number */
21 | static sttype_t* type_list[STTYPE_NUM_TYPES];
22 |
23 |
24 | void
25 | sttype_init(void)
26 | {
27 | sttype_register_field();
28 | sttype_register_function();
29 | sttype_register_number();
30 | sttype_register_pointer();
31 | sttype_register_set();
32 | sttype_register_slice();
33 | sttype_register_string();
34 | sttype_register_opers();
35 | }
36 |
37 | void
38 | sttype_cleanup(void)
39 | {
40 | /* nothing to do */
41 | }
42 |
43 |
44 | void
45 | sttype_register(sttype_t *type)
46 | {
47 | sttype_id_t type_id;
48 |
49 | type_id = type->id;
50 |
51 | /* Check input */
52 | ws_assert(type_id < STTYPE_NUM_TYPES)do { if ((1) && !(type_id < STTYPE_NUM_TYPES)) ws_log_fatal_full ("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 52 , __func__, "assertion failed: %s", "type_id < STTYPE_NUM_TYPES" ); } while (0);
53 |
54 | /* Don't re-register. */
55 | ws_assert(type_list[type_id] == NULL)do { if ((1) && !(type_list[type_id] == ((void*)0))) ws_log_fatal_full ("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 55 , __func__, "assertion failed: %s", "type_list[type_id] == ((void*)0)" ); } while (0);
56 |
57 | type_list[type_id] = type;
58 | }
59 |
60 | static sttype_t*
61 | sttype_lookup(sttype_id_t type_id)
62 | {
63 | sttype_t *result;
64 |
65 | /* Check input */
66 | ws_assert(type_id < STTYPE_NUM_TYPES)do { if ((1) && !(type_id < STTYPE_NUM_TYPES)) ws_log_fatal_full ("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 66 , __func__, "assertion failed: %s", "type_id < STTYPE_NUM_TYPES" ); } while (0);
67 |
68 | result = type_list[type_id];
69 |
70 | /* Check output. */
71 | ws_assert(result != NULL)do { if ((1) && !(result != ((void*)0))) ws_log_fatal_full ("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 71 , __func__, "assertion failed: %s", "result != ((void*)0)"); } while (0);
72 |
73 | return result;
74 | }
75 |
76 | const char *
77 | sttype_name(const sttype_id_t type)
78 | {
79 | switch (type) {
80 | case STTYPE_UNINITIALIZED: return "UNINITIALIZED";
81 | case STTYPE_TEST: return "TEST";
82 | case STTYPE_LITERAL: return "LITERAL";
83 | case STTYPE_UNPARSED: return "UNPARSED";
84 | case STTYPE_REFERENCE: return "REFERENCE";
85 | case STTYPE_STRING: return "STRING";
86 | case STTYPE_CHARCONST: return "CHARCONST";
87 | case STTYPE_NUMBER: return "NUMBER";
88 | case STTYPE_FIELD: return "FIELD";
89 | case STTYPE_FVALUE: return "FVALUE";
90 | case STTYPE_SLICE: return "SLICE";
91 | case STTYPE_FUNCTION: return "FUNCTION";
92 | case STTYPE_SET: return "SET";
93 | case STTYPE_PCRE: return "PCRE";
94 | case STTYPE_ARITHMETIC: return "ARITHMETIC";
95 | case STTYPE_NUM_TYPES: return "NUM_TYPES";
96 | }
97 | return "(unknown sttype)";
98 | }
99 |
100 | const char *
101 | stnode_op_name(const stnode_op_t op)
102 | {
103 | const char *s = "(null)";
| Value stored to 's' during its initialization is never read
104 |
105 | switch(op) {
106 | case STNODE_OP_NOT:
107 | s = "TEST_NOT";
108 | break;
109 | case STNODE_OP_AND:
110 | s = "TEST_AND";
111 | break;
112 | case STNODE_OP_OR:
113 | s = "TEST_OR";
114 | break;
115 | case STNODE_OP_ALL_EQ:
116 | s = "TEST_ALL_EQ";
117 | break;
118 | case STNODE_OP_ANY_EQ:
119 | s = "TEST_ANY_EQ";
120 | break;
121 | case STNODE_OP_ALL_NE:
122 | s = "TEST_ALL_NE";
123 | break;
124 | case STNODE_OP_ANY_NE:
125 | s = "TEST_ANY_NE";
126 | break;
127 | case STNODE_OP_GT:
128 | s = "TEST_GT";
129 | break;
130 | case STNODE_OP_GE:
131 | s = "TEST_GE";
132 | break;
133 | case STNODE_OP_LT:
134 | s = "TEST_LT";
135 | break;
136 | case STNODE_OP_LE:
137 | s = "TEST_LE";
138 | break;
139 | case STNODE_OP_BITWISE_AND:
140 | s = "OP_BITWISE_AND";
141 | break;
142 | case STNODE_OP_UNARY_MINUS:
143 | s = "OP_UNARY_MINUS";
144 | break;
145 | case STNODE_OP_ADD:
146 | s = "OP_ADD";
147 | break;
148 | case STNODE_OP_SUBTRACT:
149 | s = "OP_SUBTRACT";
150 | break;
151 | case STNODE_OP_MULTIPLY:
152 | s = "OP_MULTIPLY";
153 | break;
154 | case STNODE_OP_DIVIDE:
155 | s = "OP_DIVIDE";
156 | break;
157 | case STNODE_OP_MODULO:
158 | s = "OP_MODULO";
159 | break;
160 | case STNODE_OP_CONTAINS:
161 | s = "TEST_CONTAINS";
162 | break;
163 | case STNODE_OP_MATCHES:
164 | s = "TEST_MATCHES";
165 | break;
166 | case STNODE_OP_IN:
167 | s = "TEST_IN";
168 | break;
169 | case STNODE_OP_NOT_IN:
170 | s = "TEST_NOT_IN";
171 | break;
172 | case STNODE_OP_UNINITIALIZED:
173 | s = "(uninitialized)";
174 | break;
175 | }
176 |
177 | return s;
178 | }
179 |
180 | void
181 | stnode_clear(stnode_t *node)
182 | {
183 | if (node->type) {
184 | if (node->type->func_free && node->data) {
185 | node->type->func_free(node->data);
186 | }
187 | }
188 | else {
189 | ws_assert(!node->data)do { if ((1) && !(!node->data)) ws_log_fatal_full( "DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 189 , __func__, "assertion failed: %s", "!node->data"); } while (0);
190 | }
191 |
192 | node->type = NULL((void*)0);
193 | node->data = NULL((void*)0);
194 | g_free(node->repr_display)(__builtin_object_size ((node->repr_display), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_display, __builtin_object_size ((node->repr_display), 0)) : (g_free) (node->repr_display );
195 | node->repr_display = NULL((void*)0);
196 | g_free(node->repr_debug)(__builtin_object_size ((node->repr_debug), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_debug, __builtin_object_size ((node->repr_debug), 0)) : (g_free) (node->repr_debug);
197 | node->repr_debug = NULL((void*)0);
198 | g_free(node->repr_token)(__builtin_object_size ((node->repr_token), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_token, __builtin_object_size ((node->repr_token), 0)) : (g_free) (node->repr_token);
199 | node->repr_token = NULL((void*)0);
200 | node->location.col_start = -1;
201 | node->location.col_len = 0;
202 | node->flags = 0;
203 | }
204 |
205 | void
206 | stnode_init(stnode_t *node, sttype_id_t type_id, void *data, char *token, df_loc_t loc)
207 | {
208 | sttype_t *type;
209 |
210 | ws_assert(!node->type)do { if ((1) && !(!node->type)) ws_log_fatal_full( "DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 210 , __func__, "assertion failed: %s", "!node->type"); } while (0);
211 | ws_assert(!node->data)do { if ((1) && !(!node->data)) ws_log_fatal_full( "DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 211 , __func__, "assertion failed: %s", "!node->data"); } while (0);
212 | node->repr_display = NULL((void*)0);
213 | node->repr_debug = NULL((void*)0);
214 | node->repr_token = token;
215 | node->location = loc;
216 | node->flags = 0;
217 |
218 | if (type_id == STTYPE_UNINITIALIZED) {
219 | node->type = NULL((void*)0);
220 | node->data = NULL((void*)0);
221 | }
222 | else {
223 | /* Creating an initialized node with a NULL pointer is
224 | * allowed and needs to be safe. The parser relies on that. */
225 | type = sttype_lookup(type_id);
226 | ws_assert(type)do { if ((1) && !(type)) ws_log_fatal_full("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 226, __func__ , "assertion failed: %s", "type"); } while (0);
227 | node->type = type;
228 | if (type->func_new) {
229 | node->data = type->func_new(data);
230 | }
231 | else {
232 | node->data = data;
233 | }
234 | }
235 | }
236 |
237 | void
238 | stnode_replace(stnode_t *node, sttype_id_t type_id, void *data)
239 | {
240 | char *token = g_strdup(node->repr_token)g_strdup_inline (node->repr_token);
241 | df_loc_t loc = node->location;
242 | uint16_t flags = node->flags;
243 | stnode_clear(node);
244 | stnode_init(node, type_id, data, token, loc);
245 | node->flags = flags;
246 | }
247 |
248 | void
249 | stnode_mutate(stnode_t *node, sttype_id_t type_id)
250 | {
251 | //FIXME: Assert there all the same sttype
252 | node->type = sttype_lookup(type_id);
253 | ws_assert(node->type)do { if ((1) && !(node->type)) ws_log_fatal_full("DFilter" , LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 253, __func__ , "assertion failed: %s", "node->type"); } while (0);
254 | }
255 |
256 | stnode_t*
257 | stnode_new(sttype_id_t type_id, void *data, char *token, df_loc_t loc)
258 | {
259 | stnode_t *node = g_new0(stnode_t, 1)((stnode_t *) g_malloc0_n ((1), sizeof (stnode_t)));
260 | stnode_init(node, type_id, data, token, loc);
261 | return node;
262 | }
263 |
264 | stnode_t*
265 | stnode_new_empty(sttype_id_t type_id)
266 | {
267 | df_loc_t loc = {-1, 0};
268 | return stnode_new(type_id, NULL((void*)0), NULL((void*)0), loc);
269 | }
270 |
271 | stnode_t*
272 | stnode_dup(const stnode_t *node)
273 | {
274 | stnode_t *new;
275 |
276 | new = g_new(stnode_t, 1)((stnode_t *) g_malloc_n ((1), sizeof (stnode_t)));
277 | new->repr_display = NULL((void*)0);
278 | new->repr_debug = NULL((void*)0);
279 | new->repr_token = g_strdup(node->repr_token)g_strdup_inline (node->repr_token);
280 | new->location = node->location;
281 | new->flags = node->flags;
282 |
283 | new->type = node->type;
284 | if (node->type == NULL((void*)0))
285 | new->data = NULL((void*)0);
286 | else if (node->type->func_dup)
287 | new->data = node->type->func_dup(node->data);
288 | else
289 | new->data = node->data;
290 |
291 | return new;
292 | }
293 |
294 | void
295 | stnode_free(stnode_t *node)
296 | {
297 | stnode_clear(node);
298 | g_free(node)(__builtin_object_size ((node), 0) != ((size_t) - 1)) ? g_free_sized (node, __builtin_object_size ((node), 0)) : (g_free) (node);
299 | }
300 |
301 | const char*
302 | stnode_type_name(const stnode_t *node)
303 | {
304 | return sttype_name(node->type->id);
305 | }
306 |
307 | sttype_id_t
308 | stnode_type_id(const stnode_t *node)
309 | {
310 | if (node->type)
311 | return node->type->id;
312 | else
313 | return STTYPE_UNINITIALIZED;
314 | }
315 |
316 | void *
317 | stnode_data(stnode_t *node)
318 | {
319 | return node->data;
320 | }
321 |
322 | GString *
323 | stnode_string(stnode_t *node)
324 | {
325 | ws_assert(stnode_type_id(node) == STTYPE_STRING)do { if ((1) && !(stnode_type_id(node) == STTYPE_STRING )) ws_log_fatal_full("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c" , 325, __func__, "assertion failed: %s", "stnode_type_id(node) == STTYPE_STRING" ); } while (0);
326 | return stnode_data(node);
327 | }
328 |
329 | void *
330 | stnode_steal_data(stnode_t *node)
331 | {
332 | void *data = node->data;
333 | ws_assert(data)do { if ((1) && !(data)) ws_log_fatal_full("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 333, __func__ , "assertion failed: %s", "data"); } while (0);
334 | node->data = NULL((void*)0);
335 | return data;
336 | }
337 |
338 | const char *
339 | stnode_token(const stnode_t *node)
340 | {
341 | return node->repr_token;
342 | }
343 |
344 | df_loc_t
345 | stnode_location(const stnode_t *node)
346 | {
347 | return node->location;
348 | }
349 |
350 | void
351 | stnode_set_location(stnode_t *node, df_loc_t loc)
352 | {
353 | node->location = loc;
354 | }
355 |
356 | bool_Bool
357 | stnode_get_flags(stnode_t *node, uint16_t flags)
358 | {
359 | return node->flags & flags;
360 | }
361 |
362 | void
363 | stnode_set_flags(stnode_t *node, uint16_t flags)
364 | {
365 | node->flags |= flags;
366 | }
367 |
368 | /* Finds the first and last location from a set and creates
369 | * a new location from start of first (col_start) to end of
370 | * last (col_start + col_len). Sets the result to dst. */
371 | void
372 | stnode_merge_location(stnode_t *dst, stnode_t *n1, stnode_t *n2)
373 | {
374 | df_loc_t first, last;
375 | df_loc_t loc2;
376 |
377 | first = last = stnode_location(n1);
378 | loc2 = stnode_location(n2);
379 | if (loc2.col_start >= 0 && loc2.col_start > first.col_start)
380 | last = loc2;
381 | dst->location.col_start = first.col_start;
382 | dst->location.col_len = last.col_start - first.col_start + last.col_len;
383 | }
384 |
385 | #define IS_OPERATOR(node)(stnode_type_id(node) == STTYPE_TEST || stnode_type_id(node) == STTYPE_ARITHMETIC) \
386 | (stnode_type_id(node) == STTYPE_TEST || \
387 | stnode_type_id(node) == STTYPE_ARITHMETIC)
388 |
389 | static char *
390 | _node_tostr(stnode_t *node, bool_Bool pretty)
391 | {
392 | char *s, *repr;
393 |
394 | if (node->type->func_tostr == NULL((void*)0))
395 | s = g_strdup("FIXME")g_strdup_inline ("FIXME");
396 | else
397 | s = node->type->func_tostr(node->data, pretty);
398 |
399 | if (pretty)
400 | return s;
401 |
402 | if (IS_OPERATOR(node)(stnode_type_id(node) == STTYPE_TEST || stnode_type_id(node) == STTYPE_ARITHMETIC)) {
403 | repr = s;
404 | }
405 | else {
406 | repr = ws_strdup_printf("%s(%s)", stnode_type_name(node), s)wmem_strdup_printf(((void*)0), "%s(%s)", stnode_type_name(node ), s);
407 | g_free(s)(__builtin_object_size ((s), 0) != ((size_t) - 1)) ? g_free_sized (s, __builtin_object_size ((s), 0)) : (g_free) (s);
408 | }
409 |
410 | return repr;
411 | }
412 |
413 | const char *
414 | stnode_tostr(stnode_t *node, bool_Bool pretty)
415 | {
416 | if (pretty && IS_OPERATOR(node)(stnode_type_id(node) == STTYPE_TEST || stnode_type_id(node) == STTYPE_ARITHMETIC) && node->repr_token != NULL((void*)0)) {
417 | /* Some operators can have synonyms, like "or" and "||".
418 | * Show the user the same representation as he typed. */
419 | g_free(node->repr_display)(__builtin_object_size ((node->repr_display), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_display, __builtin_object_size ((node->repr_display), 0)) : (g_free) (node->repr_display );
420 | node->repr_display = g_strdup(node->repr_token)g_strdup_inline (node->repr_token);
421 | return node->repr_display;
422 | }
423 |
424 | char *str = _node_tostr(node, pretty);
425 |
426 | if (pretty) {
427 | g_free(node->repr_display)(__builtin_object_size ((node->repr_display), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_display, __builtin_object_size ((node->repr_display), 0)) : (g_free) (node->repr_display );
428 | node->repr_display = str;
429 | }
430 | else {
431 | g_free(node->repr_debug)(__builtin_object_size ((node->repr_debug), 0) != ((size_t ) - 1)) ? g_free_sized (node->repr_debug, __builtin_object_size ((node->repr_debug), 0)) : (g_free) (node->repr_debug);
432 | node->repr_debug = str;
433 | }
434 |
435 | return str;
436 | }
437 |
438 | static char *
439 | sprint_node(stnode_t *node)
440 | {
441 | wmem_strbuf_t *buf = wmem_strbuf_new(NULL((void*)0), NULL((void*)0));
442 |
443 | wmem_strbuf_append_printf(buf, "{ ");
444 | wmem_strbuf_append_printf(buf, "type = %s, ", stnode_type_name(node));
445 | wmem_strbuf_append_printf(buf, "data = %s, ", stnode_todebug(node)stnode_tostr(node, 0));
446 | wmem_strbuf_append_printf(buf, "location = %ld:%zu",
447 | node->location.col_start, node->location.col_len);
448 | wmem_strbuf_append_printf(buf, " }");
449 | return wmem_strbuf_finalize(buf);
450 | }
451 |
452 | void
453 | log_node_full(enum ws_log_level level,
454 | const char *file, int line, const char *func,
455 | stnode_t *node, const char *msg)
456 | {
457 | if (!ws_log_msg_is_active(WS_LOG_DOMAIN"DFilter", level))
458 | return;
459 |
460 | if (node == NULL((void*)0)) {
461 | ws_log_write_always_full(WS_LOG_DOMAIN"DFilter", level,
462 | file, line, func, "%s is NULL", msg);
463 | return;
464 | }
465 |
466 | char *str = sprint_node(node);
467 |
468 | ws_log_write_always_full(WS_LOG_DOMAIN"DFilter", level, file, line, func,
469 | "%s = %s", msg, str);
470 |
471 | g_free(str)(__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str);
472 | }
473 |
474 | void
475 | log_test_full(enum ws_log_level level,
476 | const char *file, int line, const char *func,
477 | stnode_t *node, const char *msg)
478 | {
479 | if (!ws_log_msg_is_active(WS_LOG_DOMAIN"DFilter", level))
480 | return;
481 |
482 | if (node == NULL((void*)0)) {
483 | ws_log_write_always_full(WS_LOG_DOMAIN"DFilter", level,
484 | file, line, func, "%s is NULL", msg);
485 | return;
486 | }
487 |
488 | stnode_op_t st_op;
489 | stnode_t *st_lhs = NULL((void*)0), *st_rhs = NULL((void*)0);
490 | char *lhs = NULL((void*)0), *rhs = NULL((void*)0);
491 |
492 | sttype_oper_get(node, &st_op, &st_lhs, &st_rhs);
493 |
494 | if (st_lhs)
495 | lhs = sprint_node(st_lhs);
496 | if (st_rhs)
497 | rhs = sprint_node(st_rhs);
498 |
499 | ws_log_write_always_full(WS_LOG_DOMAIN"DFilter", level, file, line, func,
500 | "%s:\n LHS = %s\n RHS = %s",
501 | stnode_todebug(node)stnode_tostr(node, 0),
502 | lhs ? lhs : "NULL",
503 | rhs ? rhs : "NULL");
504 |
505 | g_free(lhs)(__builtin_object_size ((lhs), 0) != ((size_t) - 1)) ? g_free_sized (lhs, __builtin_object_size ((lhs), 0)) : (g_free) (lhs);
506 | g_free(rhs)(__builtin_object_size ((rhs), 0) != ((size_t) - 1)) ? g_free_sized (rhs, __builtin_object_size ((rhs), 0)) : (g_free) (rhs);
507 | }
508 |
509 | static void
510 | indent(wmem_strbuf_t *buf, int level)
511 | {
512 | for (int i = 0; i < level * 2; i++) {
513 | wmem_strbuf_append_c(buf, ' ');
514 | }
515 | wmem_strbuf_append_printf(buf, "% 2d ", level);
516 | }
517 |
518 | static void
519 | visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level)
520 | {
521 | stnode_t *left, *right;
522 | stnode_t *lower, *upper;
523 | GSList *params;
524 | GSList *nodelist;
525 |
526 | if (stnode_type_id(node) == STTYPE_TEST ||
527 | stnode_type_id(node) == STTYPE_ARITHMETIC) {
528 | wmem_strbuf_append_printf(buf, "%s:\n", stnode_todebug(node)stnode_tostr(node, 0));
529 | sttype_oper_get(node, NULL((void*)0), &left, &right);
530 | if (left && right) {
531 | indent(buf, level + 1);
532 | visit_tree(buf, left, level + 1);
533 | wmem_strbuf_append_c(buf, '\n');
534 | indent(buf, level + 1);
535 | visit_tree(buf, right, level + 1);
536 | }
537 | else if (left) {
538 | indent(buf, level + 1);
539 | visit_tree(buf, left, level + 1);
540 | }
541 | else if (right) {
542 | ws_assert_not_reached()ws_log_fatal_full("DFilter", LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c" , 542, __func__, "assertion \"not reached\" failed");
543 | }
544 | }
545 | else if (stnode_type_id(node) == STTYPE_SET) {
546 | nodelist = stnode_data(node);
547 | wmem_strbuf_append_printf(buf, "SET(#%u):\n", g_slist_length(nodelist) / 2);
548 | while (nodelist) {
549 | indent(buf, level + 1);
550 | lower = nodelist->data;
551 | wmem_strbuf_append(buf, stnode_tostr(lower, false0));
552 | /* Set elements are always in pairs; upper may be null. */
553 | nodelist = g_slist_next(nodelist)((nodelist) ? (((GSList *)(nodelist))->next) : ((void*)0));
554 | ws_assert(nodelist)do { if ((1) && !(nodelist)) ws_log_fatal_full("DFilter" , LOG_LEVEL_ERROR, "epan/dfilter/syntax-tree.c", 554, __func__ , "assertion failed: %s", "nodelist"); } while (0);
555 | upper = nodelist->data;
556 | if (upper != NULL((void*)0)) {
557 | wmem_strbuf_append(buf, " .. ");
558 | wmem_strbuf_append(buf, stnode_tostr(upper, false0));
559 | }
560 | nodelist = g_slist_next(nodelist)((nodelist) ? (((GSList *)(nodelist))->next) : ((void*)0));
561 | if (nodelist != NULL((void*)0)) {
562 | wmem_strbuf_append_c(buf, '\n');
563 | }
564 | }
565 | }
566 | else if (stnode_type_id(node) == STTYPE_FUNCTION) {
567 | wmem_strbuf_append_printf(buf, "%s:\n", stnode_todebug(node)stnode_tostr(node, 0));
568 | params = sttype_function_params(node);
569 | while (params) {
570 | indent(buf, level + 1);
571 | visit_tree(buf, params->data, level + 1);
572 | if (params->next != NULL((void*)0)) {
573 | wmem_strbuf_append_c(buf, '\n');
574 | }
575 | params = params->next;
576 | }
577 | }
578 | else {
579 | wmem_strbuf_append(buf, stnode_todebug(node)stnode_tostr(node, 0));
580 | }
581 | }
582 |
583 | char *
584 | dump_syntax_tree_str(stnode_t *root)
585 | {
586 | wmem_strbuf_t *buf = wmem_strbuf_new(NULL((void*)0), NULL((void*)0));
587 | indent(buf, 0);
588 | visit_tree(buf, root, 0);
589 | return wmem_strbuf_finalize(buf);
590 | }
591 |
592 | void
593 | log_syntax_tree(enum ws_log_level level, stnode_t *root, const char *msg, char **cache_ptr)
594 | {
595 | if (!ws_log_msg_is_active(LOG_DOMAIN_DFILTER"DFilter", level))
596 | return;
597 |
598 | char *str = dump_syntax_tree_str(root);
599 |
600 | ws_log_write_always_full(LOG_DOMAIN_DFILTER"DFilter", level, NULL((void*)0), -1, NULL((void*)0),
601 | "%s:\n%s", msg, str);
602 |
603 | if (cache_ptr) {
604 | *cache_ptr = str;
605 | }
606 | else {
607 | g_free(str)(__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str);
608 | }
609 | }
610 |
611 | /*
612 | * Editor modelines - https://www.wireshark.org/tools/modelines.html
613 | *
614 | * Local variables:
615 | * c-basic-offset: 8
616 | * tab-width: 8
617 | * indent-tabs-mode: t
618 | * End:
619 | *
620 | * vi: set shiftwidth=8 tabstop=8 noexpandtab:
621 | * :indentSize=8:tabSize=8:noTabs=false:
622 | */