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/2024-12-02-100256-3913-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-12-02-100256-3913-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) : |
61 | QTreeWidgetItem (parent, simple_row_type_), |
62 | num_fields_(num_fields), |
63 | fields_(fields) |
64 | { |
65 | } |
66 | void draw() { |
67 | for (int i = 0; i < num_fields_ && i < treeWidget()->columnCount(); i++) { |
68 | switch (fields_[i].type) { |
69 | case TABLE_ITEM_UINT: |
70 | setText(i, QString::number(fields_[i].value.uint_value)); |
71 | break; |
72 | case TABLE_ITEM_INT: |
73 | setText(i, QString::number(fields_[i].value.int_value)); |
74 | break; |
75 | case TABLE_ITEM_STRING: |
76 | setText(i, fields_[i].value.string_value); |
77 | break; |
78 | case TABLE_ITEM_FLOAT: |
79 | setText(i, QString::number(fields_[i].value.float_value, 'f', 6)); |
80 | break; |
81 | case TABLE_ITEM_ENUM: |
82 | setText(i, QString::number(fields_[i].value.enum_value)); |
83 | break; |
84 | default: |
85 | break; |
86 | } |
87 | } |
88 | } |
89 | bool operator< (const QTreeWidgetItem &other) const |
90 | { |
91 | int col = treeWidget()->sortColumn(); |
92 | if (other.type() != simple_row_type_ || col >= num_fields_) { |
93 | return QTreeWidgetItem::operator< (other); |
94 | } |
95 | const SimpleStatisticsTreeWidgetItem *other_row = static_cast<const SimpleStatisticsTreeWidgetItem *>(&other); |
96 | switch (fields_[col].type) { |
97 | case TABLE_ITEM_UINT: |
98 | return fields_[col].value.uint_value < other_row->fields_[col].value.uint_value; |
99 | case TABLE_ITEM_INT: |
100 | return fields_[col].value.int_value < other_row->fields_[col].value.int_value; |
101 | case TABLE_ITEM_STRING: |
102 | return g_strcmp0(fields_[col].value.string_value, other_row->fields_[col].value.string_value) < 0; |
103 | case TABLE_ITEM_FLOAT: |
104 | return fields_[col].value.float_value < other_row->fields_[col].value.float_value; |
105 | case TABLE_ITEM_ENUM: |
106 | return fields_[col].value.enum_value < other_row->fields_[col].value.enum_value; |
107 | default: |
108 | break; |
109 | } |
110 | |
111 | return QTreeWidgetItem::operator< (other); |
112 | } |
113 | QList<QVariant> rowData() { |
114 | QList<QVariant> row_data; |
115 | |
116 | for (int i = 0; i < num_fields_ && i < columnCount(); i++) { |
117 | switch (fields_[i].type) { |
118 | case TABLE_ITEM_UINT: |
119 | row_data << fields_[i].value.uint_value; |
120 | break; |
121 | case TABLE_ITEM_INT: |
122 | row_data << fields_[i].value.int_value; |
123 | break; |
124 | case TABLE_ITEM_STRING: |
125 | row_data << fields_[i].value.string_value; |
126 | break; |
127 | case TABLE_ITEM_FLOAT: |
128 | row_data << fields_[i].value.float_value; |
129 | break; |
130 | case TABLE_ITEM_ENUM: |
131 | row_data << fields_[i].value.enum_value; |
132 | break; |
133 | default: |
134 | break; |
135 | } |
136 | } |
137 | |
138 | return row_data; |
139 | } |
140 | |
141 | private: |
142 | const int num_fields_; |
143 | const stat_tap_table_item_type *fields_; |
144 | }; |
145 | |
146 | SimpleStatisticsDialog::SimpleStatisticsDialog(QWidget &parent, CaptureFile &cf, struct _stat_tap_table_ui *stu, const QString filter, int help_topic) : |
147 | TapParameterDialog(parent, cf, help_topic), |
148 | stu_(stu) |
149 | { |
150 | stu->refcount++; |
151 | setWindowSubtitle(stu_->title); |
152 | loadGeometry(0, 0, stu_->title); |
153 | |
154 | QStringList header_labels; |
155 | for (int col = 0; col < (int) stu_->nfields; col++) { |
156 | header_labels << stu_->fields[col].column_name; |
157 | } |
158 | statsTreeWidget()->setHeaderLabels(header_labels); |
159 | |
160 | for (int col = 0; col < (int) stu_->nfields; col++) { |
161 | if (stu_->fields[col].align == TAP_ALIGN_RIGHT) { |
162 | statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight); |
163 | } |
164 | } |
165 | |
166 | setDisplayFilter(filter); |
167 | } |
168 | |
169 | TapParameterDialog *SimpleStatisticsDialog::createSimpleStatisticsDialog(QWidget &parent, const QString cfg_str, const QString filter, CaptureFile &cf) |
170 | { |
171 | if (!cfg_str_to_stu_.contains(cfg_str)) { |
172 | |
173 | return NULL; |
174 | } |
175 | |
176 | stat_tap_table_ui *stu = cfg_str_to_stu_[cfg_str]; |
177 | |
178 | return new SimpleStatisticsDialog(parent, cf, stu, filter); |
179 | } |
180 | |
181 | void SimpleStatisticsDialog::addMissingRows(struct _stat_data_t *stat_data) |
182 | { |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | 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 | |
|
192 | stat_tap_table* st_table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, table_idx); |
193 | QTreeWidgetItem *ti = NULL; |
194 | |
195 | if ((int) table_idx >= statsTreeWidget()->topLevelItemCount()) { |
| 11 | | Assuming the condition is false | |
|
| |
196 | ti = new QTreeWidgetItem(statsTreeWidget()); |
197 | ti->setText(0, st_table->title); |
198 | ti->setFirstColumnSpanned(true); |
199 | ti->setExpanded(true); |
200 | } else { |
201 | ti = statsTreeWidget()->topLevelItem(table_idx); |
202 | } |
203 | 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' |
|
204 | stat_tap_table_item_type* fields = stat_tap_get_field_data(st_table, element, 0); |
205 | if (stu_->nfields > 0) { |
| 15 | | Assuming field 'nfields' is > 0 | |
|
| |
206 | SimpleStatisticsTreeWidgetItem *ss_ti = new SimpleStatisticsTreeWidgetItem(ti, st_table->num_fields, fields); |
| |
207 | 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 203 | |
|
208 | if (stu_->fields[col].align == TAP_ALIGN_RIGHT) { |
| 19 | | Assuming field 'align' is not equal to TAP_ALIGN_RIGHT | |
|
| |
209 | ss_ti->setTextAlignment(col, Qt::AlignRight); |
210 | } |
211 | } |
212 | } |
213 | } |
214 | } |
215 | } |
216 | |
217 | void SimpleStatisticsDialog::tapReset(void *sd_ptr) |
218 | { |
219 | stat_data_t *sd = (stat_data_t*) sd_ptr; |
220 | SimpleStatisticsDialog *ss_dlg = static_cast<SimpleStatisticsDialog *>(sd->user_data); |
221 | if (!ss_dlg) return; |
222 | |
223 | reset_stat_table(sd->stat_tap_data); |
224 | ss_dlg->statsTreeWidget()->clear(); |
225 | } |
226 | |
227 | void SimpleStatisticsDialog::tapDraw(void *sd_ptr) |
228 | { |
229 | stat_data_t *sd = (stat_data_t*) sd_ptr; |
230 | SimpleStatisticsDialog *ss_dlg = static_cast<SimpleStatisticsDialog *>(sd->user_data); |
231 | if (!ss_dlg) return; |
| 6 | | Assuming 'ss_dlg' is non-null | |
|
| |
232 | |
233 | ss_dlg->addMissingRows(sd); |
| 8 | | Calling 'SimpleStatisticsDialog::addMissingRows' | |
|
234 | |
235 | QTreeWidgetItemIterator it(ss_dlg->statsTreeWidget()); |
236 | while (*it) { |
237 | if ((*it)->type() == simple_row_type_) { |
238 | SimpleStatisticsTreeWidgetItem *ss_ti = static_cast<SimpleStatisticsTreeWidgetItem *>((*it)); |
239 | ss_ti->draw(); |
240 | } |
241 | ++it; |
242 | } |
243 | |
244 | for (int i = 0; i < ss_dlg->statsTreeWidget()->columnCount() - 1; i++) { |
245 | ss_dlg->statsTreeWidget()->resizeColumnToContents(i); |
246 | } |
247 | } |
248 | |
249 | void SimpleStatisticsDialog::fillTree() |
250 | { |
251 | stat_data_t stat_data; |
252 | stat_data.stat_tap_data = stu_; |
253 | stat_data.user_data = this; |
254 | |
255 | stu_->stat_tap_init_cb(stu_); |
256 | |
257 | QString display_filter = displayFilter(); |
258 | if (!registerTapListener(stu_->tap_name, |
| 1 | Assuming the condition is false | |
|
| |
259 | &stat_data, |
260 | display_filter.toUtf8().constData(), |
261 | 0, |
262 | tapReset, |
263 | stu_->packet_func, |
264 | tapDraw)) { |
265 | free_stat_tables(stu_); |
266 | reject(); |
267 | return; |
268 | } |
269 | |
270 | statsTreeWidget()->setSortingEnabled(false); |
271 | |
272 | cap_file_.retapPackets(); |
273 | |
274 | |
275 | if (statsTreeWidget()->invisibleRootItem()->childCount() == 1) { |
| 3 | | Assuming the condition is false | |
|
| |
276 | statsTreeWidget()->setRootIndex(statsTreeWidget()->model()->index(0, 0)); |
277 | } |
278 | |
279 | tapDraw(&stat_data); |
| 5 | | Calling 'SimpleStatisticsDialog::tapDraw' | |
|
280 | |
281 | statsTreeWidget()->sortItems(0, Qt::AscendingOrder); |
282 | statsTreeWidget()->setSortingEnabled(true); |
283 | |
284 | removeTapListeners(); |
285 | } |
286 | |
287 | |
288 | QList<QVariant> SimpleStatisticsDialog::treeItemData(QTreeWidgetItem *it) const |
289 | { |
290 | |
291 | SimpleStatisticsTreeWidgetItem *rit = dynamic_cast<SimpleStatisticsTreeWidgetItem*>(it); |
292 | if (rit) { |
293 | return rit->rowData(); |
294 | } |
295 | else { |
296 | return QList<QVariant>(); |
297 | } |
298 | } |
299 | |
300 | |
301 | SimpleStatisticsDialog::~SimpleStatisticsDialog() |
302 | { |
303 | stu_->refcount--; |
304 | if (stu_->refcount == 0) { |
305 | if (stu_->tables) |
306 | free_stat_tables(stu_); |
307 | } |
308 | } |