Bug Summary

File:ui/cli/tap-follow.c
Warning:line 586, column 12
Potential leak of memory pointed to by 'follow_info'

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 tap-follow.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 -pic-is-pie -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-20/lib/clang/20 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-09-11-100357-3933-1 -x c /builds/wireshark/wireshark/ui/cli/tap-follow.c
1/* tap-follow.c
2 *
3 * Copyright 2011-2013, QA Cafe <[email protected]>
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <[email protected]>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12/* This module provides udp and tcp follow stream capabilities to tshark.
13 * It is only used by tshark and not wireshark.
14 */
15
16#include "config.h"
17
18#include <stdio.h>
19#include <stdlib.h>
20
21#include <glib.h>
22#include <epan/addr_resolv.h>
23#include <wsutil/str_util.h>
24#include <wsutil/unicode-utils.h>
25#include <epan/follow.h>
26#include <epan/stat_tap_ui.h>
27#include <epan/tap.h>
28#include <wsutil/ws_assert.h>
29#include <wsutil/cmdarg_err.h>
30
31void register_tap_listener_follow(void);
32
33/* Show Type */
34typedef enum {
35 SHOW_ASCII,
36 SHOW_CARRAY,
37 SHOW_EBCDIC,
38 SHOW_HEXDUMP,
39 SHOW_RAW,
40 SHOW_CODEC, // Ordered to match UTF-8 combobox index
41 SHOW_YAML
42} show_type_t;
43
44typedef struct _cli_follow_info {
45 show_type_t show_type;
46 register_follow_t* follower;
47
48 /* range */
49 uint32_t chunkMin;
50 uint32_t chunkMax;
51
52 /* filter */
53 int stream_index;
54 int sub_stream_index;
55 int port[2];
56 address addr[2];
57 union {
58 uint32_t addrBuf_v4;
59 ws_in6_addr addrBuf_v6;
60 } addrBuf[2];
61} cli_follow_info_t;
62
63
64#define STR_FOLLOW"follow," "follow,"
65
66#define STR_HEX",hex" ",hex"
67#define STR_ASCII",ascii" ",ascii"
68#define STR_EBCDIC",ebcdic" ",ebcdic"
69#define STR_RAW",raw" ",raw"
70#define STR_CODEC",utf-8" ",utf-8"
71#define STR_YAML",yaml" ",yaml"
72
73static const char * follow_str_type(cli_follow_info_t* cli_follow_info)
74{
75 switch (cli_follow_info->show_type)
76 {
77 case SHOW_HEXDUMP: return "hex";
78 case SHOW_ASCII: return "ascii";
79 case SHOW_EBCDIC: return "ebcdic";
80 case SHOW_RAW: return "raw";
81 case SHOW_CODEC: return "utf-8";
82 case SHOW_YAML: return "yaml";
83 default:
84 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-follow.c",
84, __func__, "assertion \"not reached\" failed")
;
85 break;
86 }
87
88 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-follow.c",
88, __func__, "assertion \"not reached\" failed")
;
89
90 return "<unknown-mode>";
91}
92
93static void
94follow_free(follow_info_t *follow_info)
95{
96 cli_follow_info_t* cli_follow_info = (cli_follow_info_t*)follow_info->gui_data;
97
98 g_free(cli_follow_info);
99 follow_info_free(follow_info);
100}
101
102#define BYTES_PER_LINE16 16
103#define OFFSET_LEN8 8
104#define OFFSET_SPACE2 2
105#define HEX_START(8 + 2) (OFFSET_LEN8 + OFFSET_SPACE2)
106#define HEX_LEN(16 * 3) (BYTES_PER_LINE16 * 3) /* extra space at column 8 */
107#define HEX_SPACE2 2
108#define ASCII_START((8 + 2) + (16 * 3) + 2) (HEX_START(8 + 2) + HEX_LEN(16 * 3) + HEX_SPACE2)
109#define ASCII_LEN(16 + 1) (BYTES_PER_LINE16 + 1) /* extra space at column 8 */
110#define LINE_LEN(((8 + 2) + (16 * 3) + 2) + (16 + 1)) (ASCII_START((8 + 2) + (16 * 3) + 2) + ASCII_LEN(16 + 1))
111
112static const char bin2hex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
113 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
114
115static void follow_print_hex(const char *prefixp, uint32_t offset, void *datap, int len)
116{
117 int ii;
118 int jj;
119 int kk;
120 uint8_t val;
121 char line[LINE_LEN(((8 + 2) + (16 * 3) + 2) + (16 + 1)) + 1];
122
123 for (ii = 0, jj = 0, kk = 0; ii < len; )
124 {
125 if ((ii % BYTES_PER_LINE16) == 0)
126 {
127 /* new line */
128 snprintf(line, LINE_LEN(((8 + 2) + (16 * 3) + 2) + (16 + 1)) + 1, "%0*X", OFFSET_LEN8, offset);
129 memset(line + HEX_START(8 + 2) - OFFSET_SPACE2, ' ',
130 HEX_LEN(16 * 3) + OFFSET_SPACE2 + HEX_SPACE2);
131
132 /* offset of hex */
133 jj = HEX_START(8 + 2);
134
135 /* offset of ascii */
136 kk = ASCII_START((8 + 2) + (16 * 3) + 2);
137 }
138
139 val = ((uint8_t *)datap)[ii];
140
141 line[jj++] = bin2hex[val >> 4];
142 line[jj++] = bin2hex[val & 0xf];
143 jj++;
144
145 line[kk++] = val >= ' ' && val < 0x7f ? val : '.';
146
147 /* extra space at column 8 */
148 if (++ii % BYTES_PER_LINE16 == BYTES_PER_LINE16/2)
149 {
150 line[jj++] = ' ';
151 line[kk++] = ' ';
152 }
153
154 if ((ii % BYTES_PER_LINE16) == 0 || ii == len)
155 {
156 /* end of line or buffer */
157 if (line[kk - 1] == ' ')
158 {
159 kk--;
160 }
161 line[kk] = 0;
162 printf("%s%s\n", prefixp, line);
163 offset += BYTES_PER_LINE16;
164 }
165 }
166}
167
168static void follow_draw(void *contextp)
169{
170 static const char separator[] =
171 "===================================================================\n";
172
173 follow_info_t *follow_info = (follow_info_t*)contextp;
174 cli_follow_info_t* cli_follow_info = (cli_follow_info_t*)follow_info->gui_data;
175 char buf[WS_INET6_ADDRSTRLEN46];
176 uint32_t global_client_pos = 0, global_server_pos = 0;
177 uint32_t *global_pos;
178 uint32_t ii, jj;
179 char *buffer;
180 wmem_strbuf_t *strbuf;
181 GList *cur;
182 follow_record_t *follow_record;
183 unsigned chunk;
184 char *b64encoded;
185 const uint32_t base64_raw_len = 57; /* Encodes to 76 bytes, common in RFCs */
186
187 /* Print header */
188 switch (cli_follow_info->show_type)
189 {
190 case SHOW_YAML:
191 printf("peers:\n");
192 printf(" - peer: 0\n");
193 address_to_str_buf(&follow_info->client_ip, buf, sizeof buf);
194 printf(" host: %s\n", buf);
195 printf(" port: %d\n", follow_info->client_port);
196 printf(" - peer: 1\n");
197 address_to_str_buf(&follow_info->server_ip, buf, sizeof buf);
198 printf(" host: %s\n", buf);
199 printf(" port: %d\n", follow_info->server_port);
200 printf("packets:\n");
201 break;
202
203 default:
204 printf("\n%s", separator);
205 printf("Follow: %s,%s\n", proto_get_protocol_filter_name(get_follow_proto_id(cli_follow_info->follower)), follow_str_type(cli_follow_info));
206 printf("Filter: %s\n", follow_info->filter_out_filter);
207
208 address_to_str_buf(&follow_info->client_ip, buf, sizeof buf);
209 if (follow_info->client_ip.type == AT_IPv6)
210 printf("Node 0: [%s]:%u\n", buf, follow_info->client_port);
211 else
212 printf("Node 0: %s:%u\n", buf, follow_info->client_port);
213
214 address_to_str_buf(&follow_info->server_ip, buf, sizeof buf);
215 if (follow_info->server_ip.type == AT_IPv6)
216 printf("Node 1: [%s]:%u\n", buf, follow_info->server_port);
217 else
218 printf("Node 1: %s:%u\n", buf, follow_info->server_port);
219 break;
220 }
221
222 for (cur = g_list_last(follow_info->payload), chunk = 1;
223 cur != NULL((void*)0);
224 cur = g_list_previous(cur)((cur) ? (((GList *)(cur))->prev) : ((void*)0)), chunk++)
225 {
226 follow_record = (follow_record_t *)cur->data;
227 if (!follow_record->is_server) {
228 global_pos = &global_client_pos;
229 } else {
230 global_pos = &global_server_pos;
231 }
232
233 /* ignore chunks not in range */
234 if ((chunk < cli_follow_info->chunkMin) || (chunk > cli_follow_info->chunkMax)) {
235 (*global_pos) += follow_record->data->len;
236 continue;
237 }
238
239 /* Print start of line */
240 switch (cli_follow_info->show_type)
241 {
242 case SHOW_HEXDUMP:
243 case SHOW_YAML:
244 case SHOW_CODEC: /* The transformation to UTF-8 can change the length */
245 break;
246
247 case SHOW_ASCII:
248 case SHOW_EBCDIC:
249 printf("%s%u\n", follow_record->is_server ? "\t" : "", follow_record->data->len);
250 break;
251
252 case SHOW_RAW:
253 if (follow_record->is_server)
254 {
255 putchar('\t');
256 }
257 break;
258
259 default:
260 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-follow.c",
260, __func__, "assertion \"not reached\" failed")
;
261 }
262
263 /* Print data */
264 switch (cli_follow_info->show_type)
265 {
266 case SHOW_HEXDUMP:
267 follow_print_hex(follow_record->is_server ? "\t" : "", *global_pos, follow_record->data->data, follow_record->data->len);
268 (*global_pos) += follow_record->data->len;
269 break;
270
271 case SHOW_ASCII:
272 case SHOW_EBCDIC:
273 buffer = (char *)g_malloc(follow_record->data->len+2);
274
275 for (ii = 0; ii < follow_record->data->len; ii++)
276 {
277 switch (follow_record->data->data[ii])
278 {
279 // XXX: qt/follow_stream_dialog.c sanitize_buffer() also passes
280 // tabs ('\t') through. Should we do that here too?
281 // The Qt code has automatic universal new line handling for reading
282 // so, e.g., \r\n in HTML becomes just \n, but we don't do that here.
283 // (The Qt version doesn't write the file as Text, so all files use
284 // Unix line endings, including on Windows.)
285 case '\r':
286 case '\n':
287 buffer[ii] = follow_record->data->data[ii];
288 break;
289 default:
290 buffer[ii] = g_ascii_isprint(follow_record->data->data[ii])((g_ascii_table[(guchar) (follow_record->data->data[ii]
)] & G_ASCII_PRINT) != 0)
? follow_record->data->data[ii] : '.';
291 break;
292 }
293 }
294
295 buffer[ii++] = '\n';
296 buffer[ii] = 0;
297 if (cli_follow_info->show_type == SHOW_EBCDIC) {
298 EBCDIC_to_ASCII(buffer, ii);
299 }
300 printf("%s", buffer);
301 g_free(buffer);
302 break;
303
304 case SHOW_CODEC:
305 // This does the same as the Show As UTF-8 code in the Qt version
306 // (passing through all legal UTF-8, including control codes and
307 // internal NULs, substituting illegal UTF-8 sequences with
308 // REPLACEMENT CHARACTER, and not handling valid UTF-8 sequences
309 // which are split between unreassembled frames), except for the
310 // end of line terminator issue as above.
311 strbuf = ws_utf8_make_valid_strbuf(NULL((void*)0), follow_record->data->data, follow_record->data->len);
312 printf("%s%zu\n", follow_record->is_server ? "\t" : "", wmem_strbuf_get_len(strbuf));
313 fwrite(wmem_strbuf_get_str(strbuf), 1, wmem_strbuf_get_len(strbuf), stdoutstdout);
314 wmem_strbuf_destroy(strbuf);
315 putchar('\n');
316 break;
317
318 case SHOW_RAW:
319 buffer = (char *)g_malloc((follow_record->data->len*2)+2);
320
321 for (ii = 0, jj = 0; ii < follow_record->data->len; ii++)
322 {
323 buffer[jj++] = bin2hex[follow_record->data->data[ii] >> 4];
324 buffer[jj++] = bin2hex[follow_record->data->data[ii] & 0xf];
325 }
326
327 buffer[jj++] = '\n';
328 buffer[jj] = 0;
329 printf("%s", buffer);
330 g_free(buffer);
331 break;
332
333 case SHOW_YAML:
334 printf(" - packet: %d\n", follow_record->packet_num);
335 printf(" peer: %d\n", follow_record->is_server ? 1 : 0);
336 printf(" timestamp: %.9f\n", nstime_to_sec(&follow_record->abs_ts));
337 printf(" data: !!binary |\n");
338 ii = 0;
339 while (ii < follow_record->data->len) {
340 uint32_t len = ii + base64_raw_len < follow_record->data->len
341 ? base64_raw_len
342 : follow_record->data->len - ii;
343 b64encoded = g_base64_encode(&follow_record->data->data[ii], len);
344 printf(" %s\n", b64encoded);
345 g_free(b64encoded);
346 ii += len;
347 }
348 break;
349
350 default:
351 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-follow.c",
351, __func__, "assertion \"not reached\" failed")
;
352 }
353 }
354
355 /* Print footer */
356 switch (cli_follow_info->show_type)
357 {
358 case SHOW_YAML:
359 break;
360
361 default:
362 printf("%s", separator);
363 break;
364 }
365}
366
367static bool_Bool follow_arg_strncmp(const char **opt_argp, const char *strp)
368{
369 size_t len = strlen(strp);
370
371 if (strncmp(*opt_argp, strp, len) == 0)
372 {
373 *opt_argp += len;
374 return true1;
375 }
376 return false0;
377}
378
379static bool_Bool
380follow_arg_mode(const char **opt_argp, follow_info_t *follow_info)
381{
382 cli_follow_info_t* cli_follow_info = (cli_follow_info_t*)follow_info->gui_data;
383
384 if (follow_arg_strncmp(opt_argp, STR_HEX",hex"))
385 {
386 cli_follow_info->show_type = SHOW_HEXDUMP;
387 }
388 else if (follow_arg_strncmp(opt_argp, STR_ASCII",ascii"))
389 {
390 cli_follow_info->show_type = SHOW_ASCII;
391 }
392 else if (follow_arg_strncmp(opt_argp, STR_EBCDIC",ebcdic"))
393 {
394 cli_follow_info->show_type = SHOW_EBCDIC;
395 }
396 else if (follow_arg_strncmp(opt_argp, STR_RAW",raw"))
397 {
398 cli_follow_info->show_type = SHOW_RAW;
399 }
400 else if (follow_arg_strncmp(opt_argp, STR_CODEC",utf-8"))
401 {
402 cli_follow_info->show_type = SHOW_CODEC;
403 }
404 else if (follow_arg_strncmp(opt_argp, STR_YAML",yaml"))
405 {
406 cli_follow_info->show_type = SHOW_YAML;
407 }
408 else
409 {
410 cmdarg_err("Invalid display mode.");
411 return false0;
412 }
413
414 return true1;
415}
416
417#define _STRING(s)"s" # s
418#define STRING(s)"s" _STRING(s)"s"
419
420#define ADDR_CHARS80 80
421#define ADDR_LEN(80 + 1) (ADDR_CHARS80 + 1)
422#define ADDRv6_FMT",[%" "80" "[^]]]:%d%n" ",[%" STRING(ADDR_CHARS)"80" "[^]]]:%d%n"
423#define ADDRv4_FMT",%" "80" "[^:]:%d%n" ",%" STRING(ADDR_CHARS)"80" "[^:]:%d%n"
424
425static bool_Bool
426follow_arg_filter(const char **opt_argp, follow_info_t *follow_info)
427{
428 int len;
429 unsigned int ii;
430 char addr[ADDR_LEN(80 + 1)];
431 cli_follow_info_t* cli_follow_info = (cli_follow_info_t*)follow_info->gui_data;
432 bool_Bool is_ipv6;
433
434 if (sscanf(*opt_argp, ",%d%n", &cli_follow_info->stream_index, &len) == 1 &&
435 ((*opt_argp)[len] == 0 || (*opt_argp)[len] == ','))
436 {
437 *opt_argp += len;
438
439 /* if it's HTTP2 or QUIC protocol we should read substream id otherwise it's a range parameter from follow_arg_range */
440 if (cli_follow_info->sub_stream_index == -1 && sscanf(*opt_argp, ",%d%n", &cli_follow_info->sub_stream_index, &len) == 1 &&
441 ((*opt_argp)[len] == 0 || (*opt_argp)[len] == ','))
442 {
443 *opt_argp += len;
444 follow_info->substream_id = cli_follow_info->sub_stream_index;
445 }
446 }
447 else
448 {
449 for (ii = 0; ii < array_length(cli_follow_info->addr)(sizeof (cli_follow_info->addr) / sizeof (cli_follow_info->
addr)[0])
; ii++)
450 {
451 if (sscanf(*opt_argp, ADDRv6_FMT",[%" "80" "[^]]]:%d%n", addr, &cli_follow_info->port[ii], &len) == 2)
452 {
453 is_ipv6 = true1;
454 }
455 else if (sscanf(*opt_argp, ADDRv4_FMT",%" "80" "[^:]:%d%n", addr, &cli_follow_info->port[ii], &len) == 2)
456 {
457 is_ipv6 = false0;
458 }
459 else
460 {
461 cmdarg_err("Invalid address.");
462 return false0;
463 }
464
465 if (cli_follow_info->port[ii] <= 0 || cli_follow_info->port[ii] > UINT16_MAX(65535))
466 {
467 cmdarg_err("Invalid port.");
468 return false0;
469 }
470
471 if (is_ipv6)
472 {
473 if (!get_host_ipaddr6(addr, &cli_follow_info->addrBuf[ii].addrBuf_v6))
474 {
475 cmdarg_err("Can't get IPv6 address");
476 return false0;
477 }
478 set_address(&cli_follow_info->addr[ii], AT_IPv6, 16, (void *)&cli_follow_info->addrBuf[ii].addrBuf_v6);
479 }
480 else
481 {
482 if (!get_host_ipaddr(addr, &cli_follow_info->addrBuf[ii].addrBuf_v4))
483 {
484 cmdarg_err("Can't get IPv4 address");
485 return false0;
486 }
487 set_address(&cli_follow_info->addr[ii], AT_IPv4, 4, (void *)&cli_follow_info->addrBuf[ii].addrBuf_v4);
488 }
489
490 *opt_argp += len;
491 }
492
493 if (cli_follow_info->addr[0].type != cli_follow_info->addr[1].type)
494 {
495 cmdarg_err("Mismatched IP address types.");
496 return false0;
497 }
498 cli_follow_info->stream_index = -1;
499 }
500
501 return true1;
502}
503
504static bool_Bool follow_arg_range(const char **opt_argp, cli_follow_info_t* cli_follow_info)
505{
506 int len;
507
508 if (**opt_argp == 0)
509 {
510 cli_follow_info->chunkMin = 1;
511 cli_follow_info->chunkMax = UINT32_MAX(4294967295U);
512 }
513 else
514 {
515 if (sscanf(*opt_argp, ",%u-%u%n", &cli_follow_info->chunkMin, &cli_follow_info->chunkMax, &len) == 2)
516 {
517 *opt_argp += len;
518 }
519 else if (sscanf(*opt_argp, ",%u%n", &cli_follow_info->chunkMin, &len) == 1)
520 {
521 cli_follow_info->chunkMax = cli_follow_info->chunkMin;
522 *opt_argp += len;
523 }
524 else
525 {
526 cmdarg_err("Invalid range.");
527 return false0;
528 }
529
530 if (cli_follow_info->chunkMin < 1 || cli_follow_info->chunkMin > cli_follow_info->chunkMax)
531 {
532 cmdarg_err("Invalid range value.");
533 return false0;
534 }
535 }
536
537 return true1;
538}
539
540static bool_Bool
541follow_arg_done(const char *opt_argp)
542{
543 if (*opt_argp != 0)
544 {
545 cmdarg_err("Invalid parameter.");
546 return false0;
547 }
548
549 return true1;
550}
551
552static bool_Bool follow_stream(const char *opt_argp, void *userdata)
553{
554 follow_info_t *follow_info;
555 cli_follow_info_t* cli_follow_info;
556 GString *errp;
557 register_follow_t* follower = (register_follow_t*)userdata;
558 follow_index_filter_func index_filter;
559 follow_address_filter_func address_filter;
560 int proto_id = get_follow_proto_id(follower);
561 const char* proto_filter_name = proto_get_protocol_filter_name(proto_id);
562 bool_Bool arg_success = true1;
563
564 opt_argp += strlen(STR_FOLLOW"follow,");
565 opt_argp += strlen(proto_filter_name);
566
567 cli_follow_info = g_new0(cli_follow_info_t, 1)((cli_follow_info_t *) g_malloc0_n ((1), sizeof (cli_follow_info_t
)))
;
568 cli_follow_info->stream_index = -1;
569 /* use second parameter only for followers that have sub streams
570 * (currently HTTP2 or QUIC) */
571 if (get_follow_sub_stream_id_func(follower)) {
1
Assuming the condition is false
2
Taking false branch
572 cli_follow_info->sub_stream_index = -1;
573 } else {
574 cli_follow_info->sub_stream_index = 0;
575 }
576 follow_info = g_new0(follow_info_t, 1)((follow_info_t *) g_malloc0_n ((1), sizeof (follow_info_t)));
3
Memory is allocated
577 follow_info->gui_data = cli_follow_info;
578 follow_info->substream_id = SUBSTREAM_UNUSED0xFFFFFFFFFFFFFFFFUL;
579 cli_follow_info->follower = follower;
580
581 arg_success &= follow_arg_mode(&opt_argp, follow_info);
582 arg_success &= follow_arg_filter(&opt_argp, follow_info);
583 arg_success &= follow_arg_range(&opt_argp, cli_follow_info);
584 arg_success &= follow_arg_done(opt_argp);
585 if (!arg_success
3.1
'arg_success' is false
)
4
Taking true branch
586 return false0;
5
Potential leak of memory pointed to by 'follow_info'
587
588 if (cli_follow_info->stream_index >= 0)
589 {
590 index_filter = get_follow_index_func(follower);
591 follow_info->filter_out_filter = index_filter(cli_follow_info->stream_index, cli_follow_info->sub_stream_index);
592 if (follow_info->filter_out_filter == NULL((void*)0) || cli_follow_info->sub_stream_index < 0)
593 {
594 cmdarg_err("Error creating filter for this stream.");
595 return false0;
596 }
597 }
598 else
599 {
600 address_filter = get_follow_address_func(follower);
601 follow_info->filter_out_filter = address_filter(&cli_follow_info->addr[0], &cli_follow_info->addr[1], cli_follow_info->port[0], cli_follow_info->port[1]);
602 if (follow_info->filter_out_filter == NULL((void*)0))
603 {
604 cmdarg_err("Error creating filter for this address/port pair.\n");
605 return false0;
606 }
607 }
608
609 errp = register_tap_listener(get_follow_tap_string(follower), follow_info, follow_info->filter_out_filter, 0,
610 NULL((void*)0), get_follow_tap_handler(follower), follow_draw, (tap_finish_cb)follow_free);
611
612 if (errp != NULL((void*)0))
613 {
614 follow_free(follow_info);
615 g_string_free(errp, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(errp), ((!(0)))) : g_string_free_and_steal (errp)) : (g_string_free
) ((errp), ((!(0)))))
;
616 cmdarg_err("Error registering tap listener.");
617 return false0;
618 }
619 return true1;
620}
621
622static bool_Bool
623follow_register(const void *key _U___attribute__((unused)), void *value, void *userdata _U___attribute__((unused)))
624{
625 register_follow_t *follower = (register_follow_t*)value;
626 stat_tap_ui follow_ui;
627 char *cli_string;
628
629 cli_string = follow_get_stat_tap_string(follower);
630 follow_ui.group = REGISTER_STAT_GROUP_GENERIC;
631 follow_ui.title = NULL((void*)0); /* construct this from the protocol info? */
632 follow_ui.cli_string = cli_string;
633 follow_ui.tap_init_cb = follow_stream;
634 follow_ui.nparams = 0;
635 follow_ui.params = NULL((void*)0);
636 register_stat_tap_ui(&follow_ui, follower);
637 g_free(cli_string);
638 return false0;
639}
640
641void
642register_tap_listener_follow(void)
643{
644 follow_iterate_followers(follow_register, NULL((void*)0));
645}
646
647/*
648 * Editor modelines - https://www.wireshark.org/tools/modelines.html
649 *
650 * Local Variables:
651 * c-basic-offset: 2
652 * tab-width: 8
653 * indent-tabs-mode: nil
654 * End:
655 *
656 * ex: set shiftwidth=2 tabstop=8 expandtab:
657 * :indentSize=2:tabSize=8:noTabs=true:
658 */