Bug Summary

File:builds/wireshark/wireshark/ui/cli/tap-follow.c
Warning:line 587, 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-21/lib/clang/21 -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-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-05-17-100315-3642-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((uint8_t*)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 follow_info->stream_id = cli_follow_info->stream_index;
439
440 /* if it's HTTP2 or QUIC protocol we should read substream id otherwise it's a range parameter from follow_arg_range */
441 if (cli_follow_info->sub_stream_index == -1 && sscanf(*opt_argp, ",%d%n", &cli_follow_info->sub_stream_index, &len) == 1 &&
442 ((*opt_argp)[len] == 0 || (*opt_argp)[len] == ','))
443 {
444 *opt_argp += len;
445 follow_info->substream_id = cli_follow_info->sub_stream_index;
446 }
447 }
448 else
449 {
450 for (ii = 0; ii < array_length(cli_follow_info->addr)(sizeof (cli_follow_info->addr) / sizeof (cli_follow_info->
addr)[0])
; ii++)
451 {
452 if (sscanf(*opt_argp, ADDRv6_FMT",[%" "80" "[^]]]:%d%n", addr, &cli_follow_info->port[ii], &len) == 2)
453 {
454 is_ipv6 = true1;
455 }
456 else if (sscanf(*opt_argp, ADDRv4_FMT",%" "80" "[^:]:%d%n", addr, &cli_follow_info->port[ii], &len) == 2)
457 {
458 is_ipv6 = false0;
459 }
460 else
461 {
462 cmdarg_err("Invalid address.");
463 return false0;
464 }
465
466 if (cli_follow_info->port[ii] <= 0 || cli_follow_info->port[ii] > UINT16_MAX(65535))
467 {
468 cmdarg_err("Invalid port.");
469 return false0;
470 }
471
472 if (is_ipv6)
473 {
474 if (!get_host_ipaddr6(addr, &cli_follow_info->addrBuf[ii].addrBuf_v6))
475 {
476 cmdarg_err("Can't get IPv6 address");
477 return false0;
478 }
479 set_address(&cli_follow_info->addr[ii], AT_IPv6, 16, (void *)&cli_follow_info->addrBuf[ii].addrBuf_v6);
480 }
481 else
482 {
483 if (!get_host_ipaddr(addr, &cli_follow_info->addrBuf[ii].addrBuf_v4))
484 {
485 cmdarg_err("Can't get IPv4 address");
486 return false0;
487 }
488 set_address(&cli_follow_info->addr[ii], AT_IPv4, 4, (void *)&cli_follow_info->addrBuf[ii].addrBuf_v4);
489 }
490
491 *opt_argp += len;
492 }
493
494 if (cli_follow_info->addr[0].type != cli_follow_info->addr[1].type)
495 {
496 cmdarg_err("Mismatched IP address types.");
497 return false0;
498 }
499 cli_follow_info->stream_index = -1;
500 }
501
502 return true1;
503}
504
505static bool_Bool follow_arg_range(const char **opt_argp, cli_follow_info_t* cli_follow_info)
506{
507 int len;
508
509 if (**opt_argp == 0)
510 {
511 cli_follow_info->chunkMin = 1;
512 cli_follow_info->chunkMax = UINT32_MAX(4294967295U);
513 }
514 else
515 {
516 if (sscanf(*opt_argp, ",%u-%u%n", &cli_follow_info->chunkMin, &cli_follow_info->chunkMax, &len) == 2)
517 {
518 *opt_argp += len;
519 }
520 else if (sscanf(*opt_argp, ",%u%n", &cli_follow_info->chunkMin, &len) == 1)
521 {
522 cli_follow_info->chunkMax = cli_follow_info->chunkMin;
523 *opt_argp += len;
524 }
525 else
526 {
527 cmdarg_err("Invalid range.");
528 return false0;
529 }
530
531 if (cli_follow_info->chunkMin < 1 || cli_follow_info->chunkMin > cli_follow_info->chunkMax)
532 {
533 cmdarg_err("Invalid range value.");
534 return false0;
535 }
536 }
537
538 return true1;
539}
540
541static bool_Bool
542follow_arg_done(const char *opt_argp)
543{
544 if (*opt_argp != 0)
545 {
546 cmdarg_err("Invalid parameter.");
547 return false0;
548 }
549
550 return true1;
551}
552
553static bool_Bool follow_stream(const char *opt_argp, void *userdata)
554{
555 follow_info_t *follow_info;
556 cli_follow_info_t* cli_follow_info;
557 GString *errp;
558 register_follow_t* follower = (register_follow_t*)userdata;
559 follow_index_filter_func index_filter;
560 follow_address_filter_func address_filter;
561 int proto_id = get_follow_proto_id(follower);
562 const char* proto_filter_name = proto_get_protocol_filter_name(proto_id);
563 bool_Bool arg_success = true1;
564
565 opt_argp += strlen(STR_FOLLOW"follow,");
566 opt_argp += strlen(proto_filter_name);
567
568 cli_follow_info = g_new0(cli_follow_info_t, 1)((cli_follow_info_t *) g_malloc0_n ((1), sizeof (cli_follow_info_t
)))
;
569 cli_follow_info->stream_index = -1;
570 /* use second parameter only for followers that have sub streams
571 * (currently HTTP2 or QUIC) */
572 if (get_follow_sub_stream_id_func(follower)) {
1
Assuming the condition is false
2
Taking false branch
573 cli_follow_info->sub_stream_index = -1;
574 } else {
575 cli_follow_info->sub_stream_index = 0;
576 }
577 follow_info = g_new0(follow_info_t, 1)((follow_info_t *) g_malloc0_n ((1), sizeof (follow_info_t)));
3
Memory is allocated
578 follow_info->gui_data = cli_follow_info;
579 follow_info->substream_id = SUBSTREAM_UNUSED0xFFFFFFFFFFFFFFFFUL;
580 cli_follow_info->follower = follower;
581
582 arg_success &= follow_arg_mode(&opt_argp, follow_info);
583 arg_success &= follow_arg_filter(&opt_argp, follow_info);
584 arg_success &= follow_arg_range(&opt_argp, cli_follow_info);
585 arg_success &= follow_arg_done(opt_argp);
586 if (!arg_success
3.1
'arg_success' is false
)
4
Taking true branch
587 return false0;
5
Potential leak of memory pointed to by 'follow_info'
588
589 if (cli_follow_info->stream_index >= 0)
590 {
591 index_filter = get_follow_index_func(follower);
592 follow_info->filter_out_filter = index_filter(cli_follow_info->stream_index, cli_follow_info->sub_stream_index);
593 if (follow_info->filter_out_filter == NULL((void*)0) || cli_follow_info->sub_stream_index < 0)
594 {
595 cmdarg_err("Error creating filter for this stream.");
596 return false0;
597 }
598 }
599 else
600 {
601 address_filter = get_follow_address_func(follower);
602 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]);
603 if (follow_info->filter_out_filter == NULL((void*)0))
604 {
605 cmdarg_err("Error creating filter for this address/port pair.\n");
606 return false0;
607 }
608 }
609
610 errp = register_tap_listener(get_follow_tap_string(follower), follow_info, follow_info->filter_out_filter, 0,
611 NULL((void*)0), get_follow_tap_handler(follower), follow_draw, (tap_finish_cb)follow_free);
612
613 if (errp != NULL((void*)0))
614 {
615 follow_free(follow_info);
616 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)))))
;
617 cmdarg_err("Error registering tap listener.");
618 return false0;
619 }
620 return true1;
621}
622
623static bool_Bool
624follow_register(const void *key _U___attribute__((unused)), void *value, void *userdata _U___attribute__((unused)))
625{
626 register_follow_t *follower = (register_follow_t*)value;
627 stat_tap_ui follow_ui;
628 char *cli_string;
629
630 cli_string = follow_get_stat_tap_string(follower);
631 follow_ui.group = REGISTER_STAT_GROUP_GENERIC;
632 follow_ui.title = NULL((void*)0); /* construct this from the protocol info? */
633 follow_ui.cli_string = cli_string;
634 follow_ui.tap_init_cb = follow_stream;
635 follow_ui.nparams = 0;
636 follow_ui.params = NULL((void*)0);
637 register_stat_tap_ui(&follow_ui, follower);
638 g_free(cli_string);
639 return false0;
640}
641
642void
643register_tap_listener_follow(void)
644{
645 follow_iterate_followers(follow_register, NULL((void*)0));
646}
647
648/*
649 * Editor modelines - https://www.wireshark.org/tools/modelines.html
650 *
651 * Local Variables:
652 * c-basic-offset: 2
653 * tab-width: 8
654 * indent-tabs-mode: nil
655 * End:
656 *
657 * ex: set shiftwidth=2 tabstop=8 expandtab:
658 * :indentSize=2:tabSize=8:noTabs=true:
659 */