Bug Summary

File:builds/wireshark/wireshark/ui/qt/models/enabled_protocols_model.cpp
Warning:line 279, column 1
Potential leak of memory pointed to by 'heuristic_row'

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 enabled_protocols_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/enabled_protocols_model.cpp -o /builds/wireshark/wireshark/sbout/2024-11-18-100252-3912-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-11-18-100252-3912-1 -x c++ /builds/wireshark/wireshark/ui/qt/models/enabled_protocols_model.cpp
1/* enabled_protocols_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 <QSortFilterProxyModel>
11
12#include <ui/qt/models/enabled_protocols_model.h>
13#include <epan/packet.h>
14#include <epan/disabled_protos.h>
15
16#include <ui/qt/utils/variant_pointer.h>
17#include "main_application.h"
18
19#include <QRegularExpression>
20
21class ProtocolTreeItem : public EnabledProtocolItem
22{
23public:
24 ProtocolTreeItem(protocol_t* proto, EnabledProtocolItem* parent)
25 : EnabledProtocolItem(proto_get_protocol_short_name(proto), proto_get_protocol_long_name(proto), proto_is_protocol_enabled(proto), parent),
26 proto_(proto)
27 {
28
29 }
30
31 virtual ~ProtocolTreeItem() {}
32
33protected:
34 virtual void applyValuePrivate(bool value)
35 {
36 if (! proto_can_toggle_protocol(proto_get_id(proto_))) {
37 return;
38 }
39 proto_set_decoding(proto_get_id(proto_), value);
40 }
41
42private:
43 protocol_t* proto_;
44};
45
46class HeuristicTreeItem : public EnabledProtocolItem
47{
48public:
49 HeuristicTreeItem(heur_dtbl_entry_t *heuristic, EnabledProtocolItem* parent)
50 : EnabledProtocolItem(heuristic->short_name, heuristic->display_name, heuristic->enabled, parent),
51 heuristic_table_(heuristic)
52 {
53 type_ = EnabledProtocolItem::Heuristic;
54 }
55
56 virtual ~HeuristicTreeItem() {}
57
58protected:
59 virtual void applyValuePrivate(bool value)
60 {
61 heuristic_table_->enabled = value;
62 }
63
64private:
65 heur_dtbl_entry_t *heuristic_table_;
66};
67
68
69EnabledProtocolItem::EnabledProtocolItem(QString name, QString description, bool enabled, EnabledProtocolItem* parent) :
70 ModelHelperTreeItem<EnabledProtocolItem>(parent),
71 name_(name),
72 description_(description),
73 enabled_(enabled),
74 enabledInit_(enabled),
75 type_(EnabledProtocolItem::Standard)
76{
77}
78
79EnabledProtocolItem::~EnabledProtocolItem()
80{
81}
82
83EnabledProtocolItem::EnableProtocolType EnabledProtocolItem::type() const
84{
85 return type_;
86}
87
88bool EnabledProtocolItem::applyValue()
89{
90 if (enabledInit_ != enabled_) {
91 applyValuePrivate(enabled_);
92 return true;
93 }
94
95 return false;
96}
97
98
99
100
101EnabledProtocolsModel::EnabledProtocolsModel(QObject *parent) :
102 QAbstractItemModel(parent),
103 root_(new ProtocolTreeItem(NULL__null, NULL__null))
104{
105}
106
107EnabledProtocolsModel::~EnabledProtocolsModel()
108{
109 delete root_;
110}
111
112int EnabledProtocolsModel::rowCount(const QModelIndex &parent) const
113{
114 EnabledProtocolItem *parent_item;
115 if (parent.column() > 0)
116 return 0;
117
118 if (!parent.isValid())
119 parent_item = root_;
120 else
121 parent_item = static_cast<EnabledProtocolItem*>(parent.internalPointer());
122
123 if (parent_item == NULL__null)
124 return 0;
125
126 return parent_item->childCount();
127}
128
129int EnabledProtocolsModel::columnCount(const QModelIndex&) const
130{
131 return colLast;
132}
133
134QVariant EnabledProtocolsModel::headerData(int section, Qt::Orientation orientation, int role) const
135{
136 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
137
138 switch ((enum EnabledProtocolsColumn)section) {
139 case colProtocol:
140 return tr("Protocol");
141 case colDescription:
142 return tr("Description");
143 default:
144 break;
145 }
146 }
147 return QVariant();
148}
149
150QModelIndex EnabledProtocolsModel::parent(const QModelIndex& index) const
151{
152 if (!index.isValid())
153 return QModelIndex();
154
155 EnabledProtocolItem* item = static_cast<EnabledProtocolItem*>(index.internalPointer());
156 if (item != NULL__null) {
157 EnabledProtocolItem* parent_item = item->parentItem();
158 if (parent_item != NULL__null) {
159 if (parent_item == root_)
160 return QModelIndex();
161
162 return createIndex(parent_item->row(), 0, parent_item);
163 }
164 }
165
166 return QModelIndex();
167}
168
169QModelIndex EnabledProtocolsModel::index(int row, int column, const QModelIndex& parent) const
170{
171 if (!hasIndex(row, column, parent))
172 return QModelIndex();
173
174 EnabledProtocolItem *parent_item, *child_item;
175
176 if (!parent.isValid())
177 parent_item = root_;
178 else
179 parent_item = static_cast<EnabledProtocolItem*>(parent.internalPointer());
180
181 Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item"
, "ui/qt/models/enabled_protocols_model.cpp", 181))
;
182
183 child_item = parent_item->child(row);
184 if (child_item) {
185 return createIndex(row, column, child_item);
186 }
187
188 return QModelIndex();
189}
190
191Qt::ItemFlags EnabledProtocolsModel::flags(const QModelIndex &index) const
192{
193 if (!index.isValid())
194 return Qt::ItemFlags();
195
196 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
197 switch(index.column())
198 {
199 case colProtocol:
200 flags |= Qt::ItemIsUserCheckable;
201 break;
202 default:
203 break;
204 }
205
206 return flags;
207}
208
209QVariant EnabledProtocolsModel::data(const QModelIndex &index, int role) const
210{
211 if (!index.isValid())
212 return QVariant();
213
214 EnabledProtocolItem* item = static_cast<EnabledProtocolItem*>(index.internalPointer());
215 if (item == NULL__null)
216 return QVariant();
217
218 switch (role)
219 {
220 case Qt::DisplayRole:
221 switch ((enum EnabledProtocolsColumn)index.column())
222 {
223 case colProtocol:
224 return item->name();
225 case colDescription:
226 return item->description();
227 default:
228 break;
229 }
230 break;
231 case Qt::CheckStateRole:
232 switch ((enum EnabledProtocolsColumn)index.column())
233 {
234 case colProtocol:
235 return item->enabled() ? Qt::Checked : Qt::Unchecked;
236 default:
237 break;
238 }
239 break;
240 case DATA_PROTOCOL_TYPE:
241 return QVariant::fromValue(item->type());
242 default:
243 break;
244 }
245
246 return QVariant();
247}
248
249bool EnabledProtocolsModel::setData(const QModelIndex &index, const QVariant &value, int role)
250{
251 if (!index.isValid())
252 return false;
253
254 if ((role != Qt::EditRole) &&
255 ((index.column() == colProtocol) && (role != Qt::CheckStateRole)))
256 return false;
257
258 if (data(index, role) == value) {
259 // Data appears unchanged, do not do additional checks.
260 return true;
261 }
262
263 EnabledProtocolItem* item = static_cast<EnabledProtocolItem*>(index.internalPointer());
264 if (item == NULL__null)
265 return false;
266
267 item->setEnabled(value.toInt() == Qt::Checked ? true : false);
268
269 return true;
270}
271
272static void addHeuristicItem(void *data, void *user_data)
273{
274 heur_dtbl_entry_t* heur = (heur_dtbl_entry_t*)data;
275 ProtocolTreeItem* protocol_item = (ProtocolTreeItem*)user_data;
276
277 HeuristicTreeItem* heuristic_row = new HeuristicTreeItem(heur, protocol_item);
1
Memory is allocated
278 protocol_item->prependChild(heuristic_row);
279}
2
Potential leak of memory pointed to by 'heuristic_row'
280
281void EnabledProtocolsModel::populate()
282{
283 void *cookie;
284 protocol_t *protocol;
285
286 beginResetModel();
287
288 // Iterate over all the protocols
289 for (int i = proto_get_first_protocol(&cookie); i != -1; i = proto_get_next_protocol(&cookie))
290 {
291 if (proto_can_toggle_protocol(i))
292 {
293 protocol = find_protocol_by_id(i);
294 if (!proto_is_pino(protocol)) {
295 ProtocolTreeItem* protocol_row = new ProtocolTreeItem(protocol, root_);
296 root_->prependChild(protocol_row);
297
298 proto_heuristic_dissector_foreach(protocol, addHeuristicItem, protocol_row);
299 }
300 }
301 }
302
303 endResetModel();
304}
305
306void EnabledProtocolsModel::applyChanges(bool writeChanges)
307{
308 bool redissect = false;
309
310 for (int proto_index = 0; proto_index < root_->childCount(); proto_index++) {
311 EnabledProtocolItem* proto = root_->child(proto_index);
312 redissect |= proto->applyValue();
313 for (int heur_index = 0; heur_index < proto->childCount(); heur_index++) {
314 EnabledProtocolItem* heur = proto->child(heur_index);
315 redissect |= heur->applyValue();
316 }
317 }
318
319 if (redissect) {
320 saveChanges(writeChanges);
321 }
322}
323
324void EnabledProtocolsModel::disableProtocol(struct _protocol *protocol)
325{
326 ProtocolTreeItem disabled_proto(protocol, NULL__null);
327 disabled_proto.setEnabled(false);
328 if (disabled_proto.applyValue()) {
329 saveChanges();
330 }
331}
332
333void EnabledProtocolsModel::saveChanges(bool writeChanges)
334{
335 if (writeChanges) {
336 save_enabled_and_disabled_lists();
337 }
338 mainApp->emitAppSignal(MainApplication::PacketDissectionChanged);
339}
340
341
342EnabledProtocolsProxyModel::EnabledProtocolsProxyModel(QObject * parent)
343: QSortFilterProxyModel(parent),
344type_(EnabledProtocolsProxyModel::EveryWhere),
345protocolType_(EnabledProtocolItem::Any),
346filter_()
347{}
348
349bool EnabledProtocolsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
350{
351 //Use EnabledProtocolItem directly for better performance
352 EnabledProtocolItem* left_item = static_cast<EnabledProtocolItem*>(left.internalPointer());
353 EnabledProtocolItem* right_item = static_cast<EnabledProtocolItem*>(right.internalPointer());
354
355 if ((left_item != NULL__null) && (right_item != NULL__null)) {
356
357 int compare_ret = 0;
358
359 if (left.column() == EnabledProtocolsModel::colProtocol)
360 compare_ret = left_item->name().compare(right_item->name(), Qt::CaseInsensitive);
361 else if (left.column() == EnabledProtocolsModel::colDescription)
362 compare_ret = left_item->description().compare(right_item->description(), Qt::CaseInsensitive);
363
364 if (compare_ret < 0)
365 return true;
366 }
367
368 return false;
369}
370
371Qt::ItemFlags EnabledProtocolsProxyModel::flags(const QModelIndex &index) const
372{
373 Qt::ItemFlags flags = Qt::NoItemFlags;
374 if (index.isValid())
375 {
376 QModelIndex source = mapToSource(index);
377 if (filterAcceptsSelf(source.row(), source.parent()) )
378 {
379 flags = Qt::ItemIsEnabled;
380 flags |= Qt::ItemIsSelectable;
381 flags |= Qt::ItemIsUserCheckable;
382 }
383 }
384
385 return flags;
386}
387
388bool EnabledProtocolsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
389{
390 if (filterAcceptsSelf(sourceRow, sourceParent))
391 return true;
392
393#if 0
394 QModelIndex parent = sourceParent;
395 while (parent.isValid())
396 {
397 if (filterAcceptsSelf(parent.row(), parent.parent()))
398 return true;
399 parent = parent.parent();
400 }
401#endif
402
403 if (filterAcceptsChild(sourceRow, sourceParent))
404 return true;
405
406 return false;
407}
408
409bool EnabledProtocolsProxyModel::filterAcceptsSelf(int sourceRow, const QModelIndex &sourceParent) const
410{
411 QModelIndex nameIdx = sourceModel()->index(sourceRow, EnabledProtocolsModel::colProtocol, sourceParent);
412 if (! nameIdx.isValid())
413 return false;
414 EnabledProtocolItem* item = static_cast<EnabledProtocolItem*>(nameIdx.internalPointer());
415 if (! item)
416 return false;
417
418 QRegularExpression regex(filter_, QRegularExpression::CaseInsensitiveOption);
419 if (! regex.isValid())
420 return false;
421
422 if (protocolType_ == EnabledProtocolItem::Any || protocolType_ == item->type())
423 {
424 if (type_ != EnabledProtocolsProxyModel::EnabledItems && type_ != EnabledProtocolsProxyModel::DisabledItems)
425 {
426 if (! filter_.isEmpty())
427 {
428 if (item->name().contains(regex) && type_ != OnlyDescription)
429 return true;
430
431 if (item->description().contains(regex) && type_ != OnlyProtocol)
432 return true;
433 }
434 else
435 return true;
436 }
437 else if (filter_.isEmpty() || (! filter_.isEmpty() && (item->name().contains(regex) || item->description().contains(regex))))
438 {
439 if (type_ == EnabledProtocolsProxyModel::EnabledItems && item->enabled())
440 return true;
441 else if (type_ == EnabledProtocolsProxyModel::DisabledItems && ! item->enabled())
442 return true;
443 }
444 }
445
446 return false;
447}
448
449bool EnabledProtocolsProxyModel::filterAcceptsChild(int sourceRow, const QModelIndex &sourceParent) const
450{
451 QModelIndex item = sourceModel()->index(sourceRow, EnabledProtocolsModel::colProtocol, sourceParent);
452 if (! item.isValid())
453 return false;
454
455 int childCount = item.model()->rowCount(item);
456 if (childCount == 0)
457 return false;
458
459 for (int i = 0; i < childCount; i++)
460 {
461 if (filterAcceptsSelf(i, item))
462 return true;
463#if 0
464 /* Recursive search disabled for performance reasons */
465 if (filterAcceptsChild(i, item))
466 return true;
467#endif
468 }
469
470 return false;
471}
472
473void EnabledProtocolsProxyModel::setFilter(const QString& filter, EnabledProtocolsProxyModel::SearchType type,
474 EnabledProtocolItem::EnableProtocolType protocolType)
475{
476 filter_ = filter;
477 type_ = type;
478 protocolType_ = protocolType;
479 invalidateFilter();
480}
481
482void EnabledProtocolsProxyModel::setItemsEnable(EnabledProtocolsProxyModel::EnableType enableType, QModelIndex parent)
483{
484 if (! sourceModel())
485 return;
486
487 if (! parent.isValid())
488 beginResetModel();
489
490 int rowcount = rowCount(parent);
491 for (int row = 0; row < rowcount; row++)
492 {
493 QModelIndex idx = index(row, EnabledProtocolsModel::colProtocol, parent);
494
495 QModelIndex sIdx = mapToSource(idx);
496 if (sIdx.isValid())
497 {
498 EnabledProtocolItem* item = static_cast<EnabledProtocolItem*>(sIdx.internalPointer());
499 if (item && (protocolType_ == EnabledProtocolItem::Any || protocolType_ == item->type()) )
500 {
501 Qt::CheckState enable = idx.data(Qt::CheckStateRole).value<Qt::CheckState>();
502 if (enableType == Enable)
503 enable = Qt::Checked;
504 else if (enableType == Disable)
505 enable = Qt::Unchecked;
506 else
507 enable = enable == Qt::Checked ? Qt::Unchecked : Qt::Checked;
508
509 sourceModel()->setData(mapToSource(idx), QVariant::fromValue(enable), Qt::CheckStateRole);
510 }
511 }
512
513 setItemsEnable(enableType, idx);
514 }
515
516
517 if (! parent.isValid())
518 endResetModel();
519}