Bug Summary

File:builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp
Warning:line 299, column 1
Potential leak of memory pointed to by 'heur'

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 dissector_tables_model.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/build/ui/qt -isystem /builds/wireshark/wireshark/ui/qt -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore5Compat -isystem /usr/include/x86_64-linux-gnu/qt6/QtConcurrent -isystem /usr/include/x86_64-linux-gnu/qt6/QtPrintSupport -isystem /usr/include/x86_64-linux-gnu/qt6/QtMultimedia -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt6/QtDBus -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D QT_CONCURRENT_LIB -D QT_CORE5COMPAT_LIB -D QT_CORE_LIB -D QT_DBUS_LIB -D QT_GUI_LIB -D QT_MULTIMEDIA_LIB -D QT_NETWORK_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build/ui/qt/qtui_autogen/include -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -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 -std=c++17 -fdeprecated-macro -ferror-limit 19 -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang --driver-mode=g++ -### --analyze -x c++ -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D QT_CONCURRENT_LIB -D QT_CORE5COMPAT_LIB -D QT_CORE_LIB -D QT_DBUS_LIB -D QT_GUI_LIB -D QT_MULTIMEDIA_LIB -D QT_NETWORK_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build/ui/qt/qtui_autogen/include -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 -isystem /builds/wireshark/wireshark/build/ui/qt -isystem /builds/wireshark/wireshark/ui/qt -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore5Compat -isystem /usr/include/x86_64-linux-gnu/qt6/QtConcurrent -isystem /usr/include/x86_64-linux-gnu/qt6/QtPrintSupport -isystem /usr/include/x86_64-linux-gnu/qt6/QtMultimedia -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/x86_64-linux-gnu/qt6/QtDBus -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 -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=c++17 -fPIC -fPIC /builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp -o /builds/wireshark/wireshark/sbout/2024-12-01-100254-3912-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-12-01-100254-3912-1 -x c++ /builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp
1/* dissector_tables_model.cpp
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <[email protected]>
5 * Copyright 1998 Gerald Combs
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include <ui/qt/models/dissector_tables_model.h>
11#include <epan/ftypes/ftypes.h>
12#include <epan/packet.h>
13
14#include <ui/qt/utils/variant_pointer.h>
15#include "main_application.h"
16
17static const char* CUSTOM_TABLE_NAME = "Custom Tables";
18static const char* INTEGER_TABLE_NAME = "Integer Tables";
19static const char* STRING_TABLE_NAME = "String Tables";
20static const char* HEURISTIC_TABLE_NAME = "Heuristic Tables";
21
22class IntegerTablesItem : public DissectorTablesItem
23{
24public:
25 IntegerTablesItem(unsigned int value, QString dissectorDescription, DissectorTablesItem* parent);
26 virtual ~IntegerTablesItem();
27
28 virtual bool lessThan(DissectorTablesItem &right) const;
29
30protected:
31 unsigned int value_;
32};
33
34
35DissectorTablesItem::DissectorTablesItem(QString tableName, QString dissectorDescription, DissectorTablesItem* parent) :
36 ModelHelperTreeItem<DissectorTablesItem>(parent),
37 tableName_(tableName),
38 dissectorDescription_(dissectorDescription)
39{
40}
41
42DissectorTablesItem::~DissectorTablesItem()
43{
44}
45
46bool DissectorTablesItem::lessThan(DissectorTablesItem &right) const
47{
48 if (tableName().compare(right.tableName(), Qt::CaseInsensitive) < 0)
49 return true;
50
51 return false;
52}
53
54
55IntegerTablesItem::IntegerTablesItem(unsigned int value, QString dissectorDescription, DissectorTablesItem* parent)
56 : DissectorTablesItem(QStringLiteral("%1")(QString(QtPrivate::qMakeStringPrivate(u"" "%1"))).arg(value), dissectorDescription, parent)
57 , value_(value)
58{
59}
60
61IntegerTablesItem::~IntegerTablesItem()
62{
63}
64
65bool IntegerTablesItem::lessThan(DissectorTablesItem &right) const
66{
67 if (value_ == ((IntegerTablesItem&)right).value_) {
68 return DissectorTablesItem::lessThan(right);
69 }
70
71 if (value_ < ((IntegerTablesItem&)right).value_) {
72 return true;
73 }
74
75 return false;
76}
77
78
79
80
81
82
83
84
85DissectorTablesModel::DissectorTablesModel(QObject *parent) :
86 QAbstractItemModel(parent),
87 root_(new DissectorTablesItem(QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), NULL__null))
88{
89 populate();
90}
91
92DissectorTablesModel::~DissectorTablesModel()
93{
94 delete root_;
95}
96
97int DissectorTablesModel::rowCount(const QModelIndex &parent) const
98{
99 DissectorTablesItem *parent_item;
100 if (parent.column() > 0)
101 return 0;
102
103 if (!parent.isValid())
104 parent_item = root_;
105 else
106 parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer());
107
108 if (parent_item == NULL__null)
109 return 0;
110
111 return parent_item->childCount();
112}
113
114int DissectorTablesModel::columnCount(const QModelIndex&) const
115{
116 return colLast;
117}
118
119QModelIndex DissectorTablesModel::parent(const QModelIndex& index) const
120{
121 if (!index.isValid())
122 return QModelIndex();
123
124 DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer());
125 if (item != NULL__null) {
126 DissectorTablesItem* parent_item = item->parentItem();
127 if (parent_item != NULL__null) {
128 if (parent_item == root_)
129 return QModelIndex();
130
131 return createIndex(parent_item->row(), 0, parent_item);
132 }
133 }
134
135 return QModelIndex();
136}
137
138QModelIndex DissectorTablesModel::index(int row, int column, const QModelIndex& parent) const
139{
140 if (!hasIndex(row, column, parent))
141 return QModelIndex();
142
143 DissectorTablesItem *parent_item, *child_item;
144
145 if (!parent.isValid())
146 parent_item = root_;
147 else
148 parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer());
149
150 Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item"
, "ui/qt/models/dissector_tables_model.cpp", 150))
;
151
152 child_item = parent_item->child(row);
153 if (child_item) {
154 return createIndex(row, column, child_item);
155 }
156
157 return QModelIndex();
158}
159
160QVariant DissectorTablesModel::data(const QModelIndex &index, int role) const
161{
162 if ((!index.isValid()) || (role != Qt::DisplayRole))
163 return QVariant();
164
165 DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer());
166 if (item == NULL__null)
167 return QVariant();
168
169 switch ((enum DissectorTablesColumn)index.column())
170 {
171 case colTableName:
172 return item->tableName();
173 case colDissectorDescription:
174 return item->dissectorDescription();
175 default:
176 break;
177 }
178
179 return QVariant();
180}
181
182static void gatherProtocolDecodes(const char *, ftenum_t selector_type, void *key, void *value, void *item_ptr)
183{
184 DissectorTablesItem* pdl_ptr = (DissectorTablesItem*)item_ptr;
185 if (pdl_ptr == NULL__null)
186 return;
187
188 dtbl_entry_t *dtbl_entry = (dtbl_entry_t*)value;
189 dissector_handle_t handle = dtbl_entry_get_handle(dtbl_entry);
190 const QString dissector_description = dissector_handle_get_description(handle);
191 DissectorTablesItem *ti = NULL__null;
192
193 switch (selector_type) {
194 case FT_UINT8:
195 case FT_UINT16:
196 case FT_UINT24:
197 case FT_UINT32:
198 ti = new IntegerTablesItem(GPOINTER_TO_UINT(key)((guint) (gulong) (key)), dissector_description, pdl_ptr);
199 pdl_ptr->prependChild(ti);
200 break;
201
202 case FT_STRING:
203 case FT_STRINGZ:
204 case FT_UINT_STRING:
205 case FT_STRINGZPAD:
206 case FT_STRINGZTRUNC:
207 ti = new DissectorTablesItem((const char *)key, dissector_description, pdl_ptr);
208 pdl_ptr->prependChild(ti);
209 break;
210
211 case FT_BYTES:
212 ti = new DissectorTablesItem(dissector_handle_get_description(handle), dissector_description, pdl_ptr);
213 pdl_ptr->prependChild(ti);
214 break;
215
216 default:
217 break;
218 }
219}
220
221struct tables_root
222{
223 DissectorTablesItem* custom_table;
224 DissectorTablesItem* integer_table;
225 DissectorTablesItem* string_table;
226};
227
228static void gatherTableNames(const char *short_name, const char *table_name, void *model_ptr)
229{
230 struct tables_root* tables = (struct tables_root*)model_ptr;
231 if (model_ptr == NULL__null)
232 return;
233
234 ftenum_t selector_type = get_dissector_table_selector_type(short_name);
235 DissectorTablesItem *dt_ti = NULL__null;
236
237 switch (selector_type) {
238 case FT_UINT8:
239 case FT_UINT16:
240 case FT_UINT24:
241 case FT_UINT32:
242 dt_ti = new DissectorTablesItem(table_name, short_name, tables->integer_table);
243 tables->integer_table->prependChild(dt_ti);
244 break;
245 case FT_STRING:
246 case FT_STRINGZ:
247 case FT_UINT_STRING:
248 case FT_STRINGZPAD:
249 case FT_STRINGZTRUNC:
250 dt_ti = new DissectorTablesItem(table_name, short_name, tables->string_table);
251 tables->string_table->prependChild(dt_ti);
252 break;
253 case FT_BYTES:
254 dt_ti = new DissectorTablesItem(table_name, short_name, tables->custom_table);
255 tables->custom_table->prependChild(dt_ti);
256 break;
257 default:
258 // Assert?
259 return;
260 }
261
262 dissector_table_foreach(short_name, gatherProtocolDecodes, dt_ti);
263}
264
265static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, void *list_ptr)
266{
267 DissectorTablesItem* hdl_ptr = (DissectorTablesItem*)list_ptr;
268 if (hdl_ptr == NULL__null)
269 return;
270
271 if (dtbl_entry->protocol) {
272 QString longName = proto_get_protocol_long_name(dtbl_entry->protocol);
273 QString heurDisplayName = dtbl_entry->display_name;
274 if (! heurDisplayName.isEmpty())
275 longName.append(QStringLiteral(" (%1)")(QString(QtPrivate::qMakeStringPrivate(u"" " (%1)"))).arg(heurDisplayName));
276
277 DissectorTablesItem *heur = new DissectorTablesItem(longName, proto_get_protocol_short_name(dtbl_entry->protocol), hdl_ptr);
278 hdl_ptr->prependChild(heur);
279 }
280}
281
282static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, void *heur_tables)
283{
284 DissectorTablesItem* table = (DissectorTablesItem*)heur_tables;
285 if (table == NULL__null)
1
Assuming 'table' is not equal to NULL
2
Taking false branch
286 return;
287
288 QString desc_name = table_name;
289 if (list) {
3
Assuming 'list' is null
4
Taking false branch
290 const char *desc = heur_dissector_list_get_description(list);
291 if (desc) desc_name = desc;
292 }
293 DissectorTablesItem *heur = new DissectorTablesItem(desc_name, table_name, table);
5
Memory is allocated
294 table->prependChild(heur);
295
296 if (list
5.1
'list' is null
) {
6
Taking false branch
297 heur_dissector_table_foreach(table_name, gatherHeurProtocolDecodes, heur);
298 }
299}
7
Potential leak of memory pointed to by 'heur'
300
301void DissectorTablesModel::populate()
302{
303 beginResetModel();
304
305 struct tables_root tables;
306
307 tables.custom_table = new DissectorTablesItem(tr(CUSTOM_TABLE_NAME), QString(""), root_);
308 root_->prependChild(tables.custom_table);
309 tables.integer_table = new DissectorTablesItem(tr(INTEGER_TABLE_NAME), QString(""), root_);
310 root_->prependChild(tables.integer_table);
311 tables.string_table = new DissectorTablesItem(tr(STRING_TABLE_NAME), QString(""), root_);
312 root_->prependChild(tables.string_table);
313
314 dissector_all_tables_foreach_table(gatherTableNames, &tables, NULL__null);
315
316 DissectorTablesItem* heuristic_table = new DissectorTablesItem(tr(HEURISTIC_TABLE_NAME), QString(""), root_);
317 root_->prependChild(heuristic_table);
318
319 dissector_all_heur_tables_foreach_table(gatherHeurTableNames, heuristic_table, NULL__null);
320
321 endResetModel();
322}
323
324
325
326
327
328DissectorTablesProxyModel::DissectorTablesProxyModel(QObject * parent)
329: QSortFilterProxyModel(parent),
330tableName_(tr("Table Type")),
331dissectorDescription_(),
332filter_()
333{
334}
335
336QVariant DissectorTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
337{
338 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
339
340 switch ((enum DissectorTablesModel::DissectorTablesColumn)section) {
341 case DissectorTablesModel::colTableName:
342 return tableName_;
343 case DissectorTablesModel::colDissectorDescription:
344 return dissectorDescription_;
345 default:
346 break;
347 }
348 }
349 return QVariant();
350}
351
352bool DissectorTablesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
353{
354 //Use DissectorTablesItem directly for better performance
355 DissectorTablesItem* left_item = static_cast<DissectorTablesItem*>(left.internalPointer());
356 DissectorTablesItem* right_item = static_cast<DissectorTablesItem*>(right.internalPointer());
357
358 if ((left_item != NULL__null) && (right_item != NULL__null)) {
359 return left_item->lessThan(*right_item);
360 }
361
362 return false;
363}
364
365bool DissectorTablesProxyModel::filterAcceptItem(DissectorTablesItem& item) const
366{
367 if (filter_.isEmpty())
368 return true;
369
370 if (item.tableName().contains(filter_, Qt::CaseInsensitive) || item.dissectorDescription().contains(filter_, Qt::CaseInsensitive))
371 return true;
372
373 DissectorTablesItem *child_item;
374 for (int child_row = 0; child_row < item.childCount(); child_row++)
375 {
376 child_item = item.child(child_row);
377 if ((child_item != NULL__null) && (filterAcceptItem(*child_item)))
378 return true;
379 }
380
381 return false;
382}
383
384bool DissectorTablesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
385{
386 QModelIndex nameIdx = sourceModel()->index(sourceRow, DissectorTablesModel::colTableName, sourceParent);
387 DissectorTablesItem* item = static_cast<DissectorTablesItem*>(nameIdx.internalPointer());
388 if (item == NULL__null)
389 return false;
390
391 if (filterAcceptItem(*item))
392 return true;
393
394 return false;
395}
396
397void DissectorTablesProxyModel::setFilter(const QString& filter)
398{
399 filter_ = filter;
400 invalidateFilter();
401}
402
403void DissectorTablesProxyModel::adjustHeader(const QModelIndex &currentIndex)
404{
405 tableName_ = tr("Table Type");
406 dissectorDescription_ = QString();
407 if (currentIndex.isValid() && currentIndex.parent().isValid()) {
408 QString table;
409
410 if (currentIndex.parent().parent().isValid()) {
411 table = data(index(currentIndex.parent().parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString();
412 if ((table.compare(CUSTOM_TABLE_NAME) == 0) ||
413 (table.compare(STRING_TABLE_NAME) == 0)) {
414 tableName_ = tr("String");
415 dissectorDescription_ = tr("Dissector Description");
416 } else if (table.compare(INTEGER_TABLE_NAME) == 0) {
417 tableName_ = tr("Integer");
418 dissectorDescription_ = tr("Dissector Description");
419 } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) {
420 tableName_ = tr("Protocol");
421 dissectorDescription_ = tr("Short Name");
422 }
423 } else {
424 table = data(index(currentIndex.parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString();
425 if ((table.compare(CUSTOM_TABLE_NAME) == 0) ||
426 (table.compare(INTEGER_TABLE_NAME) == 0) ||
427 (table.compare(STRING_TABLE_NAME) == 0)) {
428 tableName_ = tr("Table Name");
429 dissectorDescription_ = tr("Selector Name");
430 } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) {
431 tableName_ = tr("Protocol");
432 dissectorDescription_ = tr("Short Name");
433 }
434 }
435 }
436
437
438 emit headerDataChanged(Qt::Vertical, 0, 1);
439}