Bug Summary

File:builds/wireshark/wireshark/epan/color_filters.c
Warning:line 702, column 13
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

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 color_filters.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-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/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-nonliteral -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/2026-01-29-100357-3623-1 -x c /builds/wireshark/wireshark/epan/color_filters.c
1/* color_filters.c
2 * Routines for color filters
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <[email protected]>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10/*
11 * Updated 1 Dec 10 jjm
12 */
13
14#include <config.h>
15#define WS_LOG_DOMAIN"Epan" LOG_DOMAIN_EPAN"Epan"
16
17#include <glib.h>
18
19#include <errno(*__errno_location ()).h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <wsutil/filesystem.h>
25#include <wsutil/file_util.h>
26#include <wsutil/report_message.h>
27#include <wsutil/wslog.h>
28#include <wsutil/ws_assert.h>
29
30#include <epan/packet.h>
31#include "color_filters.h"
32#include "file.h"
33#include <epan/dfilter/dfilter.h>
34#include <epan/prefs.h>
35#include <epan/epan_dissect.h>
36
37/*
38 * Each line in the colorfilters file has the following format:
39 *
40 * @<filter name>@<filter string>@[<background>][<foreground>]
41 * Background and foreground colors are 16-bit comma-separated RGB
42 * triplets. Colors are 16 bits because that's what GdkColor used.
43 * We might want to use a more standard, copy+paste-able color scheme
44 * such as #RRGGBB instead.
45 */
46
47static int read_filters_file(const char *path, FILE *f, void *user_data, color_filter_add_cb_func add_cb);
48
49/* the currently active filters */
50static GSList *color_filter_list;
51
52/* keep "old" deleted filters in this list until
53 * the dissection no longer needs them (e.g. file is closed) */
54static GSList *color_filter_deleted_list;
55static GSList *color_filter_valid_list;
56
57/* Color Filters can en-/disabled. */
58static bool_Bool filters_enabled = true1;
59
60/* Remember if there are temporary coloring filters set to
61 * add sensitivity to the "Reset Coloring 1-10" menu item
62 */
63static bool_Bool tmp_colors_set;
64
65/* Create a new filter */
66color_filter_t *
67color_filter_new(const char *name, /* The name of the filter to create */
68 const char *filter_string, /* The string representing the filter */
69 color_t *bg_color, /* The background color */
70 color_t *fg_color, /* The foreground color */
71 bool_Bool disabled) /* Is the filter disabled? */
72{
73 color_filter_t *colorf;
74
75 colorf = g_new0(color_filter_t, 1)((color_filter_t *) g_malloc0_n ((1), sizeof (color_filter_t)
))
;
76 colorf->filter_name = g_strdup(name)g_strdup_inline (name);
77 colorf->filter_text = g_strdup(filter_string)g_strdup_inline (filter_string);
78 colorf->bg_color = *bg_color;
79 colorf->fg_color = *fg_color;
80 colorf->disabled = disabled;
81 return colorf;
82}
83
84/* Add ten empty (temporary) colorfilters for easy coloring */
85static void
86color_filters_add_tmp(GSList **cfl)
87{
88 char *name = NULL((void*)0);
89 uint32_t i;
90 char** bg_colors;
91 char** fg_colors;
92 unsigned long cval;
93 color_t bg_color, fg_color;
94 color_filter_t *colorf;
95
96 ws_assert(strlen(prefs.gui_colorized_fg)==69)do { if ((1) && !(strlen(prefs.gui_colorized_fg)==69)
) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 96, __func__, "assertion failed: %s", "strlen(prefs.gui_colorized_fg)==69"
); } while (0)
;
97 ws_assert(strlen(prefs.gui_colorized_bg)==69)do { if ((1) && !(strlen(prefs.gui_colorized_bg)==69)
) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 97, __func__, "assertion failed: %s", "strlen(prefs.gui_colorized_bg)==69"
); } while (0)
;
98 fg_colors = g_strsplit(prefs.gui_colorized_fg, ",", -1);
99 bg_colors = g_strsplit(prefs.gui_colorized_bg, ",", -1);
100
101 for ( i=1 ; i<=10 ; i++ ) {
102 name = ws_strdup_printf("%s%02d",CONVERSATION_COLOR_PREFIX,i)wmem_strdup_printf(((void*)0), "%s%02d","___conversation_color_filter___"
,i)
;
103
104 /* retrieve background and foreground colors */
105 cval = strtoul(fg_colors[i-1], NULL((void*)0), 16);
106 fg_color.red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
107 fg_color.green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
108 fg_color.blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
109 cval = strtoul(bg_colors[i-1], NULL((void*)0), 16);
110 bg_color.red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
111 bg_color.green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
112 bg_color.blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
113 colorf = color_filter_new(name, NULL((void*)0), &bg_color, &fg_color, true1);
114 colorf->filter_text = g_strdup("frame")g_strdup_inline ("frame");
115 *cfl = g_slist_append(*cfl, colorf);
116
117 g_free(name);
118 }
119
120 g_strfreev(fg_colors);
121 g_strfreev(bg_colors);
122}
123
124static int
125color_filters_find_by_name_cb(const void *arg1, const void *arg2)
126{
127 const color_filter_t *colorf = (const color_filter_t *)arg1;
128 const char *name = (const char *)arg2;
129
130 return strcmp(colorf->filter_name, name);
131}
132
133/* Get the filter of a temporary color filter */
134char*
135color_filters_get_tmp(uint8_t filt_nr)
136{
137 char* name = NULL((void*)0);
138 char* filter = NULL((void*)0);
139 GSList* cfl;
140 color_filter_t* colorf;
141 /* Only perform a lookup if the supplied filter number is in the expected range */
142 if (filt_nr < 1 || filt_nr > 10)
143 return NULL((void*)0);
144
145 name = ws_strdup_printf("%s%02d", CONVERSATION_COLOR_PREFIX, filt_nr)wmem_strdup_printf(((void*)0), "%s%02d", "___conversation_color_filter___"
, filt_nr)
;
146 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
147 colorf = (color_filter_t*)cfl->data;
148
149 if (!colorf->disabled)
150 filter = g_strdup(colorf->filter_text)g_strdup_inline (colorf->filter_text);
151
152 g_free(name);
153
154 return filter;
155}
156
157/* Set the filter off a temporary colorfilters and enable it */
158bool_Bool
159color_filters_set_tmp(uint8_t filt_nr, const char *filter, bool_Bool disabled, char **err_msg)
160{
161 char *name = NULL((void*)0);
162 const char *tmpfilter = NULL((void*)0);
163 GSList *cfl;
164 color_filter_t *colorf;
165 dfilter_t *compiled_filter;
166 uint8_t i;
167 df_error_t *df_err = NULL((void*)0);
168 /* Go through the temporary filters and look for the same filter string.
169 * If found, clear it so that a filter can be "moved" up and down the list
170 */
171 for ( i=1 ; i<=10 ; i++ ) {
172 /* If we need to reset the temporary filter (filter==NULL), don't look
173 * for other rules with the same filter string
174 */
175 if( i!=filt_nr && filter==NULL((void*)0) )
176 continue;
177
178 name = ws_strdup_printf("%s%02d",CONVERSATION_COLOR_PREFIX,i)wmem_strdup_printf(((void*)0), "%s%02d","___conversation_color_filter___"
,i)
;
179 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
180 colorf = (color_filter_t *)cfl->data;
181
182 /* Only change the filter rule if this is the rule to change or if
183 * a matching filter string has been found
184 */
185 if(colorf && ( i == filt_nr || filter == NULL((void*)0) || !strcmp(filter, colorf->filter_text) ) ) {
186 /* set filter string to "frame" if we are resetting the rules
187 * or if we found a matching filter string which need to be cleared
188 */
189 tmpfilter = ( (filter==NULL((void*)0)) || (i!=filt_nr) ) ? "frame" : filter;
190 if (!dfilter_compile(tmpfilter, &compiled_filter, &df_err)dfilter_compile_full(tmpfilter, &compiled_filter, &df_err
, (1U << 1)|(1U << 2), __func__)
) {
191 *err_msg = ws_strdup_printf( "Could not compile color filter name: \"%s\" text: \"%s\".\n%s", name, filter, df_err->msg)wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, name, filter, df_err->msg)
;
192 df_error_free(&df_err);
193 g_free(name);
194 return false0;
195 } else {
196 g_free(colorf->filter_text);
197 dfilter_free(colorf->c_colorfilter);
198 colorf->filter_text = g_strdup(tmpfilter)g_strdup_inline (tmpfilter);
199 colorf->c_colorfilter = compiled_filter;
200 colorf->disabled = ((i!=filt_nr) ? true1 : disabled);
201 /* Remember that there are now temporary coloring filters set */
202 if( filter )
203 tmp_colors_set = true1;
204 }
205 }
206 g_free(name);
207 }
208 return true1;
209}
210
211const color_filter_t *
212color_filters_tmp_color(uint8_t filter_num) {
213 char *name;
214 color_filter_t *colorf = NULL((void*)0);
215 GSList *cfl;
216
217 name = ws_strdup_printf("%s%02d", CONVERSATION_COLOR_PREFIX, filter_num)wmem_strdup_printf(((void*)0), "%s%02d", "___conversation_color_filter___"
, filter_num)
;
218 cfl = g_slist_find_custom(color_filter_list, name, color_filters_find_by_name_cb);
219 if (cfl) {
220 colorf = (color_filter_t *)cfl->data;
221 }
222 g_free(name);
223
224 return colorf;
225}
226
227/* Reset the temporary colorfilters */
228bool_Bool
229color_filters_reset_tmp(char **err_msg)
230{
231 uint8_t i;
232
233 for ( i=1 ; i<=10 ; i++ ) {
234 if (!color_filters_set_tmp(i, NULL((void*)0), true1, err_msg))
235 return false0;
236 }
237 /* Remember that there are now *no* temporary coloring filters set */
238 tmp_colors_set = false0;
239 return true1;
240}
241
242/* delete the specified filter */
243void
244color_filter_delete(color_filter_t *colorf)
245{
246 g_free(colorf->filter_name);
247 g_free(colorf->filter_text);
248 dfilter_free(colorf->c_colorfilter);
249 g_free(colorf);
250}
251
252/* delete the specified filter (called from g_slist_foreach) */
253static void
254color_filter_delete_cb(void *filter_arg)
255{
256 color_filter_t *colorf = (color_filter_t *)filter_arg;
257
258 color_filter_delete(colorf);
259}
260
261/* delete the specified list */
262void
263color_filter_list_delete(GSList **cfl)
264{
265 g_slist_free_full(*cfl, color_filter_delete_cb);
266 *cfl = NULL((void*)0);
267}
268
269/* clone a single list entries from normal to edit list */
270static color_filter_t *
271color_filter_clone(color_filter_t *colorf)
272{
273 color_filter_t *new_colorf;
274
275 new_colorf = g_new(color_filter_t, 1)((color_filter_t *) g_malloc_n ((1), sizeof (color_filter_t))
)
;
276 new_colorf->filter_name = g_strdup(colorf->filter_name)g_strdup_inline (colorf->filter_name);
277 new_colorf->filter_text = g_strdup(colorf->filter_text)g_strdup_inline (colorf->filter_text);
278 new_colorf->bg_color = colorf->bg_color;
279 new_colorf->fg_color = colorf->fg_color;
280 new_colorf->disabled = colorf->disabled;
281 new_colorf->c_colorfilter = NULL((void*)0);
282
283 return new_colorf;
284}
285
286static void
287color_filter_list_clone_cb(void *filter_arg, void *cfl_arg)
288{
289 GSList **cfl = (GSList **)cfl_arg;
290 color_filter_t *new_colorf;
291
292 new_colorf = color_filter_clone((color_filter_t *)filter_arg);
293 *cfl = g_slist_append(*cfl, new_colorf);
294}
295
296/* clone the specified list */
297static GSList *
298color_filter_list_clone(GSList *cfl)
299{
300 GSList *new_list = NULL((void*)0);
301
302 g_slist_foreach(cfl, color_filter_list_clone_cb, &new_list);
303
304 return new_list;
305}
306
307static bool_Bool
308color_filters_get(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
309{
310 char *path;
311 FILE *f;
312 int ret;
313
314 /* start the list with the temporary colorizing rules */
315 color_filters_add_tmp(&color_filter_list);
316
317 /*
318 * Try to get the user's filters.
319 *
320 * Get the path for the file that would have their filters, and
321 * try to open it.
322 */
323 path = get_persconffile_path(COLORFILTERS_FILE_NAME"colorfilters", true1, app_env_var_prefix);
324 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
325 if (errno(*__errno_location ()) != ENOENT2) {
326 /* Error trying to open the file; give up. */
327 *err_msg = ws_strdup_printf("Could not open filter file\n\"%s\": %s.", path,wmem_strdup_printf(((void*)0), "Could not open filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
328 g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
329 g_free(path);
330 return false0;
331 }
332 /* They don't have any filters; try to read the global filters */
333 g_free(path);
334 return color_filters_read_globals(&color_filter_list, err_msg, add_cb, app_env_var_prefix);
335 }
336
337 /*
338 * We've opened it; try to read it.
339 */
340 ret = read_filters_file(path, f, &color_filter_list, add_cb);
341 if (ret != 0) {
342 *err_msg = ws_strdup_printf("Error reading filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
343 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
344 fclose(f);
345 g_free(path);
346 return false0;
347 }
348
349 /* Success. */
350 fclose(f);
351 g_free(path);
352 return true1;
353}
354
355/* Initialize the filter structures (reading from file) for general running, including app startup */
356bool_Bool
357color_filters_init(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
358{
359 /* delete all currently existing filters */
360 color_filter_list_delete(&color_filter_list);
361
362 /* now try to construct the filters list */
363 return color_filters_get(err_msg, add_cb, app_env_var_prefix);
364}
365
366bool_Bool
367color_filters_reload(char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
368{
369 /* "move" old entries to the deleted list
370 * we must keep them until the dissection no longer needs them */
371 color_filter_deleted_list = g_slist_concat(color_filter_deleted_list, color_filter_list);
372 color_filter_list = NULL((void*)0);
373
374 /* now try to construct the filters list */
375 return color_filters_get(err_msg, add_cb, app_env_var_prefix);
376}
377
378void
379color_filters_cleanup(void)
380{
381 /* delete the previously deleted filters */
382 color_filter_list_delete(&color_filter_deleted_list);
383}
384
385typedef struct _color_clone
386{
387 void *user_data;
388 color_filter_add_cb_func add_cb;
389} color_clone_t;
390
391static void
392color_filters_clone_cb(void *filter_arg, void *user_data)
393{
394 color_clone_t* clone_data = (color_clone_t*)user_data;
395 color_filter_t * new_colorf = color_filter_clone((color_filter_t *)filter_arg);
396
397 clone_data->add_cb (new_colorf, clone_data->user_data);
398}
399
400void
401color_filters_clone(void *user_data, color_filter_add_cb_func add_cb)
402{
403 color_clone_t clone_data;
404
405 clone_data.user_data = user_data;
406 clone_data.add_cb = add_cb;
407 g_slist_foreach(color_filter_list, color_filters_clone_cb, &clone_data);
408}
409
410
411static void
412color_filter_compile_cb(void *filter_arg, void *err)
413{
414 color_filter_t *colorf = (color_filter_t *)filter_arg;
415 char **err_msg = (char**)err;
416 df_error_t *df_err = NULL((void*)0);
417
418 ws_assert(colorf->c_colorfilter == NULL)do { if ((1) && !(colorf->c_colorfilter == ((void*
)0))) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 418, __func__, "assertion failed: %s", "colorf->c_colorfilter == ((void*)0)"
); } while (0)
;
419
420 /* If the filter is disabled it doesn't matter if it compiles or not. */
421 if (colorf->disabled) return;
422
423 if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)dfilter_compile_full(colorf->filter_text, &colorf->
c_colorfilter, &df_err, (1U << 1)|(1U << 2), __func__
)
) {
424 *err_msg = ws_strdup_printf("Could not compile color filter name: \"%s\" text: \"%s\".\n%s",wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
425 colorf->filter_name, colorf->filter_text, df_err->msg)wmem_strdup_printf(((void*)0), "Could not compile color filter name: \"%s\" text: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
;
426 df_error_free(&df_err);
427 /* this filter was compilable before, so this should never happen */
428 /* except if the OK button of the parent window has been clicked */
429 /* so don't use ws_assert_not_reached() but check the filters again */
430 }
431}
432
433static void
434color_filter_validate_cb(void *filter_arg, void *err)
435{
436 color_filter_t *colorf = (color_filter_t *)filter_arg;
437 char **err_msg = (char**)err;
438 df_error_t *df_err = NULL((void*)0);
439
440 ws_assert(colorf->c_colorfilter == NULL)do { if ((1) && !(colorf->c_colorfilter == ((void*
)0))) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/color_filters.c"
, 440, __func__, "assertion failed: %s", "colorf->c_colorfilter == ((void*)0)"
); } while (0)
;
441
442 /* If the filter is disabled it doesn't matter if it compiles or not. */
443 if (colorf->disabled) return;
444
445 if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)dfilter_compile_full(colorf->filter_text, &colorf->
c_colorfilter, &df_err, (1U << 1)|(1U << 2), __func__
)
) {
446 *err_msg = ws_strdup_printf("Disabling color filter name: \"%s\" filter: \"%s\".\n%s",wmem_strdup_printf(((void*)0), "Disabling color filter name: \"%s\" filter: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
447 colorf->filter_name, colorf->filter_text, df_err->msg)wmem_strdup_printf(((void*)0), "Disabling color filter name: \"%s\" filter: \"%s\".\n%s"
, colorf->filter_name, colorf->filter_text, df_err->
msg)
;
448 df_error_free(&df_err);
449
450 /* Disable the color filter in the list of color filters. */
451 colorf->disabled = true1;
452 }
453
454 /* XXX: What if the color filter tests "frame.coloring_rule.name" or
455 * "frame.coloring_rule.string"?
456 */
457}
458
459/* apply changes from the edit list */
460bool_Bool
461color_filters_apply(GSList *tmp_cfl, GSList *edit_cfl, char** err_msg)
462{
463 bool_Bool ret = true1;
464
465 *err_msg = NULL((void*)0);
466
467 /* "move" old entries to the deleted list
468 * we must keep them until the dissection no longer needs them */
469 color_filter_deleted_list = g_slist_concat(color_filter_deleted_list, color_filter_list);
470 color_filter_list = NULL((void*)0);
471
472 /* clone all list entries from tmp/edit to normal list */
473 color_filter_list_delete(&color_filter_valid_list);
474 color_filter_valid_list = color_filter_list_clone(tmp_cfl);
475 color_filter_valid_list = g_slist_concat(color_filter_valid_list,
476 color_filter_list_clone(edit_cfl) );
477
478 /* compile all filter */
479 g_slist_foreach(color_filter_valid_list, color_filter_validate_cb, err_msg);
480 if (*err_msg != NULL((void*)0)) {
481 ret = false0;
482 }
483
484 /* clone all list entries from tmp/edit to normal list */
485 color_filter_list = color_filter_list_clone(color_filter_valid_list);
486
487 /* compile all filter */
488 g_slist_foreach(color_filter_list, color_filter_compile_cb, err_msg);
489 if (*err_msg != NULL((void*)0)) {
490 ret = false0;
491 }
492
493 return ret;
494}
495
496bool_Bool
497color_filters_used(void)
498{
499 return color_filter_list != NULL((void*)0) && filters_enabled;
500}
501
502bool_Bool
503tmp_color_filters_used(void)
504{
505 return tmp_colors_set;
506}
507
508/* prepare the epan_dissect_t for the filter */
509static void
510prime_edt(void *data, void *user_data)
511{
512 color_filter_t *colorf = (color_filter_t *)data;
513 epan_dissect_t *edt = (epan_dissect_t *)user_data;
514
515 if (colorf->c_colorfilter != NULL((void*)0))
516 epan_dissect_prime_with_dfilter(edt, colorf->c_colorfilter);
517}
518
519/* Prime the epan_dissect_t with all the compiler
520 * color filters in 'color_filter_list'. */
521void
522color_filters_prime_edt(epan_dissect_t *edt)
523{
524 if (color_filters_used())
525 g_slist_foreach(color_filter_list, prime_edt, edt);
526}
527
528static int
529find_hfid(const void *data, const void *user_data)
530{
531 color_filter_t *colorf = (color_filter_t *)data;
532 int hfid = GPOINTER_TO_INT(user_data)((gint) (glong) (user_data));
533
534 if ((!colorf->disabled) && colorf->c_colorfilter != NULL((void*)0)) {
535 if (dfilter_interested_in_field(colorf->c_colorfilter, hfid)) {
536 return 0;
537 }
538 }
539 return -1;
540}
541
542bool_Bool
543color_filters_use_hfid(int hfid)
544{
545 GSList *item = NULL((void*)0);
546 if (color_filters_used())
547 item = g_slist_find_custom(color_filter_list, GINT_TO_POINTER(hfid)((gpointer) (glong) (hfid)), find_hfid);
548 return (item != NULL((void*)0));
549}
550
551static int
552find_proto(const void *data, const void *user_data)
553{
554 color_filter_t *colorf = (color_filter_t *)data;
555 int proto_id = GPOINTER_TO_INT(user_data)((gint) (glong) (user_data));
556
557 if ((!colorf->disabled) && colorf->c_colorfilter != NULL((void*)0)) {
558 if (dfilter_interested_in_proto(colorf->c_colorfilter, proto_id)) {
559 return 0;
560 }
561 }
562 return -1;
563}
564
565bool_Bool
566color_filters_use_proto(int proto_id)
567{
568 GSList *item = NULL((void*)0);
569 if (color_filters_used())
570 item = g_slist_find_custom(color_filter_list, GINT_TO_POINTER(proto_id)((gpointer) (glong) (proto_id)), find_proto);
571 return (item != NULL((void*)0));
572}
573
574/* * Return the color_t for later use */
575const color_filter_t *
576color_filters_colorize_packet(epan_dissect_t *edt)
577{
578 GSList *curr;
579 color_filter_t *colorf;
580
581 /* If we have color filters, "search" for the matching one. */
582 if ((edt->tree != NULL((void*)0)) && (color_filters_used())) {
583 curr = color_filter_list;
584
585 while(curr != NULL((void*)0)) {
586 colorf = (color_filter_t *)curr->data;
587 if ( (!colorf->disabled) &&
588 (colorf->c_colorfilter != NULL((void*)0)) &&
589 dfilter_apply_edt(colorf->c_colorfilter, edt)) {
590 return colorf;
591 }
592 curr = g_slist_next(curr)((curr) ? (((GSList *)(curr))->next) : ((void*)0));
593 }
594 }
595
596 return NULL((void*)0);
597}
598
599/* read filters from the given file */
600/* XXX - Would it make more sense to use GStrings here instead of reallocing
601 our buffers? */
602static int
603read_filters_file(const char *path, FILE *f, void *user_data, color_filter_add_cb_func add_cb)
604{
605#define INIT_BUF_SIZE128 128
606 char *name;
607 char *filter_exp;
608 uint32_t name_len = INIT_BUF_SIZE128;
609 uint32_t filter_exp_len = INIT_BUF_SIZE128;
610 uint32_t i = 0;
611 int c;
612 uint16_t fg_r, fg_g, fg_b, bg_r, bg_g, bg_b;
613 bool_Bool disabled = false0;
614 bool_Bool skip_end_of_line = false0;
615 int ret = 0;
616
617 name = (char *)g_malloc(name_len + 1);
618 filter_exp = (char *)g_malloc(filter_exp_len + 1);
619
620 while (1) {
3
Loop condition is true. Entering loop body
37
Loop condition is true. Entering loop body
621
622 if (skip_end_of_line
3.1
'skip_end_of_line' is false
37.1
'skip_end_of_line' is true
) {
38
Taking true branch
623 do {
41
Loop condition is false. Exiting loop
624 c = ws_getc_unlockedgetc_unlocked(f);
625 } while (c != EOF(-1) && c != '\n');
39
Assuming the condition is true
40
Assuming the condition is false
626 if (c == EOF(-1))
42
Taking false branch
627 break;
628 disabled = false0;
629 skip_end_of_line = false0;
630 }
631
632 while ((c = ws_getc_unlockedgetc_unlocked(f)) != EOF(-1) && g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)) {
4
Assuming the condition is true
5
Loop condition is false. Execution continues on line 638
43
Assuming the condition is true
44
Loop condition is false. Execution continues on line 638
633 if (c == '\n') {
634 continue;
635 }
636 }
637
638 if (c == EOF(-1))
6
Taking false branch
45
Taking false branch
639 break;
640
641 if (c == '!') {
7
Assuming the condition is false
8
Taking false branch
46
Assuming the condition is false
47
Taking false branch
642 disabled = true1;
643 continue;
644 }
645
646 /* skip # comments and invalid lines */
647 if (c != '@') {
9
Assuming the condition is false
10
Taking false branch
48
Assuming the condition is false
49
Taking false branch
648 skip_end_of_line = true1;
649 continue;
650 }
651
652 /* we get the @ delimiter.
653 * Format is:
654 * @name@filter expression@[background r,g,b][foreground r,g,b]
655 */
656
657 /* retrieve name */
658 i = 0;
659 while (1) {
11
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
50
Loop condition is true. Entering loop body
55
Loop condition is true. Entering loop body
660 c = ws_getc_unlockedgetc_unlocked(f);
661 if (c == EOF(-1) || c == '@')
12
Assuming the condition is false
13
Assuming the condition is false
14
Taking false branch
17
Assuming the condition is false
18
Assuming the condition is true
19
Taking true branch
51
Assuming the condition is false
52
Assuming the condition is false
53
Taking false branch
56
Assuming the condition is false
57
Assuming the condition is true
58
Taking true branch
662 break;
20
Execution continues on line 670
59
Execution continues on line 670
663 if (i
14.1
'i' is < 'name_len'
53.1
'i' is < 'name_len'
>= name_len) {
15
Taking false branch
54
Taking false branch
664 /* buffer isn't long enough; double its length.*/
665 name_len *= 2;
666 name = (char *)g_realloc(name, name_len + 1);
667 }
668 name[i++] = c;
669 }
670 name[i] = '\0';
671
672 if (c == EOF(-1)) {
21
Taking false branch
60
Taking false branch
673 break;
674 } else if (i
21.1
'i' is not equal to 0
60.1
'i' is not equal to 0
== 0) {
22
Taking false branch
61
Taking false branch
675 skip_end_of_line = true1;
676 continue;
677 }
678
679 /* retrieve filter expression */
680 i = 0;
681 while (1) {
23
Loop condition is true. Entering loop body
28
Loop condition is true. Entering loop body
62
Loop condition is true. Entering loop body
67
Loop condition is true. Entering loop body
682 c = ws_getc_unlockedgetc_unlocked(f);
683 if (c == EOF(-1) || c == '@')
24
Assuming the condition is false
25
Assuming the condition is false
26
Taking false branch
29
Assuming the condition is false
30
Assuming the condition is true
31
Taking true branch
63
Assuming the condition is false
64
Assuming the condition is false
65
Taking false branch
68
Assuming the condition is false
69
Assuming the condition is true
70
Taking true branch
684 break;
32
Execution continues on line 692
71
Execution continues on line 692
685 if (i
26.1
'i' is < 'filter_exp_len'
65.1
'i' is < 'filter_exp_len'
>= filter_exp_len) {
27
Taking false branch
66
Taking false branch
686 /* buffer isn't long enough; double its length.*/
687 filter_exp_len *= 2;
688 filter_exp = (char *)g_realloc(filter_exp, filter_exp_len + 1);
689 }
690 filter_exp[i++] = c;
691 }
692 filter_exp[i] = '\0';
693
694 if (c == EOF(-1)) {
33
Taking false branch
72
Taking false branch
695 break;
696 } else if (i
33.1
'i' is not equal to 0
72.1
'i' is not equal to 0
== 0) {
34
Taking false branch
73
Taking false branch
697 skip_end_of_line = true1;
698 continue;
699 }
700
701 /* retrieve background and foreground colors */
702 if (fscanf(f,"[%hu,%hu,%hu][%hu,%hu,%hu]",
35
Assuming this stream operation fails
36
Taking false branch
74
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
703 &bg_r, &bg_g, &bg_b, &fg_r, &fg_g, &fg_b) == 6) {
704
705 /* we got a complete color filter */
706
707 color_t bg_color, fg_color;
708 color_filter_t *colorf;
709 dfilter_t *temp_dfilter = NULL((void*)0);
710 df_error_t *df_err = NULL((void*)0);
711
712 if (!disabled && !dfilter_compile(filter_exp, &temp_dfilter, &df_err)dfilter_compile_full(filter_exp, &temp_dfilter, &df_err
, (1U << 1)|(1U << 2), __func__)
) {
713 report_warning("Disabling color filter: Could not compile \"%s\" in colorfilters file \"%s\".\n%s", name, path, df_err->msg);
714 df_error_free(&df_err);
715
716 /* skip_end_of_line = true; */
717 disabled = true1;
718 }
719
720 fg_color.red = fg_r;
721 fg_color.green = fg_g;
722 fg_color.blue = fg_b;
723
724 bg_color.red = bg_r;
725 bg_color.green = bg_g;
726 bg_color.blue = bg_b;
727
728 colorf = color_filter_new(name, filter_exp, &bg_color,
729 &fg_color, disabled);
730 if(user_data == &color_filter_list) {
731 GSList **cfl = (GSList **)user_data;
732
733 /* internal call */
734 colorf->c_colorfilter = temp_dfilter;
735 *cfl = g_slist_append(*cfl, colorf);
736 } else {
737 /* external call */
738 /* just editing, don't need the compiled filter */
739 dfilter_free(temp_dfilter);
740 add_cb(colorf, user_data);
741 }
742 } /* if sscanf */
743
744 skip_end_of_line = true1;
745 }
746
747 if (ferror(f))
748 ret = errno(*__errno_location ());
749
750 g_free(name);
751 g_free(filter_exp);
752 return ret;
753}
754
755/* read filters from the filter file */
756bool_Bool
757color_filters_read_globals(void *user_data, char** err_msg, color_filter_add_cb_func add_cb, const char* app_env_var_prefix)
758{
759 char *path;
760 FILE *f;
761 int ret;
762
763 /*
764 * Try to get the global filters.
765 *
766 * Get the path for the file that would have the global filters, and
767 * try to open it.
768 */
769 path = get_datafile_path(COLORFILTERS_FILE_NAME"colorfilters", app_env_var_prefix);
770 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
771 if (errno(*__errno_location ()) != ENOENT2) {
772 /* Error trying to open the file; give up. */
773 *err_msg = ws_strdup_printf("Could not open global filter file\n\"%s\": %s.", path,wmem_strdup_printf(((void*)0), "Could not open global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
774 g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
775 g_free(path);
776 return false0;
777 }
778
779 /*
780 * There is no global filter file; treat that as equivalent to
781 * that file existing bug being empty, and say we succeeded.
782 */
783 g_free(path);
784 return true1;
785 }
786
787 ret = read_filters_file(path, f, user_data, add_cb);
788 if (ret != 0) {
789 *err_msg = ws_strdup_printf("Error reading global filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
790 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading global filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
791 fclose(f);
792 g_free(path);
793 return false0;
794 }
795
796 fclose(f);
797 g_free(path);
798 return true1;
799}
800
801/* read filters from some other filter file (import) */
802bool_Bool
803color_filters_import(const char *path, void *user_data, char **err_msg, color_filter_add_cb_func add_cb)
804{
805 FILE *f;
806 int ret;
807
808 if ((f = ws_fopenfopen(path, "r")) == NULL((void*)0)) {
1
Taking false branch
809 *err_msg = ws_strdup_printf("Could not open filter file\n%s\nfor reading: %s.",wmem_strdup_printf(((void*)0), "Could not open filter file\n%s\nfor reading: %s."
, path, g_strerror((*__errno_location ())))
810 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open filter file\n%s\nfor reading: %s."
, path, g_strerror((*__errno_location ())))
;
811 return false0;
812 }
813
814 ret = read_filters_file(path, f, user_data, add_cb);
2
Calling 'read_filters_file'
815 if (ret != 0) {
816 *err_msg = ws_strdup_printf("Error reading filter file\n\"%s\": %s.",wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
817 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Error reading filter file\n\"%s\": %s."
, path, g_strerror((*__errno_location ())))
;
818 fclose(f);
819 return false0;
820 }
821
822 fclose(f);
823 return true1;
824}
825
826struct write_filter_data
827{
828 FILE *f;
829 bool_Bool only_selected;
830};
831
832/* save a single filter */
833static void
834write_filter(void *filter_arg, void *data_arg)
835{
836 struct write_filter_data *data = (struct write_filter_data *)data_arg;
837 color_filter_t *colorf = (color_filter_t *)filter_arg;
838 FILE *f = data->f;
839
840 if ( (!data->only_selected) &&
841 (strstr(colorf->filter_name,CONVERSATION_COLOR_PREFIX"___conversation_color_filter___")==NULL((void*)0)) ) {
842 fprintf(f,"%s@%s@%s@[%u,%u,%u][%u,%u,%u]\n",
843 colorf->disabled ? "!" : "",
844 colorf->filter_name,
845 colorf->filter_text,
846 colorf->bg_color.red,
847 colorf->bg_color.green,
848 colorf->bg_color.blue,
849 colorf->fg_color.red,
850 colorf->fg_color.green,
851 colorf->fg_color.blue);
852 }
853}
854
855/* save filters in a filter file */
856static bool_Bool
857write_filters_file(GSList *cfl, FILE *f, bool_Bool only_selected, const char* app_name)
858{
859 struct write_filter_data data;
860
861 data.f = f;
862 data.only_selected = only_selected;
863
864 fprintf(f,"# This file was created by %s. Edit with care.\n", app_name);
865 g_slist_foreach(cfl, write_filter, &data);
866 return true1;
867}
868
869/* save filters in users filter file */
870bool_Bool
871color_filters_write(GSList *cfl, const char* app_name, const char* app_env_var_prefix, char** err_msg)
872{
873 char *pf_dir_path;
874 char *path;
875 FILE *f;
876
877 /* Create the directory that holds personal configuration files,
878 if necessary. */
879 if (create_persconffile_dir(app_env_var_prefix, &pf_dir_path) == -1) {
880 *err_msg = ws_strdup_printf("Can't create directory\n\"%s\"\nfor color files: %s.",wmem_strdup_printf(((void*)0), "Can't create directory\n\"%s\"\nfor color files: %s."
, pf_dir_path, g_strerror((*__errno_location ())))
881 pf_dir_path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Can't create directory\n\"%s\"\nfor color files: %s."
, pf_dir_path, g_strerror((*__errno_location ())))
;
882 g_free(pf_dir_path);
883 return false0;
884 }
885
886 path = get_persconffile_path(COLORFILTERS_FILE_NAME"colorfilters", true1, app_env_var_prefix);
887 if ((f = ws_fopenfopen(path, "w+")) == NULL((void*)0)) {
888 *err_msg = ws_strdup_printf("Could not open\n%s\nfor writing: %s.",wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
889 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
;
890 g_free(path);
891 return false0;
892 }
893 g_free(path);
894 write_filters_file(cfl, f, false0, app_name);
895 fclose(f);
896 return true1;
897}
898
899/* save filters in some other filter file (export) */
900bool_Bool
901color_filters_export(const char *path, GSList *cfl, bool_Bool only_marked, const char* app_name, char** err_msg)
902{
903 FILE *f;
904
905 if ((f = ws_fopenfopen(path, "w+")) == NULL((void*)0)) {
906 *err_msg = ws_strdup_printf("Could not open\n%s\nfor writing: %s.",wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
907 path, g_strerror(errno))wmem_strdup_printf(((void*)0), "Could not open\n%s\nfor writing: %s."
, path, g_strerror((*__errno_location ())))
;
908 return false0;
909 }
910 write_filters_file(cfl, f, only_marked, app_name);
911 fclose(f);
912 return true1;
913}
914
915/*
916 * Editor modelines - https://www.wireshark.org/tools/modelines.html
917 *
918 * Local variables:
919 * c-basic-offset: 4
920 * tab-width: 8
921 * indent-tabs-mode: nil
922 * End:
923 *
924 * vi: set shiftwidth=4 tabstop=8 expandtab:
925 * :indentSize=4:tabSize=8:noTabs=true:
926 */