/builds/wireshark/wireshark/epan/stats_tree.c (2024)

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 stats_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 -mframe-pointer=all -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 -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-17/lib/clang/17 -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/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 -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../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-error=stringop-overflow= -Wno-error=deprecated-declarations -Wno-format-truncation -Wno-pointer-sign -std=gnu11 -fdebug-compilation-dir=/builds/wireshark/wireshark/build -ferror-limit 19 -fvisibility=hidden -fwrapv -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-06-26-100254-3154-1 -x c /builds/wireshark/wireshark/epan/stats_tree.c

1/* stats_tree.c2 * API for a counter tree for Wireshark3 * 2004, Luis E. G. Ontanon4 *5 * Wireshark - Network traffic analyzer6 * By Gerald Combs <[emailprotected]>7 * Copyright 1998 Gerald Combs8 *9 * SPDX-License-Identifier: GPL-2.0-or-later10 */11 12 /* stats_tree modifications by Deon van der Westhuysen, November 201313 * support for14 * - sorting by column,15 * - calculation of average values16 * - calculation of burst rate17 * - export to text, CSV or XML file18 */19 20#include "config.h"21 22#include <glib.h>23 24#include <stdlib.h>25 26#include <epan/stats_tree_priv.h>27#include <epan/prefs.h>28#include <math.h>29#include <string.h>30 31#include "strutil.h"32#include "stats_tree.h"33#include <wsutil/ws_assert.h>34 35enum _stat_tree_columns {36 COL_NAME,37 COL_COUNT,38 COL_AVERAGE,39 COL_MIN,40 COL_MAX,41 COL_RATE,42 COL_PERCENT,43 COL_BURSTRATE,44 COL_BURSTTIME,45 N_COLUMNS46};47 48/* used to contain the registered stat trees */49static GHashTable *registry;50 51/* a text representation of a node52if buffer is NULL returns a newly allocated string */53extern char*54stats_tree_node_to_str(const stat_node *node, char *buffer, unsigned len)55{56 if (buffer) {57 snprintf(buffer,len,"%s: %i",node->name, node->counter);58 return buffer;59 } else {60 return ws_strdup_printf("%s: %i",node->name, node->counter)wmem_strdup_printf(((void*)0), "%s: %i",node->name, node->
counter)
;61 }62}63 64extern unsigned65// NOLINTNEXTLINE(misc-no-recursion)66stats_tree_branch_max_namelen(const stat_node *node, unsigned indent)67{68 stat_node *child;69 unsigned maxlen = 0;70 unsigned len;71 72 indent = indent > INDENT_MAX32 ? INDENT_MAX32 : indent;73 74 if (node->children) {75 for (child = node->children; child; child = child->next ) {76 // Recursion is limited by proto.c checks77 len = stats_tree_branch_max_namelen(child,indent+1);78 maxlen = len > maxlen ? len : maxlen;79 }80 }81 82 if (node->st_flags&ST_FLG_ROOTCHILD0x20000000) {83 char *display_name = stats_tree_get_displayname(node->name);84 len = (unsigned) strlen(display_name) + indent;85 g_free(display_name);86 }87 else {88 len = (unsigned) strlen(node->name) + indent;89 }90 maxlen = len > maxlen ? len : maxlen;91 92 return maxlen;93}94 95/* frees the resources allocated by a stat_tree node */96static void97// NOLINTNEXTLINE(misc-no-recursion)98free_stat_node(stat_node *node)99{100 stat_node *child;101 stat_node *next;102 burst_bucket *bucket;103 104 if (node->children) {105 for (child = node->children; child; child = next ) {106 /* child->next will be gone after free_stat_node, so cache it here */107 next = child->next;108 // Recursion is limited by proto.c checks109 free_stat_node(child);110 }111 }112 113 if (node->hash) g_hash_table_destroy(node->hash);114 115 while (node->bh) {116 bucket = node->bh;117 node->bh = bucket->next;118 g_free(bucket);119 }120 121 g_free(node->rng);122 g_free(node->name);123 g_free(node);124}125 126/* destroys the whole tree instance */127extern void128stats_tree_free(stats_tree *st)129{130 stat_node *child;131 stat_node *next;132 133 if (!st) return;134 135 g_free(st->filter);136 g_hash_table_destroy(st->names);137 g_ptr_array_free(st->parents,TRUE(!(0)));138 g_free(st->display_name);139 140 for (child = st->root.children; child; child = next ) {141 /* child->next will be gone after free_stat_node, so cache it here */142 next = child->next;143 free_stat_node(child);144 }145 146 if (st->cfg->free_tree_pr)147 st->cfg->free_tree_pr(st);148 149 if (st->cfg->cleanup)150 st->cfg->cleanup(st);151 152 g_free(st);153}154 155 156/* reset a node to its original state */157static void158// NOLINTNEXTLINE(misc-no-recursion)159reset_stat_node(stat_node *node)160{161 stat_node *child;162 burst_bucket *bucket;163 164 node->counter = 0;165 switch (node->datatype)166 {167 case STAT_DT_INT:168 node->total.int_total = 0;169 node->minvalue.int_min = INT_MAX2147483647;170 node->maxvalue.int_max = INT_MIN(-2147483647 -1);171 break;172 case STAT_DT_FLOAT:173 node->total.float_total = 0;174 node->minvalue.float_min = FLT_MAX3.40282347e+38F;175 node->maxvalue.float_max = FLT_MIN1.17549435e-38F;176 break;177 }178 node->st_flags = 0;179 180 while (node->bh) {181 bucket = node->bh;182 node->bh = bucket->next;183 g_free(bucket);184 }185 node->bh = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));186 node->bt = node->bh;187 node->bcount = 0;188 node->max_burst = 0;189 node->burst_time = -1.0;190 191 if (node->children) {192 for (child = node->children; child; child = child->next )193 // Recursion is limited by proto.c checks194 reset_stat_node(child);195 }196}197 198/* reset the whole stats_tree */199extern void200stats_tree_reset(void *p)201{202 stats_tree *st = (stats_tree *)p;203 204 st->start = -1.0;205 st->elapsed = 0.0;206 st->now = - 1.0;207 208 reset_stat_node(&st->root);209}210 211extern void212stats_tree_reinit(void *p)213{214 stats_tree *st = (stats_tree *)p;215 stat_node *child;216 stat_node *next;217 218 for (child = st->root.children; child; child = next) {219 /* child->next will be gone after free_stat_node, so cache it here */220 next = child->next;221 free_stat_node(child);222 }223 224 st->root.children = NULL((void*)0);225 st->root.counter = 0;226 switch (st->root.datatype)227 {228 case STAT_DT_INT:229 st->root.total.int_total = 0;230 st->root.minvalue.int_min = INT_MAX2147483647;231 st->root.maxvalue.int_max = INT_MIN(-2147483647 -1);232 break;233 case STAT_DT_FLOAT:234 st->root.total.float_total = 0;235 st->root.minvalue.float_min = FLT_MAX3.40282347e+38F;236 st->root.maxvalue.float_max = FLT_MIN1.17549435e-38F;237 break;238 }239 st->root.st_flags = 0;240 241 st->root.bh = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));242 st->root.bt = st->root.bh;243 st->root.bcount = 0;244 st->root.max_burst = 0;245 st->root.burst_time = -1.0;246 247 /* No more stat_nodes left in tree - clean out hash, array */248 g_hash_table_remove_all(st->names);249 if (st->parents->len>1) {250 g_ptr_array_remove_range(st->parents, 1, st->parents->len-1);251 }252 253 /* Do not update st_flags for the tree (sorting) - leave as was */254 st->num_columns = N_COLUMNS;255 g_free(st->display_name);256 st->display_name = stats_tree_get_displayname(st->cfg->path);257 258 if (st->cfg->init) {259 st->cfg->init(st);260 }261}262 263static void264stats_tree_free_configuration(void *p)265{266 stats_tree_cfg* cfg = (stats_tree_cfg*)p;267 g_free(cfg->tapname);268 g_free(cfg->abbr);269 g_free(cfg->path);270 g_free(cfg->title);271 g_free(cfg->first_column_name);272 g_free(cfg);273}274 275/* register a new stats_tree */276extern stats_tree_cfg *277stats_tree_register(const char *tapname, const char *abbr, const char *path,278 unsigned flags,279 stat_tree_packet_cb packet, stat_tree_init_cb init,280 stat_tree_cleanup_cb cleanup)281{282 stats_tree_cfg *cfg = g_new0(stats_tree_cfg, 1)((stats_tree_cfg *) g_malloc0_n ((1), sizeof (stats_tree_cfg)
))
;283 284 /* at the very least the abbrev and the packet function should be given */285 ws_assert( tapname && abbr && packet )do { if ((1) && !(tapname && abbr && packet
)) ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c"
, 285, __func__, "assertion failed: %s", "tapname && abbr && packet"
); } while (0)
;286 287 cfg->tapname = g_strdup(tapname);288 cfg->abbr = g_strdup(abbr);289 cfg->path = path ? g_strdup(path) : g_strdup(abbr);290 cfg->stat_group = REGISTER_PACKET_STAT_GROUP_UNSORTED;291 292 GString *title_str = g_string_new("");293 char **split = g_strsplit(path, STATS_TREE_MENU_SEPARATOR"//", 0);294 const char *sep = "";295 for (size_t idx = 0; split[idx]; idx++) {296 g_string_append_printf(title_str, "%s%s", sep, g_strstrip(split[idx])g_strchomp (g_strchug (split[idx])));297 sep = " / ";298 }299 g_strfreev(split);300 cfg->title = g_string_free(title_str, false0);301 302 cfg->packet = packet;303 cfg->init = init;304 cfg->cleanup = cleanup;305 306 cfg->flags = flags&~ST_FLG_MASK(0x10000000|0x20000000|0x01000000| 0x00400000|0x00800000|0x000F0000
)
;307 cfg->st_flags = flags&ST_FLG_MASK(0x10000000|0x20000000|0x01000000| 0x00400000|0x00800000|0x000F0000
)
;308 309 if (!registry) registry = g_hash_table_new_full(g_str_hash,g_str_equal,NULL((void*)0),stats_tree_free_configuration);310 311 g_hash_table_insert(registry,cfg->abbr,cfg);312 313 return cfg;314}315 316/* register a new stat_tree with default group REGISTER_PACKET_STAT_GROUP_UNSORTED from a plugin */317extern stats_tree_cfg *318stats_tree_register_plugin(const char *tapname, const char *abbr, const char *path,319 unsigned flags,320 stat_tree_packet_cb packet, stat_tree_init_cb init,321 stat_tree_cleanup_cb cleanup)322{323 stats_tree_cfg *cfg = stats_tree_register(tapname, abbr, path,324 flags, packet, init, cleanup);325 cfg->plugin = true1;326 327 return cfg;328}329 330extern void331stats_tree_set_group(stats_tree_cfg *st_config, register_stat_group_t stat_group) {332 if (st_config) {333 st_config->stat_group = stat_group;334 }335}336 337extern void338stats_tree_set_first_column_name(stats_tree_cfg *st_config, const char *column_name) {339 if (st_config) {340 st_config->first_column_name = g_strdup(column_name);341 }342}343 344extern stats_tree*345stats_tree_new(stats_tree_cfg *cfg, tree_pres *pr, const char *filter)346{347 stats_tree *st = g_new0(stats_tree, 1)((stats_tree *) g_malloc0_n ((1), sizeof (stats_tree)));348 349 st->cfg = cfg;350 st->pr = pr;351 352 st->names = g_hash_table_new(g_str_hash,g_str_equal);353 st->parents = g_ptr_array_new();354 st->filter = g_strdup(filter);355 356 st->start = -1.0;357 st->elapsed = 0.0;358 359 switch (st->root.datatype)360 {361 case STAT_DT_INT:362 st->root.minvalue.int_min = INT_MAX2147483647;363 st->root.maxvalue.int_max = INT_MIN(-2147483647 -1);364 break;365 case STAT_DT_FLOAT:366 st->root.minvalue.float_min = FLT_MAX3.40282347e+38F;367 st->root.maxvalue.float_max = FLT_MIN1.17549435e-38F;368 break;369 }370 371 st->root.bh = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));372 st->root.bt = st->root.bh;373 st->root.burst_time = -1.0;374 375 st->root.name = stats_tree_get_displayname(cfg->path);376 st->root.st = st;377 378 st->st_flags = st->cfg->st_flags;379 380 if (!(st->st_flags&ST_FLG_SRTCOL_MASK0x000F0000)) {381 /* No default sort specified - use preferences */382 st->st_flags |= prefs.st_sort_defcolflag<<ST_FLG_SRTCOL_SHIFT16;383 if (prefs.st_sort_defdescending) {384 st->st_flags |= ST_FLG_SORT_DESC0x00800000;385 }386 }387 st->num_columns = N_COLUMNS;388 st->display_name = stats_tree_get_displayname(st->cfg->path);389 390 g_ptr_array_add(st->parents,&st->root);391 392 return st;393}394 395/* will be the tap packet cb */396extern tap_packet_status397stats_tree_packet(void *p, packet_info *pinfo, epan_dissect_t *edt, const void *pri, tap_flags_t flags)398{399 stats_tree *st = (stats_tree *)p;400 401 st->now = nstime_to_msec(&pinfo->rel_ts);402 if (st->start < 0.0) st->start = st->now;403 404 st->elapsed = st->now - st->start;405 406 if (st->cfg->packet)407 return st->cfg->packet(st,pinfo,edt,pri, flags);408 else409 return TAP_PACKET_DONT_REDRAW;410}411 412extern stats_tree_cfg*413stats_tree_get_cfg_by_abbr(const char *abbr)414{415 if (!abbr) return NULL((void*)0);416 return (stats_tree_cfg *)g_hash_table_lookup(registry,abbr);417}418 419static int420compare_stat_menu_item(gconstpointer stat_a, gconstpointer stat_b)421{422 const stats_tree_cfg* stat_cfg_a = (const stats_tree_cfg*)stat_a;423 const stats_tree_cfg* stat_cfg_b = (const stats_tree_cfg*)stat_b;424 425 return strcmp(stat_cfg_a->path, stat_cfg_b->path);426}427 428extern GList*429stats_tree_get_cfg_list(void)430{431 GList* registry_list = g_hash_table_get_values(registry);432 /* Now sort the list so they can show up in the433 menu alphabetically */434 return g_list_sort(registry_list, compare_stat_menu_item);435 436}437 438struct _stats_tree_pres_cbs {439 void (*setup_node_pr)(stat_node*);440 void (*free_tree_pr)(stats_tree*);441};442 443static void444setup_tree_presentation(void *k _U___attribute__((unused)), void *v, void *p)445{446 stats_tree_cfg *cfg = (stats_tree_cfg *)v;447 struct _stats_tree_pres_cbs *d = (struct _stats_tree_pres_cbs *)p;448 449 cfg->setup_node_pr = d->setup_node_pr;450 cfg->free_tree_pr = d->free_tree_pr;451 452}453 454extern void455stats_tree_presentation(void (*registry_iterator)(void *,void *,void *),456 void (*setup_node_pr)(stat_node*),457 void (*free_tree_pr)(stats_tree*),458 void *data)459{460 static struct _stats_tree_pres_cbs d;461 462 d.setup_node_pr = setup_node_pr;463 d.free_tree_pr = free_tree_pr;464 465 if (registry) g_hash_table_foreach(registry,setup_tree_presentation,&d);466 467 if (registry_iterator && registry)468 g_hash_table_foreach(registry,registry_iterator,data);469 470}471 472 473/* creates a stat_tree node474* name: the name of the stats_tree node475* parent_name: the name of the ALREADY REGISTERED parent476* with_hash: whether or not it should keep a hash with its children names477* as_named_node: whether or not it has to be registered in the root namespace478*/479static stat_node*480new_stat_node(stats_tree *st, const char *name, int parent_id, stat_node_datatype datatype,481 bool_Bool with_hash, bool_Bool as_parent_node)482{483 484 stat_node *node = g_new0(stat_node, 1)((stat_node *) g_malloc0_n ((1), sizeof (stat_node)));485 stat_node *last_chld = NULL((void*)0);486 487 node->datatype = datatype;488 switch (datatype)

24

Control jumps to 'case STAT_DT_INT:' at line 490

489 {490 case STAT_DT_INT:491 node->minvalue.int_min = INT_MAX2147483647;492 node->maxvalue.int_max = INT_MIN(-2147483647 -1);493 break;494 case STAT_DT_FLOAT:495 node->minvalue.float_min = FLT_MAX3.40282347e+38F;496 node->maxvalue.float_max = FLT_MIN1.17549435e-38F;497 break;498 }499 node->st_flags = parent_id?0:ST_FLG_ROOTCHILD0x20000000;

25

Assuming 'parent_id' is 0

26

'?' condition is false

500 501 node->bh = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));

