Bug Summary

File:builds/wireshark/wireshark/mmdbresolve.c
Warning:line 108, column 9
Potential leak of memory pointed to by 'mmdbs'

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 mmdbresolve.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-18/lib/clang/18 -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 -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/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 -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 -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -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 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIE /builds/wireshark/wireshark/mmdbresolve.c -o /builds/wireshark/wireshark/sbout/2025-05-09-100252-3825-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-05-09-100252-3825-1 -x c /builds/wireshark/wireshark/mmdbresolve.c
1/* Read IPv4 and IPv6 addresses on stdin and print their MMDB entries on stdout.
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
6 *
7 * This program uses the MaxMind DB library (libmaxminddb) and MUST be
8 * compatible with its license (Apache 2.0).
9 *
10 * SPDX-License-Identifier: MIT
11 *
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include <maxminddb.h>
19
20#define MAX_ADDR_LEN46 46
21#define MMDBR_STRINGIFY(x)"x" MMDBR_STRINGIFY_S(x)"x"
22#define MMDBR_STRINGIFY_S(s)"s" #s
23#define OUT_BUF_SIZE65536 65536
24
25// Uncomment to enable slow lookups. Only useful on Windows for now.
26// #define MMDB_DEBUG_SLOW 1
27
28#ifdef MMDB_DEBUG_SLOW
29#ifdef _WIN32
30#include <Windows.h>
31#endif
32#endif
33
34static const char *co_iso_key[] = {"country", "iso_code", NULL((void*)0)};
35static const char *co_name_key[] = {"country", "names", "en", NULL((void*)0)};
36static const char *ci_name_key[] = {"city", "names", "en", NULL((void*)0)};
37static const char *asn_o_key[] = {"autonomous_system_organization", NULL((void*)0)};
38static const char *asn_key[] = {"autonomous_system_number", NULL((void*)0)};
39static const char *l_lat_key[] = {"location", "latitude", NULL((void*)0)};
40static const char *l_lon_key[] = {"location", "longitude", NULL((void*)0)};
41static const char *l_accuracy_key[] = {"location", "accuracy_radius", NULL((void*)0)};
42static const char *empty_key[] = {NULL((void*)0)};
43
44static const char **lookup_keys[] = {
45 co_iso_key,
46 co_name_key,
47 ci_name_key,
48 asn_o_key,
49 asn_key,
50 l_lat_key,
51 l_lon_key,
52 l_accuracy_key,
53 empty_key
54};
55
56int
57main(int argc, char *argv[])
58{
59 char addr_str[MAX_ADDR_LEN46+1];
60 size_t mmdb_count = 0;
61 MMDB_s *mmdbs = NULL((void*)0), *new_mmdbs;
62 int mmdb_err;
63
64 char *out_buf = (char *) malloc(OUT_BUF_SIZE65536);
65 if (out_buf == NULL((void*)0)) {
1
Assuming 'out_buf' is not equal to NULL
2
Taking false branch
66 fprintf(stdoutstdout, "ERROR: malloc failed\n");
67 return 1;
68 }
69 setvbuf(stdoutstdout, out_buf, _IOFBF0, OUT_BUF_SIZE65536);
70
71 fprintf(stdoutstdout, "[init]\n");
72
73 // If we need to handle anything beyond "-f" we'll probably want to
74 // link with GLib and use GOption.
75 int arg_idx = 0;
76 while (arg_idx < argc - 1) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
11
Assuming the condition is false
12
Loop condition is false. Execution continues on line 103
77 if (strcmp(argv[arg_idx], "-f") == 0) {
5
Taking true branch
78 arg_idx++;
79 const char *db_arg = argv[arg_idx];
80 MMDB_s try_mmdb;
81 mmdb_err = MMDB_open(db_arg, 0, &try_mmdb);
82 fprintf(stdoutstdout, "db.%zd.path: %s\n", mmdb_count, db_arg);
83 fprintf(stdoutstdout, "db.%zd.status: ", mmdb_count);
84 if (mmdb_err == MMDB_SUCCESS(0)) {
6
Assuming 'mmdb_err' is equal to MMDB_SUCCESS
7
Taking true branch
85 mmdb_count++;
86 new_mmdbs = (MMDB_s *) realloc(mmdbs, mmdb_count * sizeof(MMDB_s));
8
Memory is allocated
87 if (new_mmdbs == NULL((void*)0)) {
9
Assuming 'new_mmdbs' is not equal to NULL
10
Taking false branch
88 free(mmdbs);
89 fprintf(stdoutstdout, "ERROR out of memory\n");
90 return 1;
91 }
92 mmdbs = new_mmdbs;
93 mmdbs[mmdb_count - 1] = try_mmdb;
94 fprintf(stdoutstdout, "OK\n");
95 fprintf(stdoutstdout, "db.%zd.type: %s\n", mmdb_count, mmdbs[mmdb_count - 1].metadata.database_type);
96 } else {
97 fprintf(stdoutstdout, "ERROR %s\n", MMDB_strerror(mmdb_err));
98 }
99 }
100 arg_idx++;
101 }
102
103 fprintf(stdoutstdout, "mmdbresolve.status: %s\n", mmdb_count
12.1
'mmdb_count' is > 0
> 0 ? "true": "false");
13
'?' condition is true
104 fprintf(stdoutstdout, "# End init\n");
105 fflush(stdoutstdout);
106
107 if (arg_idx != argc || mmdb_count < 1) {
14
Assuming 'arg_idx' is not equal to 'argc'
108 fprintf(stderrstderr, "Usage: mmdbresolve -f db_file [-f db_file ...]\n");
15
Potential leak of memory pointed to by 'mmdbs'
109 return EXIT_FAILURE1;
110 }
111
112 int in_items = 0;
113 while (in_items != EOF(-1)) {
114 int gai_err;
115
116 in_items = fscanf(stdinstdin, "%" MMDBR_STRINGIFY(MAX_ADDR_LEN)"46" "s", addr_str);
117
118 if (in_items < 1) {
119 continue;
120 }
121
122 fprintf(stdoutstdout, "[%s]\n", addr_str);
123
124#ifdef MMDB_DEBUG_SLOW
125#ifdef _WIN32
126 Sleep(1000);
127#endif
128#endif
129
130 for (size_t mmdb_idx = 0; mmdb_idx < mmdb_count; mmdb_idx++) {
131 fprintf(stdoutstdout, "# %s\n", mmdbs[mmdb_idx].metadata.database_type);
132 MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[mmdb_idx], addr_str, &gai_err, &mmdb_err);
133
134 if (result.found_entry && gai_err == 0 && mmdb_err == MMDB_SUCCESS(0)) {
135 for (size_t key_idx = 0; lookup_keys[key_idx][0]; key_idx++) {
136 MMDB_entry_data_s entry_data;
137 int status = MMDB_aget_value(&result.entry, &entry_data, lookup_keys[key_idx]);
138 if (status == MMDB_SUCCESS(0) && entry_data.has_data) {
139 char *sep = "";
140 for (int idx = 0; lookup_keys[key_idx][idx] != 0; idx++) {
141 fprintf(stdoutstdout, "%s%s", sep, lookup_keys[key_idx][idx]);
142 sep = ".";
143 }
144 switch (entry_data.type) {
145 case MMDB_DATA_TYPE_UTF8_STRING(2):
146 {
147 char len_fmt[12]; // : %.xxxxxs\n\0
148 snprintf(len_fmt, 11, ": %%.%us\n", entry_data.data_size);
149 fprintf(stdoutstdout, len_fmt, entry_data.utf8_string);
150 }
151 break;
152 case MMDB_DATA_TYPE_UINT16(5):
153 fprintf(stdoutstdout, ": %u\n", entry_data.uint16);
154 break;
155 case MMDB_DATA_TYPE_UINT32(6):
156 fprintf(stdoutstdout, ": %u\n", entry_data.uint32);
157 break;
158 case MMDB_DATA_TYPE_INT32(8):
159 fprintf(stdoutstdout, ": %d\n", entry_data.int32);
160 break;
161 case MMDB_DATA_TYPE_BOOLEAN(14):
162 fprintf(stdoutstdout, ": %s\n", entry_data.boolean ? "True" : "False");
163 break;
164 case MMDB_DATA_TYPE_DOUBLE(3):
165 fprintf(stdoutstdout, ": %f\n", entry_data.double_value);
166 break;
167 case MMDB_DATA_TYPE_FLOAT(15):
168 fprintf(stdoutstdout, ": %f\n", entry_data.float_value);
169 break;
170 default:
171 fprintf(stdoutstdout, ": UNKNOWN (%u)\n", entry_data.type);
172 }
173 }
174 }
175 } else {
176 // dump error info.
177 }
178 }
179 fprintf(stdoutstdout, "# End %s\n", addr_str);
180 fflush(stdoutstdout);
181 }
182
183 free(mmdbs);
184
185 return EXIT_SUCCESS0;
186}
187
188/*
189 * Editor modelines - https://www.wireshark.org/tools/modelines.html
190 *
191 * Local variables:
192 * c-basic-offset: 4
193 * tab-width: 8
194 * indent-tabs-mode: nil
195 * End:
196 *
197 * vi: set shiftwidth=4 tabstop=8 expandtab:
198 * :indentSize=4:tabSize=8:noTabs=true:
199 */