| File: | builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp |
| Warning: | line 307, column 1 Potential leak of memory pointed to by 'heur' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* dissector_tables_model.cpp | |||
| 2 | * | |||
| 3 | * Wireshark - Network traffic analyzer | |||
| 4 | * By Gerald Combs <gerald@wireshark.org> | |||
| 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/qt_ui_utils.h> | |||
| 15 | #include <ui/qt/utils/variant_pointer.h> | |||
| 16 | #include "main_application.h" | |||
| 17 | ||||
| 18 | static const char* CUSTOM_TABLE_NAME = "Custom Tables"; | |||
| 19 | static const char* INTEGER_TABLE_NAME = "Integer Tables"; | |||
| 20 | static const char* STRING_TABLE_NAME = "String Tables"; | |||
| 21 | static const char* HEURISTIC_TABLE_NAME = "Heuristic Tables"; | |||
| 22 | ||||
| 23 | class IntegerTablesItem : public DissectorTablesItem | |||
| 24 | { | |||
| 25 | public: | |||
| 26 | IntegerTablesItem(unsigned int value, ftenum_t type, int display, QString dissectorDescription, DissectorTablesItem* parent); | |||
| 27 | virtual ~IntegerTablesItem(); | |||
| 28 | ||||
| 29 | virtual bool lessThan(DissectorTablesItem &right) const; | |||
| 30 | ||||
| 31 | protected: | |||
| 32 | unsigned int value_; | |||
| 33 | }; | |||
| 34 | ||||
| 35 | ||||
| 36 | DissectorTablesItem::DissectorTablesItem(QString tableName, QString dissectorDescription, DissectorTablesItem* parent) : | |||
| 37 | ModelHelperTreeItem<DissectorTablesItem>(parent), | |||
| 38 | tableName_(tableName), | |||
| 39 | dissectorDescription_(dissectorDescription) | |||
| 40 | { | |||
| 41 | } | |||
| 42 | ||||
| 43 | DissectorTablesItem::~DissectorTablesItem() | |||
| 44 | { | |||
| 45 | } | |||
| 46 | ||||
| 47 | bool DissectorTablesItem::lessThan(DissectorTablesItem &right) const | |||
| 48 | { | |||
| 49 | if (tableName().compare(right.tableName(), Qt::CaseInsensitive) < 0) | |||
| 50 | return true; | |||
| 51 | ||||
| 52 | return false; | |||
| 53 | } | |||
| 54 | ||||
| 55 | ||||
| 56 | IntegerTablesItem::IntegerTablesItem(unsigned int value, ftenum_t type, int display, QString dissectorDescription, DissectorTablesItem* parent) | |||
| 57 | : DissectorTablesItem(QString(), dissectorDescription, parent) | |||
| 58 | , value_(value) | |||
| 59 | { | |||
| 60 | switch (display) | |||
| 61 | { | |||
| 62 | case BASE_OCT: | |||
| 63 | tableName_ = QStringLiteral("0%1")(QString(QtPrivate::qMakeStringPrivate(u"" "0%1"))).arg(value, 0, 8); | |||
| 64 | break; | |||
| 65 | case BASE_HEX: | |||
| 66 | int field_width; | |||
| 67 | ||||
| 68 | switch (type) | |||
| 69 | { | |||
| 70 | case FT_UINT8: | |||
| 71 | field_width = 2; | |||
| 72 | break; | |||
| 73 | case FT_UINT16: | |||
| 74 | field_width = 4; | |||
| 75 | break; | |||
| 76 | case FT_UINT24: | |||
| 77 | field_width = 6; | |||
| 78 | break; | |||
| 79 | case FT_UINT32: | |||
| 80 | default: | |||
| 81 | field_width = 8; | |||
| 82 | break; | |||
| 83 | } | |||
| 84 | ||||
| 85 | tableName_ = int_to_qstring(value, field_width, 16); | |||
| 86 | break; | |||
| 87 | case BASE_DEC: | |||
| 88 | default: | |||
| 89 | tableName_ = QString::number(value); | |||
| 90 | break; | |||
| 91 | } | |||
| 92 | } | |||
| 93 | ||||
| 94 | IntegerTablesItem::~IntegerTablesItem() | |||
| 95 | { | |||
| 96 | } | |||
| 97 | ||||
| 98 | bool IntegerTablesItem::lessThan(DissectorTablesItem &right) const | |||
| 99 | { | |||
| 100 | if (value_ == ((IntegerTablesItem&)right).value_) { | |||
| 101 | return DissectorTablesItem::lessThan(right); | |||
| 102 | } | |||
| 103 | ||||
| 104 | if (value_ < ((IntegerTablesItem&)right).value_) { | |||
| 105 | return true; | |||
| 106 | } | |||
| 107 | ||||
| 108 | return false; | |||
| 109 | } | |||
| 110 | ||||
| 111 | DissectorTablesModel::DissectorTablesModel(QObject *parent) : | |||
| 112 | QAbstractItemModel(parent), | |||
| 113 | root_(new DissectorTablesItem(QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), NULL__null)) | |||
| 114 | { | |||
| 115 | populate(); | |||
| 116 | } | |||
| 117 | ||||
| 118 | DissectorTablesModel::~DissectorTablesModel() | |||
| 119 | { | |||
| 120 | delete root_; | |||
| 121 | } | |||
| 122 | ||||
| 123 | int DissectorTablesModel::rowCount(const QModelIndex &parent) const | |||
| 124 | { | |||
| 125 | DissectorTablesItem *parent_item; | |||
| 126 | if (parent.column() > 0) | |||
| 127 | return 0; | |||
| 128 | ||||
| 129 | if (!parent.isValid()) | |||
| 130 | parent_item = root_; | |||
| 131 | else | |||
| 132 | parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer()); | |||
| 133 | ||||
| 134 | if (parent_item == NULL__null) | |||
| 135 | return 0; | |||
| 136 | ||||
| 137 | return parent_item->childCount(); | |||
| 138 | } | |||
| 139 | ||||
| 140 | int DissectorTablesModel::columnCount(const QModelIndex&) const | |||
| 141 | { | |||
| 142 | return colLast; | |||
| 143 | } | |||
| 144 | ||||
| 145 | QModelIndex DissectorTablesModel::parent(const QModelIndex& index) const | |||
| 146 | { | |||
| 147 | if (!index.isValid()) | |||
| 148 | return QModelIndex(); | |||
| 149 | ||||
| 150 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer()); | |||
| 151 | if (item != NULL__null) { | |||
| 152 | DissectorTablesItem* parent_item = item->parentItem(); | |||
| 153 | if (parent_item != NULL__null) { | |||
| 154 | if (parent_item == root_) | |||
| 155 | return QModelIndex(); | |||
| 156 | ||||
| 157 | return createIndex(parent_item->row(), 0, parent_item); | |||
| 158 | } | |||
| 159 | } | |||
| 160 | ||||
| 161 | return QModelIndex(); | |||
| 162 | } | |||
| 163 | ||||
| 164 | QModelIndex DissectorTablesModel::index(int row, int column, const QModelIndex& parent) const | |||
| 165 | { | |||
| 166 | if (!hasIndex(row, column, parent)) | |||
| 167 | return QModelIndex(); | |||
| 168 | ||||
| 169 | DissectorTablesItem *parent_item, *child_item; | |||
| 170 | ||||
| 171 | if (!parent.isValid()) | |||
| 172 | parent_item = root_; | |||
| 173 | else | |||
| 174 | parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer()); | |||
| 175 | ||||
| 176 | Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item" , "ui/qt/models/dissector_tables_model.cpp", 176)); | |||
| 177 | ||||
| 178 | child_item = parent_item->child(row); | |||
| 179 | if (child_item) { | |||
| 180 | return createIndex(row, column, child_item); | |||
| 181 | } | |||
| 182 | ||||
| 183 | return QModelIndex(); | |||
| 184 | } | |||
| 185 | ||||
| 186 | QVariant DissectorTablesModel::data(const QModelIndex &index, int role) const | |||
| 187 | { | |||
| 188 | if ((!index.isValid()) || (role != Qt::DisplayRole)) | |||
| 189 | return QVariant(); | |||
| 190 | ||||
| 191 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer()); | |||
| 192 | if (item == NULL__null) | |||
| 193 | return QVariant(); | |||
| 194 | ||||
| 195 | switch ((enum DissectorTablesColumn)index.column()) | |||
| 196 | { | |||
| 197 | case colTableName: | |||
| 198 | return item->tableName(); | |||
| 199 | case colDissectorDescription: | |||
| 200 | return item->dissectorDescription(); | |||
| 201 | default: | |||
| 202 | break; | |||
| 203 | } | |||
| 204 | ||||
| 205 | return QVariant(); | |||
| 206 | } | |||
| 207 | ||||
| 208 | static void gatherProtocolDecodes(const char *short_name, ftenum_t selector_type, void *key, void *value, void *item_ptr) | |||
| 209 | { | |||
| 210 | DissectorTablesItem* pdl_ptr = (DissectorTablesItem*)item_ptr; | |||
| 211 | if (pdl_ptr == NULL__null) | |||
| 212 | return; | |||
| 213 | ||||
| 214 | dtbl_entry_t *dtbl_entry = (dtbl_entry_t*)value; | |||
| 215 | dissector_handle_t handle = dtbl_entry_get_handle(dtbl_entry); | |||
| 216 | const QString dissector_description = dissector_handle_get_description(handle); | |||
| 217 | int display = get_dissector_table_param(short_name); | |||
| 218 | DissectorTablesItem *ti = NULL__null; | |||
| 219 | ||||
| 220 | switch (selector_type) { | |||
| 221 | case FT_UINT8: | |||
| 222 | case FT_UINT16: | |||
| 223 | case FT_UINT24: | |||
| 224 | case FT_UINT32: | |||
| 225 | ti = new IntegerTablesItem(GPOINTER_TO_UINT(key)((guint) (gulong) (key)), selector_type, display, dissector_description, pdl_ptr); | |||
| 226 | pdl_ptr->prependChild(ti); | |||
| 227 | break; | |||
| 228 | ||||
| 229 | case FT_STRING: | |||
| 230 | case FT_STRINGZ: | |||
| 231 | case FT_UINT_STRING: | |||
| 232 | case FT_STRINGZPAD: | |||
| 233 | case FT_STRINGZTRUNC: | |||
| 234 | ti = new DissectorTablesItem((const char *)key, dissector_description, pdl_ptr); | |||
| 235 | pdl_ptr->prependChild(ti); | |||
| 236 | break; | |||
| 237 | ||||
| 238 | case FT_BYTES: | |||
| 239 | ti = new DissectorTablesItem(dissector_handle_get_description(handle), dissector_description, pdl_ptr); | |||
| 240 | pdl_ptr->prependChild(ti); | |||
| 241 | break; | |||
| 242 | ||||
| 243 | default: | |||
| 244 | break; | |||
| 245 | } | |||
| 246 | } | |||
| 247 | ||||
| 248 | struct tables_root | |||
| 249 | { | |||
| 250 | DissectorTablesItem* custom_table; | |||
| 251 | DissectorTablesItem* integer_table; | |||
| 252 | DissectorTablesItem* string_table; | |||
| 253 | }; | |||
| 254 | ||||
| 255 | static void gatherTableNames(const char *short_name, const char *table_name, void *model_ptr) | |||
| 256 | { | |||
| 257 | struct tables_root* tables = (struct tables_root*)model_ptr; | |||
| 258 | if (model_ptr == NULL__null) | |||
| 259 | return; | |||
| 260 | ||||
| 261 | ftenum_t selector_type = get_dissector_table_selector_type(short_name); | |||
| 262 | DissectorTablesItem *dt_ti = NULL__null; | |||
| 263 | ||||
| 264 | switch (selector_type) { | |||
| 265 | case FT_UINT8: | |||
| 266 | case FT_UINT16: | |||
| 267 | case FT_UINT24: | |||
| 268 | case FT_UINT32: | |||
| 269 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->integer_table); | |||
| 270 | tables->integer_table->prependChild(dt_ti); | |||
| 271 | break; | |||
| 272 | case FT_STRING: | |||
| 273 | case FT_STRINGZ: | |||
| 274 | case FT_UINT_STRING: | |||
| 275 | case FT_STRINGZPAD: | |||
| 276 | case FT_STRINGZTRUNC: | |||
| 277 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->string_table); | |||
| 278 | tables->string_table->prependChild(dt_ti); | |||
| 279 | break; | |||
| 280 | case FT_BYTES: | |||
| 281 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->custom_table); | |||
| 282 | tables->custom_table->prependChild(dt_ti); | |||
| 283 | break; | |||
| 284 | default: | |||
| 285 | // Assert? | |||
| 286 | return; | |||
| 287 | } | |||
| 288 | ||||
| 289 | dissector_table_foreach(short_name, gatherProtocolDecodes, dt_ti); | |||
| 290 | } | |||
| 291 | ||||
| 292 | static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, void *list_ptr) | |||
| 293 | { | |||
| 294 | DissectorTablesItem* hdl_ptr = (DissectorTablesItem*)list_ptr; | |||
| 295 | if (hdl_ptr == NULL__null) | |||
| ||||
| 296 | return; | |||
| 297 | ||||
| 298 | if (dtbl_entry->protocol) { | |||
| 299 | QString longName = proto_get_protocol_long_name(dtbl_entry->protocol); | |||
| 300 | QString heurDisplayName = dtbl_entry->display_name; | |||
| 301 | if (! heurDisplayName.isEmpty()) | |||
| 302 | longName.append(QStringLiteral(" (%1)")(QString(QtPrivate::qMakeStringPrivate(u"" " (%1)"))).arg(heurDisplayName)); | |||
| 303 | ||||
| 304 | DissectorTablesItem *heur = new DissectorTablesItem(longName, proto_get_protocol_short_name(dtbl_entry->protocol), hdl_ptr); | |||
| 305 | hdl_ptr->prependChild(heur); | |||
| 306 | } | |||
| 307 | } | |||
| ||||
| 308 | ||||
| 309 | static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, void *heur_tables) | |||
| 310 | { | |||
| 311 | DissectorTablesItem* table = (DissectorTablesItem*)heur_tables; | |||
| 312 | if (table == NULL__null) | |||
| 313 | return; | |||
| 314 | ||||
| 315 | QString desc_name = table_name; | |||
| 316 | if (list) { | |||
| 317 | const char *desc = heur_dissector_list_get_description(list); | |||
| 318 | if (desc) desc_name = desc; | |||
| 319 | } | |||
| 320 | DissectorTablesItem *heur = new DissectorTablesItem(desc_name, table_name, table); | |||
| 321 | table->prependChild(heur); | |||
| 322 | ||||
| 323 | if (list) { | |||
| 324 | heur_dissector_table_foreach(table_name, gatherHeurProtocolDecodes, heur); | |||
| 325 | } | |||
| 326 | } | |||
| 327 | ||||
| 328 | void DissectorTablesModel::populate() | |||
| 329 | { | |||
| 330 | beginResetModel(); | |||
| 331 | ||||
| 332 | struct tables_root tables; | |||
| 333 | ||||
| 334 | tables.custom_table = new DissectorTablesItem(tr(CUSTOM_TABLE_NAME), QString(""), root_); | |||
| 335 | root_->prependChild(tables.custom_table); | |||
| 336 | tables.integer_table = new DissectorTablesItem(tr(INTEGER_TABLE_NAME), QString(""), root_); | |||
| 337 | root_->prependChild(tables.integer_table); | |||
| 338 | tables.string_table = new DissectorTablesItem(tr(STRING_TABLE_NAME), QString(""), root_); | |||
| 339 | root_->prependChild(tables.string_table); | |||
| 340 | ||||
| 341 | dissector_all_tables_foreach_table(gatherTableNames, &tables, NULL__null); | |||
| 342 | ||||
| 343 | DissectorTablesItem* heuristic_table = new DissectorTablesItem(tr(HEURISTIC_TABLE_NAME), QString(""), root_); | |||
| 344 | root_->prependChild(heuristic_table); | |||
| 345 | ||||
| 346 | dissector_all_heur_tables_foreach_table(gatherHeurTableNames, heuristic_table, NULL__null); | |||
| 347 | ||||
| 348 | endResetModel(); | |||
| 349 | } | |||
| 350 | ||||
| 351 | ||||
| 352 | ||||
| 353 | ||||
| 354 | ||||
| 355 | DissectorTablesProxyModel::DissectorTablesProxyModel(QObject * parent) | |||
| 356 | : QSortFilterProxyModel(parent), | |||
| 357 | tableName_(tr("Table Type")), | |||
| 358 | dissectorDescription_(), | |||
| 359 | filter_() | |||
| 360 | { | |||
| 361 | } | |||
| 362 | ||||
| 363 | QVariant DissectorTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const | |||
| 364 | { | |||
| 365 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | |||
| 366 | ||||
| 367 | switch ((enum DissectorTablesModel::DissectorTablesColumn)section) { | |||
| 368 | case DissectorTablesModel::colTableName: | |||
| 369 | return tableName_; | |||
| 370 | case DissectorTablesModel::colDissectorDescription: | |||
| 371 | return dissectorDescription_; | |||
| 372 | default: | |||
| 373 | break; | |||
| 374 | } | |||
| 375 | } | |||
| 376 | return QVariant(); | |||
| 377 | } | |||
| 378 | ||||
| 379 | bool DissectorTablesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const | |||
| 380 | { | |||
| 381 | //Use DissectorTablesItem directly for better performance | |||
| 382 | DissectorTablesItem* left_item = static_cast<DissectorTablesItem*>(left.internalPointer()); | |||
| 383 | DissectorTablesItem* right_item = static_cast<DissectorTablesItem*>(right.internalPointer()); | |||
| 384 | ||||
| 385 | if ((left_item != NULL__null) && (right_item != NULL__null)) { | |||
| 386 | return left_item->lessThan(*right_item); | |||
| 387 | } | |||
| 388 | ||||
| 389 | return false; | |||
| 390 | } | |||
| 391 | ||||
| 392 | // NOLINTNEXTLINE(misc-no-recursion) | |||
| 393 | bool DissectorTablesProxyModel::filterAcceptItem(DissectorTablesItem& item) const | |||
| 394 | { | |||
| 395 | if (filter_.isEmpty()) | |||
| 396 | return true; | |||
| 397 | ||||
| 398 | if (item.tableName().contains(filter_, Qt::CaseInsensitive) || item.dissectorDescription().contains(filter_, Qt::CaseInsensitive)) | |||
| 399 | return true; | |||
| 400 | ||||
| 401 | DissectorTablesItem *child_item; | |||
| 402 | for (int child_row = 0; child_row < item.childCount(); child_row++) | |||
| 403 | { | |||
| 404 | child_item = item.child(child_row); | |||
| 405 | // We recurse here, but the tree is only three levels deep | |||
| 406 | if ((child_item != NULL__null) && (filterAcceptItem(*child_item))) | |||
| 407 | return true; | |||
| 408 | } | |||
| 409 | ||||
| 410 | return false; | |||
| 411 | } | |||
| 412 | ||||
| 413 | bool DissectorTablesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const | |||
| 414 | { | |||
| 415 | QModelIndex nameIdx = sourceModel()->index(sourceRow, DissectorTablesModel::colTableName, sourceParent); | |||
| 416 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(nameIdx.internalPointer()); | |||
| 417 | if (item == NULL__null) | |||
| 418 | return false; | |||
| 419 | ||||
| 420 | if (filterAcceptItem(*item)) | |||
| 421 | return true; | |||
| 422 | ||||
| 423 | return false; | |||
| 424 | } | |||
| 425 | ||||
| 426 | void DissectorTablesProxyModel::setFilter(const QString& filter) | |||
| 427 | { | |||
| 428 | #if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 9, 0)((6<<16)|(9<<8)|(0)) | |||
| 429 | beginFilterChange(); | |||
| 430 | #endif | |||
| 431 | filter_ = filter; | |||
| 432 | #if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 10, 0)((6<<16)|(10<<8)|(0)) | |||
| 433 | endFilterChange(QSortFilterProxyModel::Direction::Rows); | |||
| 434 | #else | |||
| 435 | invalidateFilter(); | |||
| 436 | #endif | |||
| 437 | } | |||
| 438 | ||||
| 439 | void DissectorTablesProxyModel::adjustHeader(const QModelIndex ¤tIndex) | |||
| 440 | { | |||
| 441 | tableName_ = tr("Table Type"); | |||
| 442 | dissectorDescription_ = QString(); | |||
| 443 | if (currentIndex.isValid() && currentIndex.parent().isValid()) { | |||
| 444 | QString table; | |||
| 445 | ||||
| 446 | if (currentIndex.parent().parent().isValid()) { | |||
| 447 | table = data(index(currentIndex.parent().parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); | |||
| 448 | if ((table.compare(CUSTOM_TABLE_NAME) == 0) || | |||
| 449 | (table.compare(STRING_TABLE_NAME) == 0)) { | |||
| 450 | tableName_ = tr("String"); | |||
| 451 | dissectorDescription_ = tr("Dissector Description"); | |||
| 452 | } else if (table.compare(INTEGER_TABLE_NAME) == 0) { | |||
| 453 | tableName_ = tr("Integer"); | |||
| 454 | dissectorDescription_ = tr("Dissector Description"); | |||
| 455 | } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { | |||
| 456 | tableName_ = tr("Protocol"); | |||
| 457 | dissectorDescription_ = tr("Short Name"); | |||
| 458 | } | |||
| 459 | } else { | |||
| 460 | table = data(index(currentIndex.parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); | |||
| 461 | if ((table.compare(CUSTOM_TABLE_NAME) == 0) || | |||
| 462 | (table.compare(INTEGER_TABLE_NAME) == 0) || | |||
| 463 | (table.compare(STRING_TABLE_NAME) == 0)) { | |||
| 464 | tableName_ = tr("Table Name"); | |||
| 465 | dissectorDescription_ = tr("Selector Name"); | |||
| 466 | } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { | |||
| 467 | tableName_ = tr("Protocol"); | |||
| 468 | dissectorDescription_ = tr("Short Name"); | |||
| 469 | } | |||
| 470 | } | |||
| 471 | } | |||
| 472 | ||||
| 473 | ||||
| 474 | emit headerDataChanged(Qt::Vertical, 0, 1); | |||
| 475 | } |