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 simple_statistics_dialog.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/simple_statistics_dialog.cpp -o /builds/wireshark/wireshark/sbout/2025-01-04-100244-3868-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-01-04-100244-3868-1 -x c++ /builds/wireshark/wireshark/ui/qt/simple_statistics_dialog.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "simple_statistics_dialog.h" |
11 | |
12 | #include "file.h" |
13 | |
14 | #include "epan/stat_tap_ui.h" |
15 | |
16 | #include <QTreeWidget> |
17 | |
18 | #include "main_application.h" |
19 | |
20 | |
21 | |
22 | |
23 | static QHash<const QString, stat_tap_table_ui *> cfg_str_to_stu_; |
24 | |
25 | extern "C" { |
26 | static void |
27 | simple_stat_init(const char *args, void*) { |
28 | QStringList args_l = QString(args).split(','); |
29 | if (args_l.length() > 1) { |
30 | QString simple_stat = QStringLiteral("%1,%2").arg(args_l[0]).arg(args_l[1]); |
31 | QString filter; |
32 | if (args_l.length() > 2) { |
33 | filter = QStringList(args_l.mid(2)).join(","); |
34 | } |
35 | mainApp->emitTapParameterSignal(simple_stat, filter, NULL); |
36 | } |
37 | } |
38 | } |
39 | |
40 | bool register_simple_stat_tables(const void *key, void *value, void*) { |
41 | stat_tap_table_ui *stu = (stat_tap_table_ui*)value; |
42 | |
43 | cfg_str_to_stu_[stu->cli_string] = stu; |
44 | TapParameterDialog::registerDialog( |
45 | stu->title, |
46 | (const char*)key, |
47 | stu->group, |
48 | simple_stat_init, |
49 | SimpleStatisticsDialog::createSimpleStatisticsDialog); |
50 | return false; |
51 | } |
52 | |
53 | enum { |
54 | simple_row_type_ = 1000 |
55 | }; |
56 | |
57 | class SimpleStatisticsTreeWidgetItem : public QTreeWidgetItem |
58 | { |
59 | public: |
60 | SimpleStatisticsTreeWidgetItem(QTreeWidgetItem *parent, int num_fields, const stat_tap_table_item_type *fields, const stat_tap_table_item *field) : |
61 | QTreeWidgetItem (parent, simple_row_type_), |
62 | num_fields_(num_fields), |
63 | fields_(fields), |
64 | field_(field) |
65 | { |
66 | } |
67 | void draw() { |
68 | for (int i = 0; i < num_fields_ && i < treeWidget()->columnCount(); i++) { |
69 | switch (fields_[i].type) { |
70 | case TABLE_ITEM_UINT: |
71 | setText(i, QString::asprintf(field_[i].field_format, fields_[i].value.uint_value)); |
72 | break; |
73 | case TABLE_ITEM_INT: |
74 | setText(i, QString::asprintf(field_[i].field_format, fields_[i].value.int_value)); |
75 | break; |
76 | case TABLE_ITEM_STRING: |
77 | setText(i, QString::asprintf(field_[i].field_format, fields_[i].value.string_value)); |
78 | break; |
79 | case TABLE_ITEM_FLOAT: |
80 | setText(i, QString::asprintf(field_[i].field_format, fields_[i].value.float_value)); |
81 | break; |
82 | case TABLE_ITEM_ENUM: |
83 | setText(i, QString::number(fields_[i].value.enum_value)); |
84 | break; |
85 | default: |
86 | break; |
87 | } |
88 | } |
89 | } |
90 | bool operator< (const QTreeWidgetItem &other) const |
91 | { |
92 | int col = treeWidget()->sortColumn(); |
93 | if (other.type() != simple_row_type_ || col >= num_fields_) { |
94 | return QTreeWidgetItem::operator< (other); |
95 | } |
96 | const SimpleStatisticsTreeWidgetItem *other_row = static_cast<const SimpleStatisticsTreeWidgetItem *>(&other); |
97 | switch (fields_[col].type) { |
98 | case TABLE_ITEM_UINT: |
99 | return fields_[col].value.uint_value < other_row->fields_[col].value.uint_value; |
100 | case TABLE_ITEM_INT: |
101 | return fields_[col].value.int_value < other_row->fields_[col].value.int_value; |
102 | case TABLE_ITEM_STRING: |
103 | return g_strcmp0(fields_[col].value.string_value, other_row->fields_[col].value.string_value) < 0; |
104 | case TABLE_ITEM_FLOAT: |
105 | return fields_[col].value.float_value < other_row->fields_[col].value.float_value; |
106 | case TABLE_ITEM_ENUM: |
107 | return fields_[col].value.enum_value < other_row->fields_[col].value.enum_value; |
108 | default: |
109 | break; |
110 | } |
111 | |
112 | return QTreeWidgetItem::operator< (other); |
113 | } |
114 | QList<QVariant> rowData() { |
115 | QList<QVariant> row_data; |
116 | |
117 | for (int i = 0; i < num_fields_ && i < columnCount(); i++) { |
118 | switch (fields_[i].type) { |
119 | case TABLE_ITEM_UINT: |
120 | row_data << fields_[i].value.uint_value; |
121 | break; |
122 | case TABLE_ITEM_INT: |
123 | row_data << fields_[i].value.int_value; |
124 | break; |
125 | case TABLE_ITEM_STRING: |
126 | row_data << fields_[i].value.string_value; |
127 | break; |
128 | case TABLE_ITEM_FLOAT: |
129 | row_data << fields_[i].value.float_value; |
130 | break; |
131 | case TABLE_ITEM_ENUM: |
132 | row_data << fields_[i].value.enum_value; |
133 | break; |
134 | default: |
135 | break; |
136 | } |
137 | } |
138 | |
139 | return row_data; |
140 | } |
141 | |
142 | private: |
143 | const int num_fields_; |
144 | const stat_tap_table_item_type *fields_; |
145 | const stat_tap_table_item *field_; |
146 | }; |
147 | |
148 | SimpleStatisticsDialog::SimpleStatisticsDialog(QWidget &parent, CaptureFile &cf, struct _stat_tap_table_ui *stu, const QString filter, int help_topic) : |
149 | TapParameterDialog(parent, cf, help_topic), |
150 | stu_(stu) |
151 | { |
152 | stu->refcount++; |
153 | setWindowSubtitle(stu_->title); |
154 | loadGeometry(0, 0, stu_->title); |
155 | |
156 | QStringList header_labels; |
157 | for (int col = 0; col < (int) stu_->nfields; col++) { |
158 | header_labels << stu_->fields[col].column_name; |
159 | } |
160 | statsTreeWidget()->setHeaderLabels(header_labels); |
161 | |
162 | for (int col = 0; col < (int) stu_->nfields; col++) { |
163 | if (stu_->fields[col].align == TAP_ALIGN_RIGHT) { |
164 | statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight); |
165 | } |
166 | } |
167 | |
168 | setDisplayFilter(filter); |
169 | } |
170 | |
171 | TapParameterDialog *SimpleStatisticsDialog::createSimpleStatisticsDialog(QWidget &parent, const QString cfg_str, const QString filter, CaptureFile &cf) |
172 | { |
173 | if (!cfg_str_to_stu_.contains(cfg_str)) { |
174 | |
175 | return NULL; |
176 | } |
177 | |
178 | stat_tap_table_ui *stu = cfg_str_to_stu_[cfg_str]; |
179 | |
180 | return new SimpleStatisticsDialog(parent, cf, stu, filter); |
181 | } |
182 | |
183 | void SimpleStatisticsDialog::addMissingRows(struct _stat_data_t *stat_data) |
184 | { |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | for (unsigned table_idx = 0; table_idx < stat_data->stat_tap_data->tables->len; table_idx++) { |
| 9 | | Assuming 'table_idx' is < field 'len' | |
|
| 10 | | Loop condition is true. Entering loop body | |
|
194 | stat_tap_table* st_table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, table_idx); |
195 | QTreeWidgetItem *ti = NULL; |
196 | |
197 | if ((int) table_idx >= statsTreeWidget()->topLevelItemCount()) { |
| 11 | | Assuming the condition is false | |
|
| |
198 | ti = new QTreeWidgetItem(statsTreeWidget()); |
199 | ti->setText(0, st_table->title); |
200 | ti->setFirstColumnSpanned(true); |
201 | ti->setExpanded(true); |
202 | } else { |
203 | ti = statsTreeWidget()->topLevelItem(table_idx); |
204 | } |
205 | for (unsigned element = ti->childCount(); element < st_table->num_elements; element++) { |
| 13 | | Assuming 'element' is < field 'num_elements' | |
|
| 14 | | Loop condition is true. Entering loop body | |
|
| 23 | | Potential leak of memory pointed to by 'ss_ti' |
|
206 | stat_tap_table_item_type* fields = stat_tap_get_field_data(st_table, element, 0); |
207 | if (stu_->nfields > 0) { |
| 15 | | Assuming field 'nfields' is > 0 | |
|
| |
208 | SimpleStatisticsTreeWidgetItem *ss_ti = new SimpleStatisticsTreeWidgetItem(ti, st_table->num_fields, fields, stu_->fields); |
| |
209 | for (int col = 0; col < (int) stu_->nfields; col++) { |
| 18 | | Loop condition is true. Entering loop body | |
|
| 21 | | Assuming 'col' is >= field 'nfields' | |
|
| 22 | | Loop condition is false. Execution continues on line 205 | |
|
210 | if (stu_->fields[col].align == TAP_ALIGN_RIGHT) { |
| 19 | | Assuming field 'align' is not equal to TAP_ALIGN_RIGHT | |
|
| |
211 | ss_ti->setTextAlignment(col, Qt::AlignRight); |
212 | } |
213 | } |
214 | } |
215 | } |
216 | } |
217 | } |
218 | |
219 | void SimpleStatisticsDialog::tapReset(void *sd_ptr) |
220 | { |
221 | stat_data_t *sd = (stat_data_t*) sd_ptr; |
222 | SimpleStatisticsDialog *ss_dlg = static_cast<SimpleStatisticsDialog *>(sd->user_data); |
223 | if (!ss_dlg) return; |
224 | |
225 | reset_stat_table(sd->stat_tap_data); |
226 | ss_dlg->statsTreeWidget()->clear(); |
227 | } |
228 | |
229 | void SimpleStatisticsDialog::tapDraw(void *sd_ptr) |
230 | { |
231 | stat_data_t *sd = (stat_data_t*) sd_ptr; |
232 | SimpleStatisticsDialog *ss_dlg = static_cast<SimpleStatisticsDialog *>(sd->user_data); |
233 | if (!ss_dlg) return; |
| 6 | | Assuming 'ss_dlg' is non-null | |
|
| |
234 | |
235 | ss_dlg->addMissingRows(sd); |
| 8 | | Calling 'SimpleStatisticsDialog::addMissingRows' | |
|
236 | |
237 | QTreeWidgetItemIterator it(ss_dlg->statsTreeWidget()); |
238 | while (*it) { |
239 | if ((*it)->type() == simple_row_type_) { |
240 | SimpleStatisticsTreeWidgetItem *ss_ti = static_cast<SimpleStatisticsTreeWidgetItem *>((*it)); |
241 | ss_ti->draw(); |
242 | } |
243 | ++it; |
244 | } |
245 | |
246 | for (int i = 0; i < ss_dlg->statsTreeWidget()->columnCount() - 1; i++) { |
247 | ss_dlg->statsTreeWidget()->resizeColumnToContents(i); |
248 | } |
249 | } |
250 | |
251 | void SimpleStatisticsDialog::fillTree() |
252 | { |
253 | stat_data_t stat_data; |
254 | stat_data.stat_tap_data = stu_; |
255 | stat_data.user_data = this; |
256 | |
257 | stu_->stat_tap_init_cb(stu_); |
258 | |
259 | QString display_filter = displayFilter(); |
260 | if (!registerTapListener(stu_->tap_name, |
| 1 | Assuming the condition is false | |
|
| |
261 | &stat_data, |
262 | display_filter.toUtf8().constData(), |
263 | 0, |
264 | tapReset, |
265 | stu_->packet_func, |
266 | tapDraw)) { |
267 | free_stat_tables(stu_); |
268 | reject(); |
269 | return; |
270 | } |
271 | |
272 | statsTreeWidget()->setSortingEnabled(false); |
273 | |
274 | cap_file_.retapPackets(); |
275 | |
276 | |
277 | if (statsTreeWidget()->invisibleRootItem()->childCount() == 1) { |
| 3 | | Assuming the condition is false | |
|
| |
278 | statsTreeWidget()->setRootIndex(statsTreeWidget()->model()->index(0, 0)); |
279 | } |
280 | |
281 | tapDraw(&stat_data); |
| 5 | | Calling 'SimpleStatisticsDialog::tapDraw' | |
|
282 | |
283 | statsTreeWidget()->sortItems(0, Qt::AscendingOrder); |
284 | statsTreeWidget()->setSortingEnabled(true); |
285 | |
286 | removeTapListeners(); |
287 | } |
288 | |
289 | |
290 | QList<QVariant> SimpleStatisticsDialog::treeItemData(QTreeWidgetItem *it) const |
291 | { |
292 | |
293 | SimpleStatisticsTreeWidgetItem *rit = dynamic_cast<SimpleStatisticsTreeWidgetItem*>(it); |
294 | if (rit) { |
295 | return rit->rowData(); |
296 | } |
297 | else { |
298 | return QList<QVariant>(); |
299 | } |
300 | } |
301 | |
302 | |
303 | SimpleStatisticsDialog::~SimpleStatisticsDialog() |
304 | { |
305 | stu_->refcount--; |
306 | if (stu_->refcount == 0) { |
307 | if (stu_->tables) |
308 | free_stat_tables(stu_); |
309 | } |
310 | } |