27

Null pointer value stored to field 'next'

502 node->bt = node->bh;503 node->burst_time = -1.0;504 505 node->name = g_strdup(name);506 node->st = st;507 node->hash = with_hash

27.1

'with_hash' is false
? g_hash_table_new(g_str_hash,g_str_equal) : NULL((void*)0);

28

'?' condition is false

508 509 if (as_parent_node

28.1

'as_parent_node' is false
) {

29

Taking false branch

510 g_hash_table_insert(st->names,511 node->name,512 node);513 514 g_ptr_array_add(st->parents,node);515 516 node->id = st->parents->len - 1;517 } else {518 node->id = -1;519 }520 521 if (parent_id

29.1

'parent_id' is >= 0
>= 0 && parent_id

29.2

'parent_id' is < field 'len'
< (int) st->parents->len ) {

30

Taking true branch

522 node->parent = (stat_node *)g_ptr_array_index(st->parents,parent_id)((st->parents)->pdata)[parent_id];523 } else {524 /* ??? should we set the parent to be root ??? */525 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 525
, __func__, "assertion \"not reached\" failed")
;526 }527 528 if (node->parent->children) {

31

Assuming field 'children' is null

32

Taking false branch

529 /* insert as last child */530 531 for (last_chld = node->parent->children;532 last_chld->next;533 last_chld = last_chld->next ) ;534 535 last_chld->next = node;536 537 } else {538 /* insert as first child */539 node->parent->children = node;540 }541 542 if(node->parent->hash) {

33

Assuming field 'hash' is null

34

Taking false branch

543 g_hash_table_replace(node->parent->hash,node->name,node);544 }545 546 if (st->cfg->setup_node_pr) {

35

Assuming field 'setup_node_pr' is null

36

Taking false branch

547 st->cfg->setup_node_pr(node);548 } else {549 node->pr = NULL((void*)0);550 }551 552 return node;553}554/***/555 556extern int557stats_tree_create_node(stats_tree *st, const char *name, int parent_id, stat_node_datatype datatype, bool_Bool with_hash)558{559 stat_node *node = new_stat_node(st,name,parent_id,datatype,with_hash,true1);560 561 if (node)562 return node->id;563 else564 return 0;565}566 567/* XXX: should this be a macro? */568extern int569stats_tree_create_node_by_pname(stats_tree *st, const char *name,570 const char *parent_name, stat_node_datatype datatype, bool_Bool with_children)571{572 return stats_tree_create_node(st,name,stats_tree_parent_id_by_name(st,parent_name),datatype,with_children);573}574 575/* Internal function to update the burst calculation data - add entry to bucket */576static void577update_burst_calc(stat_node *node, int value)578{579 double current_bucket;580 double burstwin;581 582 burst_bucket *bn;583 584 if (!prefs.st_enable_burstinfo

39.1

Field 'st_enable_burstinfo' is true
) {

2

Assuming field 'st_enable_burstinfo' is true

3

Taking false branch

40

Taking false branch

585 return;586 }587 588 /* NB thebucket list should always contain at least one node - even if it is */589 /* the dummy created at init time. Head and tail should never be NULL! */590 current_bucket = floor(node->st->now/prefs.st_burst_resolution);591 burstwin = prefs.st_burst_windowlen/prefs.st_burst_resolution;592 if (current_bucket>node->bt->bucket_no) {

4

Assuming 'current_bucket' is <= field 'bucket_no'

5

Taking false branch

41

Assuming 'current_bucket' is <= field 'bucket_no'

42

Taking false branch

593 /* Must add a new bucket at the burst list tail */594 bn = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));595 bn->count = value;596 bn->bucket_no = current_bucket;597 bn->start_time = node->st->now;598 bn->prev = node->bt;599 node->bt->next = bn;600 node->bt = bn;601 /* And add value to the current burst count for node */602 node->bcount += value;603 /* Check if bucket list head is now too old and must be removed */604 while (current_bucket>=(node->bh->bucket_no+burstwin)) {605 /* off with its head! */606 bn = node->bh;607 node->bh = bn->next;608 node->bh->prev = NULL((void*)0);609 node->bcount -= bn->count;610 g_free(bn);611 }612 }613 else if (current_bucket<node->bh->bucket_no) {

6

Assuming 'current_bucket' is >= field 'bucket_no'

7

Taking false branch

43

Assuming 'current_bucket' is >= field 'bucket_no'

44

Taking false branch

614 /* Packet must be added at head of burst list - check if not too old */615 if ((current_bucket+burstwin)>node->bt->bucket_no) {616 /* packet still within the window */617 bn = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));618 bn->count = value;619 bn->bucket_no = current_bucket;620 bn->start_time = node->st->now;621 bn->next = node->bh;622 node->bh->prev = bn;623 node->bh = bn;624 /* And add value to the current burst count for node */625 node->bcount += value;626 }627 }628 else629 {630 /* Somewhere in the middle... */631 burst_bucket *search = node->bt;632 while (current_bucket<search->bucket_no) {

8

Loop condition is false. Execution continues on line 635

45

Loop condition is false. Execution continues on line 635

633 search = search->prev;634 }635 if (current_bucket==search->bucket_no) {

9

Assuming 'current_bucket' is not equal to field 'bucket_no'

10

Taking false branch

46

Assuming 'current_bucket' is not equal to field 'bucket_no'

47

Taking false branch

636 /* found existing bucket, increase value */637 search->count += value;638 if (search->start_time>node->st->now) {639 search->start_time = node->st->now;640 }641 }642 else {643 /* must add a new bucket after bn. */644 bn = g_new0(burst_bucket, 1)((burst_bucket *) g_malloc0_n ((1), sizeof (burst_bucket)));645 bn->count = value;646 bn->bucket_no = current_bucket;647 bn->start_time = node->st->now;648 bn->prev = search;649 bn->next = search->next;

48

Null pointer value stored to field 'next'

650 search->next = bn;651 bn->next->prev = bn;

49

Access to field 'prev' results in a dereference of a null pointer (loaded from field 'next')
652 }653 node->bcount += value;654 }655 if (node->bcount>node->max_burst) {

11

Assuming field 'bcount' is <= field 'max_burst'

12

Taking false branch

656 /* new record burst */657 node->max_burst = node->bcount;658 node->burst_time = node->bh->start_time;659 }660}661 662/*663 * Increases by delta the counter of the node whose name is given664 * if the node does not exist yet it's created (with counter=1)665 * using parent_name as parent node.666 * with_hash=true to indicate that the created node will have a parent667 */668int669stats_tree_manip_node_int(manip_node_mode mode, stats_tree *st, const char *name,670 int parent_id, bool_Bool with_hash, int value)671{672 stat_node *node = NULL((void*)0);673 stat_node *parent = NULL((void*)0);674 675 ws_assert( parent_id >= 0 && parent_id < (int) st->parents->len )do { if ((1) && !(parent_id >= 0 && parent_id
< (int) st->parents->len)) ws_log_fatal_full("", LOG_LEVEL_ERROR
, "epan/stats_tree.c", 675, __func__, "assertion failed: %s",
"parent_id >= 0 && parent_id < (int) st->parents->len"
); } while (0)
;

15

Assuming 'parent_id' is >= 0

16

Assuming 'parent_id' is < field 'len'

17

Taking false branch

18

Loop condition is false. Exiting loop

676 677 parent = (stat_node *)g_ptr_array_index(st->parents,parent_id)((st->parents)->pdata)[parent_id];678 679 if( parent->hash ) {

19

Assuming field 'hash' is null

20

Taking false branch

680 node = (stat_node *)g_hash_table_lookup(parent->hash,name);681 } else {682 node = (stat_node *)g_hash_table_lookup(st->names,name);683 }684 685 if ( node == NULL((void*)0) )

21

Assuming 'node' is equal to NULL

22

Taking true branch

686 node = new_stat_node(st,name,parent_id,STAT_DT_INT,with_hash,with_hash);

23

Calling 'new_stat_node'

37

Returning from 'new_stat_node'

687 688 switch (mode) {

38

Control jumps to 'case MN_INCREASE:' at line 689

689 case MN_INCREASE:690 node->counter += value;691 update_burst_calc(node, value);

39

Calling 'update_burst_calc'

692 break;693 case MN_SET:694 node->counter = value;695 break;696 case MN_AVERAGE:697 node->counter++;698 update_burst_calc(node, 1);699 /* fall through */ /*to average code */700 case MN_AVERAGE_NOTICK:701 node->total.int_total += value;702 if (node->minvalue.int_min > value) {703 node->minvalue.int_min = value;704 }705 if (node->maxvalue.int_max < value) {706 node->maxvalue.int_max = value;707 }708 node->st_flags |= ST_FLG_AVERAGE0x10000000;709 break;710 case MN_SET_FLAGS:711 node->st_flags |= value;712 break;713 case MN_CLEAR_FLAGS:714 node->st_flags &= ~value;715 break;716 }717 718 if (node)719 return node->id;720 else721 return -1;722}723 724/*725* Increases by delta the counter of the node whose name is given726* if the node does not exist yet it's created (with counter=1)727* using parent_name as parent node.728* with_hash=true to indicate that the created node will have a parent729*/730int731stats_tree_manip_node_float(manip_node_mode mode, stats_tree *st, const char *name,732 int parent_id, bool_Bool with_hash, float value)733{734 stat_node *node = NULL((void*)0);735 stat_node *parent = NULL((void*)0);736 737 ws_assert(parent_id >= 0 && parent_id < (int)st->parents->len)do { if ((1) && !(parent_id >= 0 && parent_id
< (int)st->parents->len)) ws_log_fatal_full("", LOG_LEVEL_ERROR
, "epan/stats_tree.c", 737, __func__, "assertion failed: %s",
"parent_id >= 0 && parent_id < (int)st->parents->len"
); } while (0)
;738 739 parent = (stat_node *)g_ptr_array_index(st->parents, parent_id)((st->parents)->pdata)[parent_id];740 741 if (parent->hash) {742 node = (stat_node *)g_hash_table_lookup(parent->hash, name);743 }744 else {745 node = (stat_node *)g_hash_table_lookup(st->names, name);746 }747 748 if (node == NULL((void*)0))749 node = new_stat_node(st, name, parent_id, STAT_DT_FLOAT, with_hash, with_hash);750 751 switch (mode) {752 case MN_AVERAGE:753 node->counter++;754 update_burst_calc(node, 1);755 /* fall through */ /*to average code */756 case MN_AVERAGE_NOTICK:757 node->total.float_total += value;758 if (node->minvalue.float_min > value) {759 node->minvalue.float_min = value;760 }761 if (node->maxvalue.float_max < value) {762 node->maxvalue.float_max = value;763 }764 node->st_flags |= ST_FLG_AVERAGE0x10000000;765 break;766 default:767 //only average is currently supported768 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 768
, __func__, "assertion \"not reached\" failed")
;769 break;770 }771 772 if (node)773 return node->id;774 else775 return -1;776}777 778extern char*779stats_tree_get_abbr(const char *opt_arg)780{781 unsigned i;782 783 /* XXX: this fails when tshark is given any options784 after the -z */785 ws_assert(opt_arg != NULL)do { if ((1) && !(opt_arg != ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 785, __func__, "assertion failed: %s"
, "opt_arg != ((void*)0)"); } while (0)
;786 787 for (i=0; opt_arg[i] && opt_arg[i] != ','; i++);788 789 if (opt_arg[i] == ',') {790 return g_strndup(opt_arg,i);791 } else {792 return NULL((void*)0);793 }794}795 796 797/*798 * This function accepts an input string which should define a long integer range.799 * The normal result is a struct containing the floor and ceil value of this800 * range.801 *802 * It is allowed to define a range string in the following ways :803 *804 * "0-10" -> { 0, 10 }805 * "-0" -> { INT_MIN, 0 }806 * "0-" -> { 0, INT_MAX }807 * "-" -> { INT_MIN, INT_MAX }808 *809 * Note that this function is robust to buggy input string. If in some cases it810 * returns NULL, it but may also return a pair with undefined values.811 *812 */813static range_pair_t*814get_range(char *rngstr)815{816 char **split;817 range_pair_t *rng;818 819 split = g_strsplit((char*)rngstr,"-",2);820 821 /* empty string */822 if (split[0] == NULL((void*)0)) {823 g_strfreev(split);824 return NULL((void*)0);825 }826 827 rng = g_new(range_pair_t, 1)((range_pair_t *) g_malloc_n ((1), sizeof (range_pair_t)));828 829 if (split[1] == NULL((void*)0)) {830 /* means we have a non empty string with no delimiter831 * so it must be a single number */832 rng->floor = (int)strtol(split[0],NULL((void*)0),10);833 rng->ceil = rng->floor;834 } else {835 /* string == "X-?" */836 if (*(split[0]) != '\0') {837 rng->floor = (int)strtol(split[0],NULL((void*)0),10);838 } else {839 /* string == "-?" */840 rng->floor = INT_MIN(-2147483647 -1);841 }842 843 /* string != "?-" */844 if (*(split[1]) != '\0') {845 rng->ceil = (int)strtol(split[1],NULL((void*)0),10);846 } else {847 /* string == "?-" */848 rng->ceil = INT_MAX2147483647;849 }850 }851 g_strfreev(split);852 853 return rng;854}855 856 857extern int858stats_tree_create_range_node(stats_tree *st, const char *name, int parent_id, ...)859{860 va_list list;861 char *curr_range;862 stat_node *rng_root = new_stat_node(st, name, parent_id, STAT_DT_INT, false0, true1);863 stat_node *range_node = NULL((void*)0);864 865 va_start( list, parent_id )__builtin_va_start(list, parent_id);866 while (( curr_range = va_arg(list, char*)__builtin_va_arg(list, char*) )) {867 range_node = new_stat_node(st, curr_range, rng_root->id, STAT_DT_INT, false0, false0);868 range_node->rng = get_range(curr_range);869 }870 va_end( list )__builtin_va_end(list);871 872 return rng_root->id;873}874 875extern int876stats_tree_create_range_node_string(stats_tree *st, const char *name,877 int parent_id, int num_str_ranges,878 char** str_ranges)879{880 int i;881 stat_node *rng_root = new_stat_node(st, name, parent_id, STAT_DT_INT, false0, true1);882 stat_node *range_node = NULL((void*)0);883 884 for (i = 0; i < num_str_ranges - 1; i++) {885 range_node = new_stat_node(st, str_ranges[i], rng_root->id, STAT_DT_INT, false0, false0);886 range_node->rng = get_range(str_ranges[i]);887 }888 range_node = new_stat_node(st, str_ranges[i], rng_root->id, STAT_DT_INT, false0, false0);889 range_node->rng = get_range(str_ranges[i]);890 if (range_node->rng->floor == range_node->rng->ceil) {891 range_node->rng->ceil = INT_MAX2147483647;892 }893 894 return rng_root->id;895}896 897/****/898extern int899stats_tree_parent_id_by_name(stats_tree *st, const char *parent_name)900{901 stat_node *node = (stat_node *)g_hash_table_lookup(st->names,parent_name);902 903 if (node)904 return node->id;905 else906 return 0; /* XXX: this is the root should we return -1 instead?*/907}908 909 910extern int911stats_tree_range_node_with_pname(stats_tree *st, const char *name,912 const char *parent_name, ...)913{914 va_list list;915 char *curr_range;916 stat_node *range_node = NULL((void*)0);917 int parent_id = stats_tree_parent_id_by_name(st,parent_name);918 stat_node *rng_root = new_stat_node(st, name, parent_id, STAT_DT_INT, false0, true1);919 920 va_start( list, parent_name )__builtin_va_start(list, parent_name);921 while (( curr_range = va_arg(list, char*)__builtin_va_arg(list, char*) )) {922 range_node = new_stat_node(st, curr_range, rng_root->id, STAT_DT_INT, false0, false0);923 range_node->rng = get_range(curr_range);924 }925 va_end( list )__builtin_va_end(list);926 927 return rng_root->id;928}929 930 931extern int932stats_tree_tick_range(stats_tree *st, const char *name, int parent_id,933 int value_in_range)934{935 936 stat_node *node = NULL((void*)0);937 stat_node *parent = NULL((void*)0);938 stat_node *child = NULL((void*)0);939 int stat_floor, stat_ceil;940 941 if (parent_id >= 0 && parent_id < (int) st->parents->len) {942 parent = (stat_node *)g_ptr_array_index(st->parents,parent_id)((st->parents)->pdata)[parent_id];943 } else {944 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 944
, __func__, "assertion \"not reached\" failed")
;945 }946 947 if( parent->hash ) {948 node = (stat_node *)g_hash_table_lookup(parent->hash,name);949 } else {950 node = (stat_node *)g_hash_table_lookup(st->names,name);951 }952 953 if ( node == NULL((void*)0) )954 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 954
, __func__, "assertion \"not reached\" failed")
;955 956 /* update stats for container node. counter should already be ticked so we only update total and min/max */957 node->total.int_total += value_in_range;958 if (node->minvalue.int_min > value_in_range) {959 node->minvalue.int_min = value_in_range;960 }961 if (node->maxvalue.int_max < value_in_range) {962 node->maxvalue.int_max = value_in_range;963 }964 node->st_flags |= ST_FLG_AVERAGE0x10000000;965 966 for ( child = node->children; child; child = child->next) {967 stat_floor = child->rng->floor;968 stat_ceil = child->rng->ceil;969 970 if ( value_in_range >= stat_floor && value_in_range <= stat_ceil ) {971 child->counter++;972 child->total.int_total += value_in_range;973 if (child->minvalue.int_min > value_in_range) {974 child->minvalue.int_min = value_in_range;975 }976 if (child->maxvalue.int_max < value_in_range) {977 child->maxvalue.int_max = value_in_range;978 }979 child->st_flags |= ST_FLG_AVERAGE0x10000000;980 update_burst_calc(child, 1);981 return node->id;982 }983 }984 985 return node->id;986}987 988extern int989stats_tree_create_pivot(stats_tree *st, const char *name, int parent_id)990{991 stat_node *node = new_stat_node(st,name,parent_id,STAT_DT_INT,true1,true1);992 993 if (node)994 return node->id;995 else996 return 0;997}998 999extern int1000stats_tree_create_pivot_by_pname(stats_tree *st, const char *name,1001 const char *parent_name)1002{1003 int parent_id = stats_tree_parent_id_by_name(st,parent_name);1004 stat_node *node;1005 1006 node = new_stat_node(st,name,parent_id,STAT_DT_INT,true1,true1);1007 1008 if (node)1009 return node->id;1010 else1011 return 0;1012}1013 1014extern int1015stats_tree_tick_pivot(stats_tree *st, int pivot_id, const char *pivot_value)1016{1017 stat_node *parent = (stat_node *)g_ptr_array_index(st->parents,pivot_id)((st->parents)->pdata)[pivot_id];1018 1019 parent->counter++;1020 update_burst_calc(parent, 1);

1

Calling 'update_burst_calc'

13

Returning from 'update_burst_calc'

1021 stats_tree_manip_node_int( MN_INCREASE, st, pivot_value, pivot_id, false0, 1);

14

Calling 'stats_tree_manip_node_int'

1022 1023 return pivot_id;1024}1025 1026extern char*1027stats_tree_get_displayname (char* fullname)1028{1029 char *buf = g_strdup(fullname);1030 char *sep;1031 1032 if (prefs.st_sort_showfullname) {1033 return buf; /* unmodified */1034 }1035 1036 sep = buf;1037 while ((sep = strchr(sep,'/')) != NULL((void*)0)) {1038 if (*(++sep)=='/') { /* escaped slash - two slash characters after each other */1039 memmove(sep,sep+1,strlen(sep));1040 }1041 else {1042 /* we got a new path separator */1043 memmove(buf,sep,strlen(sep)+1);1044 sep = buf;1045 }1046 }1047 1048 return buf;1049}1050 1051extern int1052stats_tree_get_default_sort_col (stats_tree *st)1053{1054 switch ((st->st_flags&ST_FLG_SRTCOL_MASK0x000F0000)>>ST_FLG_SRTCOL_SHIFT16) {1055 case ST_SORT_COL_NAME1:1056 return COL_NAME;1057 case ST_SORT_COL_COUNT2:1058 return COL_COUNT;1059 case ST_SORT_COL_AVG3:1060 return COL_AVERAGE;1061 case ST_SORT_COL_MIN4:1062 return COL_MIN;1063 case ST_SORT_COL_MAX5:1064 return COL_MAX;1065 case ST_SORT_COL_BURSTRATE6:1066 return COL_BURSTRATE;1067 }1068 return COL_COUNT; /* nothing specific set */1069}1070 1071extern bool_Bool1072stats_tree_is_default_sort_DESC (stats_tree *st)1073{1074 return st->st_flags&ST_FLG_SORT_DESC0x00800000;1075}1076 1077extern const char*1078stats_tree_get_column_name (stats_tree_cfg *st_config, int col_index)1079{1080 switch (col_index) {1081 case COL_NAME:1082 if (st_config->first_column_name) {1083 return st_config->first_column_name;1084 }1085 return "Topic / Item";1086 case COL_COUNT:1087 return "Count";1088 case COL_AVERAGE:1089 return "Average";1090 case COL_MIN:1091 return "Min Val";1092 case COL_MAX:1093 return "Max Val";1094 case COL_RATE:1095 return "Rate (ms)";1096 case COL_PERCENT:1097 return "Percent";1098 case COL_BURSTRATE:1099 return prefs.st_burst_showcount ? "Burst Count" : "Burst Rate";1100 case COL_BURSTTIME:1101 return "Burst Start";1102 default:1103 return "(Unknown)";1104 }1105}1106 1107extern int1108stats_tree_get_column_size (int col_index)1109{1110 if (col_index==COL_NAME) {1111 return 36; /* but caller should really call stats_tree_branch_max_namelen() */1112 }1113 if (col_index<N_COLUMNS) {1114 return 12; /* all numerical values are this size */1115 }1116 return 0; /* invalid column */1117}1118 1119extern char**1120stats_tree_get_values_from_node (const stat_node* node)1121{1122 char **values = (char**) g_malloc0(sizeof(char*)*(node->st->num_columns));1123 1124 values[COL_NAME] = (node->st_flags&ST_FLG_ROOTCHILD0x20000000)?stats_tree_get_displayname(node->name):g_strdup(node->name);1125 values[COL_COUNT] = ws_strdup_printf("%u",node->counter)wmem_strdup_printf(((void*)0), "%u",node->counter);1126 if (((node->st_flags&ST_FLG_AVERAGE0x10000000) || node->rng)) {1127 if (node->counter) {1128 switch (node->datatype)1129 {1130 case STAT_DT_INT:1131 values[COL_AVERAGE] = ws_strdup_printf("%.2f", ((float)node->total.int_total) / node->counter)wmem_strdup_printf(((void*)0), "%.2f", ((float)node->total
.int_total) / node->counter)
;1132 break;1133 case STAT_DT_FLOAT:1134 values[COL_AVERAGE] = ws_strdup_printf("%.2f", node->total.float_total / node->counter)wmem_strdup_printf(((void*)0), "%.2f", node->total.float_total
/ node->counter)
;1135 break;1136 }1137 } else {1138 values[COL_AVERAGE] = g_strdup("-");1139 }1140 } else {1141 values[COL_AVERAGE] = g_strdup("");1142 }1143 1144 if (((node->st_flags&ST_FLG_AVERAGE0x10000000) || node->rng)) {1145 if (node->counter) {1146 switch (node->datatype)1147 {1148 case STAT_DT_INT:1149 values[COL_MIN] = ws_strdup_printf("%d", node->minvalue.int_min)wmem_strdup_printf(((void*)0), "%d", node->minvalue.int_min
)
;1150 break;1151 case STAT_DT_FLOAT:1152 values[COL_MIN] = ws_strdup_printf("%f", node->minvalue.float_min)wmem_strdup_printf(((void*)0), "%f", node->minvalue.float_min
)
;1153 break;1154 }1155 }1156 else {1157 values[COL_MIN] = g_strdup("-");1158 }1159 }1160 else {1161 values[COL_MIN] = g_strdup("");1162 }1163 1164 if (((node->st_flags&ST_FLG_AVERAGE0x10000000) || node->rng)) {1165 if (node->counter) {1166 switch (node->datatype)1167 {1168 case STAT_DT_INT:1169 values[COL_MAX] = ws_strdup_printf("%d", node->maxvalue.int_max)wmem_strdup_printf(((void*)0), "%d", node->maxvalue.int_max
)
;1170 break;1171 case STAT_DT_FLOAT:1172 values[COL_MAX] = ws_strdup_printf("%f", node->maxvalue.float_max)wmem_strdup_printf(((void*)0), "%f", node->maxvalue.float_max
)
;1173 break;1174 }1175 }1176 else {1177 values[COL_MAX] = g_strdup("-");1178 }1179 }1180 else {1181 values[COL_MAX] = g_strdup("");1182 }1183 1184 values[COL_RATE] = (node->st->elapsed)?ws_strdup_printf("%.4f",((float)node->counter)/node->st->elapsed)wmem_strdup_printf(((void*)0), "%.4f",((float)node->counter
)/node->st->elapsed)
:g_strdup("");1185 values[COL_PERCENT] = ((node->parent)&&(node->parent->counter))?1186 ws_strdup_printf("%.2f%%",(node->counter*100.0)/node->parent->counter)wmem_strdup_printf(((void*)0), "%.2f%%",(node->counter*100.0
)/node->parent->counter)
:1187 (node->parent==&(node->st->root)?g_strdup("100%"):g_strdup(""));1188 if (node->st->num_columns>COL_BURSTTIME) {1189 values[COL_BURSTRATE] = (!prefs.st_enable_burstinfo)?g_strdup(""):1190 (node->max_burst?(prefs.st_burst_showcount?1191 ws_strdup_printf("%d",node->max_burst)wmem_strdup_printf(((void*)0), "%d",node->max_burst):1192 ws_strdup_printf("%.4f",((double)node->max_burst)/prefs.st_burst_windowlen)wmem_strdup_printf(((void*)0), "%.4f",((double)node->max_burst
)/prefs.st_burst_windowlen)
):1193 g_strdup("-"));1194 values[COL_BURSTTIME] = (!prefs.st_enable_burstinfo)?g_strdup(""):1195 (node->max_burst?ws_strdup_printf("%.3f",(node->burst_time/1000.0))wmem_strdup_printf(((void*)0), "%.3f",(node->burst_time/1000.0
))
:g_strdup("-"));1196 }1197 return values;1198}1199 1200extern int1201stats_tree_sort_compare (const stat_node *a, const stat_node *b, int sort_column,1202 bool_Bool sort_descending)1203{1204 int result = 0;1205 float avg_a = 0, avg_b = 0;1206 1207 if (prefs.st_sort_rng_nameonly&&(a->rng&&b->rng)) {1208 /* always sort ranges by range name */1209 result = a->rng->floor - b->rng->floor;1210 if (sort_descending&&(!prefs.st_sort_rng_fixorder)) {1211 result = -result;1212 }1213 return result;1214 }1215 1216 switch (sort_column) {1217 case COL_NAME:1218 if (a->rng&&b->rng) {1219 result = a->rng->floor - b->rng->floor;1220 }1221 else if (prefs.st_sort_casesensitve) {1222 result = strcmp(a->name,b->name);1223 }1224 else {1225 result = g_ascii_strcasecmp(a->name,b->name);1226 }1227 break;1228 1229 case COL_RATE:1230 case COL_PERCENT:1231 case COL_COUNT:1232 result = a->counter - b->counter;1233 break;1234 1235 case COL_AVERAGE:1236 switch (a->datatype)1237 {1238 case STAT_DT_INT:1239 avg_a = a->counter ? ((float)a->total.int_total)/a->counter : 0;1240 avg_b = b->counter ? ((float)b->total.int_total)/b->counter : 0;1241 break;1242 case STAT_DT_FLOAT:1243 avg_a = a->counter ? ((float)a->total.float_total) / a->counter : 0;1244 avg_b = b->counter ? ((float)b->total.float_total) / b->counter : 0;1245 break;1246 }1247 result = (avg_a>avg_b) ? 1 : ( (avg_a<avg_b) ? -1 : 0);1248 break;1249 1250 case COL_MIN:1251 switch (a->datatype)1252 {1253 case STAT_DT_INT:1254 result = a->minvalue.int_min - b->minvalue.int_min;1255 break;1256 case STAT_DT_FLOAT:1257 result = (a->minvalue.float_min>b->minvalue.int_min) ? 1 : ((a->minvalue.float_min<b->minvalue.int_min) ? -1 : 0);1258 break;1259 }1260 break;1261 1262 case COL_MAX:1263 switch (a->datatype)1264 {1265 case STAT_DT_INT:1266 result = a->maxvalue.int_max - b->maxvalue.int_max;1267 break;1268 case STAT_DT_FLOAT:1269 result = (a->maxvalue.float_max>b->maxvalue.float_max) ? 1 : ((a->maxvalue.float_max<b->maxvalue.float_max) ? -1 : 0);1270 break;1271 }1272 break;1273 1274 case COL_BURSTRATE:1275 result = a->max_burst - b->max_burst;1276 break;1277 1278 case COL_BURSTTIME:1279 result = (a->burst_time>b->burst_time)?1:((a->burst_time<b->burst_time)?-1:0);1280 break;1281 1282 default:1283 /* no sort comparison found for column - must update this switch statement */1284 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/stats_tree.c", 1284
, __func__, "assertion \"not reached\" failed")
;1285 }1286 1287 /* break tie between items with same primary search result */1288 if (!result) {1289 if (sort_column==COL_NAME) {1290 result = a->counter - b->counter;1291 }1292 else {1293 if (a->rng&&b->rng) {1294 result = a->rng->floor - b->rng->floor;1295 }1296 else if (prefs.st_sort_casesensitve) {1297 result = strcmp(a->name,b->name);1298 }1299 else {1300 result = g_ascii_strcasecmp(a->name,b->name);1301 }1302 }1303 }1304 1305 /* take into account sort order */1306 if (sort_descending) {1307 result = -result;1308 }1309 1310 if ((a->st_flags&ST_FLG_SORT_TOP0x00400000)!=(b->st_flags&ST_FLG_SORT_TOP0x00400000)) {1311 /* different sort groups top vs non-top */1312 result = (a->st_flags&ST_FLG_SORT_TOP0x00400000)?-1:1;1313 }1314 return result;1315}1316 1317extern GString*1318stats_tree_format_as_str(const stats_tree* st, st_format_type format_type,1319 int sort_column, bool_Bool sort_descending)1320{1321 int maxnamelen = stats_tree_branch_max_namelen(&st->root,0);1322 stat_node *child;1323 GString *s;1324 int count;1325 char *separator = NULL((void*)0);1326 1327 switch(format_type) {1328 case ST_FORMAT_YAML:1329 s = g_string_new("---\n");1330 break;1331 case ST_FORMAT_XML:1332 s = g_string_new("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");1333 break;1334 case ST_FORMAT_CSV:1335 s = g_string_new("\"level\",\"parent\",");1336 for (count = 0; count<st->num_columns; count++) {1337 g_string_append_printf(s,"\"%s\",",stats_tree_get_column_name(st->cfg, count));1338 }1339 g_string_append (s,"\n");1340 break;1341 case ST_FORMAT_PLAIN:1342 {1343 char fmt[16];1344 int sep_length;1345 1346 sep_length = maxnamelen;1347 for (count = 1; count<st->num_columns; count++) {1348 sep_length += stats_tree_get_column_size(count)+2;1349 }1350 separator = (char *)g_malloc(sep_length+1);1351 memset (separator, '=', sep_length);1352 separator[sep_length] = 0;1353 1354 s = g_string_new("\n");1355 g_string_append(s,separator);1356 g_string_append_printf(s,"\n%s:\n",st->cfg->title);1357 snprintf (fmt,sizeof(fmt),"%%-%us",maxnamelen);1358 g_string_append_printf(s,fmt,stats_tree_get_column_name(st->cfg, 0));1359 for (count = 1; count<st->num_columns; count++) {1360 snprintf (fmt,sizeof(fmt)," %%-%ds",stats_tree_get_column_size(count)+1);1361 g_string_append_printf(s,fmt,stats_tree_get_column_name(st->cfg, count));1362 }1363 memset (separator, '-', sep_length);1364 g_string_append_printf(s,"\n%s\n",separator);1365 break;1366 }1367 default:1368 return g_string_new("unknown format for stats_tree\n");1369 }1370 1371 for (child = st->root.children; child; child = child->next ) {1372 stats_tree_format_node_as_str(child,s,format_type,0,"",maxnamelen,sort_column,sort_descending);1373 1374 }1375 1376 if (format_type==ST_FORMAT_PLAIN) {1377 g_string_append_printf(s,"\n%s\n",separator);1378 g_free(separator);1379 }1380 1381 return s;1382}1383 1384typedef struct {1385 int sort_column;1386 bool_Bool sort_descending;1387} sortinfo;1388 1389/* Function to compare elements for child array sort. a and b are children, user_data1390points to a st_flags value */1391extern int1392stat_node_array_sortcmp (gconstpointer a, gconstpointer b, void *user_data)1393{1394 /* user_data is *unsigned value to st_flags */1395 return stats_tree_sort_compare (*(const stat_node*const*)a,*(const stat_node*const*)b,1396 ((sortinfo*)user_data)->sort_column,((sortinfo*)user_data)->sort_descending);1397}1398 1399static char*1400clean_for_xml_tag (char *str)1401{1402 char *s = str;1403 while ((s=strpbrk(s,"!\"#$%%&'()*+,/;<=>?@[\\]^`{|}~ ")) != NULL((void*)0)) {1404 *(s++) = '-';1405 }1406 return str;1407}1408 1409/** helper function to add note to formatted stats_tree */1410// NOLINTNEXTLINE(misc-no-recursion)1411WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern void stats_tree_format_node_as_str(const stat_node *node,1412 GString *s,1413 st_format_type format_type,1414 unsigned indent,1415 const char *path,1416 int maxnamelen,1417 int sort_column,1418 bool_Bool sort_descending)1419{1420 int count;1421 int num_columns = node->st->num_columns;1422 char **values = stats_tree_get_values_from_node(node);1423 stat_node *child;1424 sortinfo si;1425 char *full_path;1426 char fmt[16] = "%s%s%s";1427 1428 switch(format_type) {1429 case ST_FORMAT_YAML:1430 if (indent) {1431 snprintf(fmt, sizeof(fmt), "%%%ds%%s%%s", indent*4-2);1432 }1433 g_string_append_printf(s, fmt, "", indent?"- ":"", "Description");1434 g_string_append_printf(s, ": \"%s\"\n", values[0]);1435 1436 for (count = 1; count<num_columns; count++) {1437 if (*values[count]) {1438 g_string_append_printf(s, fmt, "", indent?" ":"",1439 stats_tree_get_column_name(node->st->cfg, count));1440 g_string_append_printf(s, ": %s\n", values[count]);1441 }1442 }1443 if (node->children) {1444 g_string_append_printf(s, fmt, "", indent?" ":"", "Items:\n");1445 }1446 break;1447 case ST_FORMAT_XML:1448 {1449 char *itemname = xml_escape(values[0]);1450 g_string_append_printf(s,"<stat-node name=\"%s\"%s>\n",itemname,1451 node->rng?" isrange=\"true\"":"");1452 g_free(itemname);1453 for (count = 1; count<num_columns; count++) {1454 char *colname = g_strdup(stats_tree_get_column_name(node->st->cfg, count));1455 g_string_append_printf(s,"<%s>",clean_for_xml_tag(colname));1456 g_string_append_printf(s,"%s</%s>\n",values[count],colname);1457 g_free(colname);1458 }1459 break;1460 }1461 case ST_FORMAT_CSV:1462 g_string_append_printf(s,"%d,\"%s\",\"%s\"",indent,path,values[0]);1463 for (count = 1; count<num_columns; count++) {1464 g_string_append_printf(s,",%s",values[count]);1465 }1466 g_string_append (s,"\n");1467 break;1468 case ST_FORMAT_PLAIN:1469 snprintf (fmt,sizeof(fmt),"%%%ds%%-%us",indent,maxnamelen-indent);1470 g_string_append_printf(s,fmt,"",values[0]);1471 for (count = 1; count<num_columns; count++) {1472 snprintf (fmt,sizeof(fmt)," %%-%us",stats_tree_get_column_size(count)+1);1473 g_string_append_printf(s,fmt,values[count]);1474 }1475 g_string_append (s,"\n");1476 break;1477 }1478 1479 indent++;1480 indent = indent > INDENT_MAX32 ? INDENT_MAX32 : indent;1481 full_path = ws_strdup_printf ("%s/%s",path,values[0])wmem_strdup_printf(((void*)0), "%s/%s",path,values[0]);1482 1483 for (count = 0; count<num_columns; count++) {1484 g_free(values[count]);1485 }1486 g_free(values);1487 1488 if (node->children) {1489 GArray *Children = g_array_new(FALSE(0),FALSE(0),sizeof(child));1490 for (child = node->children; child; child = child->next ) {1491 g_array_append_val(Children,child)g_array_append_vals (Children, &(child), 1);1492 }1493 si.sort_column = sort_column;1494 si.sort_descending = sort_descending;1495 g_array_sort_with_data(Children,stat_node_array_sortcmp,&si);1496 for (count = 0; count<((int)Children->len); count++) {1497 stats_tree_format_node_as_str(g_array_index(Children,stat_node*,count)(((stat_node**) (void *) (Children)->data) [(count)]), s, format_type,1498 indent, full_path, maxnamelen, sort_column, sort_descending);1499 }1500 g_array_free(Children, TRUE(!(0)));1501 }1502 g_free(full_path);1503 1504 if (format_type==ST_FORMAT_XML) {1505 g_string_append(s,"</stat-node>\n");1506 }1507}1508 1509void stats_tree_cleanup(void)1510{1511 g_hash_table_destroy(registry);1512}1513 1514/*1515 * Editor modelines - https://www.wireshark.org/tools/modelines.html1516 *1517 * Local variables:1518 * c-basic-offset: 41519 * tab-width: 81520 * indent-tabs-mode: nil1521 * End:1522 *1523 * vi: set shiftwidth=4 tabstop=8 expandtab:1524 * :indentSize=4:tabSize=8:noTabs=true:1525 */
/builds/wireshark/wireshark/epan/stats_tree.c (2024)
Top Articles
Latest Posts
Article information

Author: Delena Feil

Last Updated:

Views: 5550

Rating: 4.4 / 5 (65 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Delena Feil

Birthday: 1998-08-29

Address: 747 Lubowitz Run, Sidmouth, HI 90646-5543

Phone: +99513241752844

Job: Design Supervisor

Hobby: Digital arts, Lacemaking, Air sports, Running, Scouting, Shooting, Puzzles

Introduction: My name is Delena Feil, I am a clean, splendid, calm, fancy, jolly, bright, faithful person who loves writing and wants to share my knowledge and understanding with you.