Bug Summary

File:epan/color_filters.c
Warning:line 706, column 13
Read function called when stream is in EOF state. Function has no effect

Annotated Source Code

Press '?' to see keyboard shortcuts

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