Bug Summary

File:builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp
Warning:line 307, 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/2025-06-29-100246-3847-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-06-29-100246-3847-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 <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
18static const char* CUSTOM_TABLE_NAME = "Custom Tables";
19static const char* INTEGER_TABLE_NAME = "Integer Tables";
20static const char* STRING_TABLE_NAME = "String Tables";
21static const char* HEURISTIC_TABLE_NAME = "Heuristic Tables";
22
23class IntegerTablesItem : public DissectorTablesItem
24{
25public:
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
31protected:
32 unsigned int value_;
33};
34
35
36DissectorTablesItem::DissectorTablesItem(QString tableName, QString dissectorDescription, DissectorTablesItem* parent) :
37 ModelHelperTreeItem<DissectorTablesItem>(parent),
38 tableName_(tableName),
39 dissectorDescription_(dissectorDescription)
40{
41}
42
43DissectorTablesItem::~DissectorTablesItem()
44{
45}
46
47bool 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
56IntegerTablesItem::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
94IntegerTablesItem::~IntegerTablesItem()
95{
96}
97
98bool 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
111DissectorTablesModel::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
118DissectorTablesModel::~DissectorTablesModel()
119{
120 delete root_;
121}
122
123int 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
140int DissectorTablesModel::columnCount(const QModelIndex&) const
141{
142 return colLast;
143}
144
145QModelIndex 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
164QModelIndex 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
186QVariant 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
208static 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
248struct tables_root
249{
250 DissectorTablesItem* custom_table;
251 DissectorTablesItem* integer_table;
252 DissectorTablesItem* string_table;
253};
254
255static 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
292static 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)
1
Assuming 'hdl_ptr' is not equal to NULL
2
Taking false branch
296 return;
297
298 if (dtbl_entry->protocol) {
3
Assuming field 'protocol' is non-null
4
Taking true branch
299 QString longName = proto_get_protocol_long_name(dtbl_entry->protocol);
300 QString heurDisplayName = dtbl_entry->display_name;
301 if (! heurDisplayName.isEmpty())
5
Assuming the condition is false
6
Taking false branch
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);
7
Memory is allocated
305 hdl_ptr->prependChild(heur);
306 }
307}
8
Potential leak of memory pointed to by 'heur'
308
309static 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
328void 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
355DissectorTablesProxyModel::DissectorTablesProxyModel(QObject * parent)
356: QSortFilterProxyModel(parent),
357tableName_(tr("Table Type")),
358dissectorDescription_(),
359filter_()
360{
361}
362
363QVariant 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
379bool 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)
393bool 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
413bool 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
426void 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
439void DissectorTablesProxyModel::adjustHeader(const QModelIndex &currentIndex)
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}