Bug Summary

File:OMEdit/OMEditLIB/CrashReport/CrashReportDialog.cpp
Warning:line 175, column 16
Potential leak of memory pointed to by 'pGDBBacktrace'

Annotated Source Code

[?] Use j/k keys for keyboard navigation

1/*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
13 * OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
14 *
15 * The OpenModelica software and the Open Source Modelica
16 * Consortium (OSMC) Public License (OSMC-PL) are obtained
17 * from OSMC, either from the above address,
18 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
19 * http://www.openmodelica.org, and in the OpenModelica distribution.
20 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
21 *
22 * This program is distributed WITHOUT ANY WARRANTY; without
23 * even the implied warranty of MERCHANTABILITY or FITNESS
24 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
25 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
26 *
27 * See the full OSMC Public License conditions for more details.
28 *
29 */
30/*
31 * @author Adeel Asghar <adeel.asghar@liu.se>
32 */
33
34#include "CrashReportDialog.h"
35#include "Util/Helper.h"
36#include "omc_config.h"
37#include "GDBBacktrace.h"
38
39#include <QGridLayout>
40#include <QMessageBox>
41
42/*!
43 * \class CrashReportDialog
44 * \brief Interface for sending crash reports.
45 */
46/*!
47 * \brief CrashReportDialog::CrashReportDialog
48 */
49CrashReportDialog::CrashReportDialog(QString stacktrace)
50 : QDialog(0)
51{
52 // flush all streams before making a crash report so we get full logs.
53 fflush(NULL__null);
54 setWindowTitle(QString(Helper::applicationName).append(" - ").append(Helper::crashReport));
55 setAttribute(Qt::WA_DeleteOnClose);
56 // brief stack trace
57 mStackTrace = stacktrace;
58 // create the GDB stack trace
59 createGDBBacktrace();
1
Calling 'CrashReportDialog::createGDBBacktrace'
60 // set heading
61 mpCrashReportHeading = Utilities::getHeadingLabel(Helper::crashReport);
62 // set separator line
63 mpHorizontalLine = Utilities::getHeadingLine();
64 // Email label and textbox
65 mpEmailLabel = new Label(tr("Your Email (in case you want us to contact you regarding this error):"));
66 mpEmailTextBox = new QLineEdit;
67 // bug description label and textbox
68 mpBugDescriptionLabel = new Label(tr("Describe in a few words what you were doing when the error occurred:"));
69 mpBugDescriptionTextBox = new QPlainTextEdit(
70 QString("Connected to %1%4.\nThe running OS is %2 on %3.\n").arg(Helper::OpenModelicaVersion,
71#if (QT_VERSION((5<<16)|(9<<8)|(5)) >= QT_VERSION_CHECK(5, 4, 0)((5<<16)|(4<<8)|(0)))
72 QSysInfo::prettyProductName(), QSysInfo::currentCpuArchitecture(),
73#elif defined(__APPLE__)
74 "OSX", "unknown (probably amd64)",
75#else
76 "unknown", "unknown",
77#endif
78#if defined(LSB_RELEASE"Ubuntu 18.04.1 LTS")
79 " built for " LSB_RELEASE"Ubuntu 18.04.1 LTS"
80#else
81 ""
82#endif
83 )
84 );
85 // files label and checkboxes
86 mpFilesDescriptionLabel = new Label(tr("Following selected files will be sent along with the crash report,"));
87 QString& tmpPath = Utilities::tempDirectory();
88 // omeditcommunication.log file checkbox
89 QFileInfo OMEditCommunicationLogFileInfo(QString("%1omeditcommunication.log").arg(tmpPath));
90 mpOMEditCommunicationLogFileCheckBox = new QCheckBox(OMEditCommunicationLogFileInfo.absoluteFilePath());
91 if (OMEditCommunicationLogFileInfo.exists()) {
92 mpOMEditCommunicationLogFileCheckBox->setChecked(true);
93 } else {
94 mpOMEditCommunicationLogFileCheckBox->setChecked(false);
95 }
96 // omeditcommands.mos file checkbox
97 QFileInfo OMEditCommandsMosFileInfo(QString("%1omeditcommands.mos").arg(tmpPath));
98 mpOMEditCommandsMosFileCheckBox = new QCheckBox(OMEditCommandsMosFileInfo.absoluteFilePath());
99 if (OMEditCommandsMosFileInfo.exists()) {
100 mpOMEditCommandsMosFileCheckBox->setChecked(true);
101 } else {
102 mpOMEditCommandsMosFileCheckBox->setChecked(false);
103 }
104 // openmodelica.stacktrace.OMEdit file checkbox
105 QFileInfo OMStackTraceFileInfo(QString("%1openmodelica.stacktrace.%2").arg(tmpPath).arg(Helper::OMCServerName));
106 mpOMStackTraceFileCheckBox = new QCheckBox(OMStackTraceFileInfo.absoluteFilePath());
107 if (OMStackTraceFileInfo.exists()) {
108 mpOMStackTraceFileCheckBox->setChecked(true);
109 } else {
110 mpOMStackTraceFileCheckBox->setChecked(false);
111 }
112 // create send report button
113 mpSendReportButton = new QPushButton(tr("Send Report"));
114 mpSendReportButton->setAutoDefault(true);
115 connect(mpSendReportButton, SIGNAL(clicked())"2""clicked()", SLOT(sendReport())"1""sendReport()");
116 mpCancelButton = new QPushButton(Helper::cancel);
117 connect(mpCancelButton, SIGNAL(clicked())"2""clicked()", SLOT(reject())"1""reject()");
118 // create buttons box
119 mpButtonBox = new QDialogButtonBox(Qt::Horizontal);
120 mpButtonBox->addButton(mpSendReportButton, QDialogButtonBox::ActionRole);
121 mpButtonBox->addButton(mpCancelButton, QDialogButtonBox::ActionRole);
122 // Progress label & bar
123 mpProgressLabel = new Label(tr("Sending crash report"));
124 mpProgressLabel->hide();
125 mpProgressBar = new QProgressBar;
126 mpProgressBar->setRange(0, 0);
127 mpProgressBar->hide();
128 // set grid layout
129 QGridLayout *pMainLayout = new QGridLayout;
130 pMainLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
131 pMainLayout->addWidget(mpCrashReportHeading, 0, 0, 1, 3);
132 pMainLayout->addWidget(mpHorizontalLine, 1, 0, 1, 3);
133 pMainLayout->addWidget(mpEmailLabel, 2, 0, 1, 3);
134 pMainLayout->addWidget(mpEmailTextBox, 3, 0, 1, 3);
135 pMainLayout->addWidget(mpBugDescriptionLabel, 4, 0, 1, 3);
136 pMainLayout->addWidget(mpBugDescriptionTextBox, 5, 0, 1, 3);
137 int index = 6;
138 if (OMEditCommunicationLogFileInfo.exists() || OMEditCommandsMosFileInfo.exists() || OMStackTraceFileInfo.exists()) {
139 pMainLayout->addWidget(mpFilesDescriptionLabel, index, 0, 1, 3);
140 index++;
141 }
142 if (OMEditCommunicationLogFileInfo.exists()) {
143 pMainLayout->addWidget(mpOMEditCommunicationLogFileCheckBox, index, 0, 1, 3);
144 index++;
145 }
146 if (OMEditCommandsMosFileInfo.exists()) {
147 pMainLayout->addWidget(mpOMEditCommandsMosFileCheckBox, index, 0, 1, 3);
148 index++;
149 }
150 if (OMStackTraceFileInfo.exists()) {
151 pMainLayout->addWidget(mpOMStackTraceFileCheckBox, index, 0, 1, 3);
152 index++;
153 }
154 pMainLayout->addWidget(mpProgressLabel, index, 0);
155 pMainLayout->addWidget(mpProgressBar, index, 1);
156 pMainLayout->addWidget(mpButtonBox, index, 2, Qt::AlignRight);
157 setLayout(pMainLayout);
158}
159
160/*!
161 * \brief CrashReportDialog::createGDBBacktrace
162 * Creates the detailed gdb backtrace. If it fails to create one then uses the simple backtrace.
163 */
164void CrashReportDialog::createGDBBacktrace()
165{
166 QString errorString;
167 bool error = false;
168 QString OMStackTraceFilePath = QString("%1/openmodelica.stacktrace.%2").arg(Utilities::tempDirectory()).arg(Helper::OMCServerName);
169 // create the GDBBacktrace object
170 GDBBacktrace *pGDBBacktrace = new GDBBacktrace;
2
Memory is allocated
171 if (pGDBBacktrace->errorOccurred()) {
3
Assuming the condition is false
4
Taking false branch
172 errorString = pGDBBacktrace->output();
173 error = true;
174 } else {
175 QFile file(OMStackTraceFilePath);
5
Potential leak of memory pointed to by 'pGDBBacktrace'
176 if (file.open(QIODevice::ReadOnly)) {
177 char buf[1024];
178 qint64 lineLength = file.readLine(buf, sizeof(buf));
179 if (lineLength != -1) {
180 QString lineText(buf);
181 // if we are unable to attach then set error occurred to true.
182 if (lineText.startsWith("Could not attach to process", Qt::CaseInsensitive)) {
183 errorString = lineText + QString(file.readAll());
184 error = true;
185 }
186 }
187 file.close();
188 } else {
189 errorString = GUIMessages::getMessage(GUIMessages::UNABLE_TO_OPEN_FILE).arg(OMStackTraceFilePath);
190 error = true;
191 }
192 }
193 // if some error has occurred
194 if (error) {
195 QMessageBox *pMessageBox = new QMessageBox;
196 pMessageBox->setWindowTitle(QString("%1 - %2").arg(Helper::applicationName, Helper::error));
197 pMessageBox->setIcon(QMessageBox::Critical);
198 pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
199 pMessageBox->setText(tr("Following error has occurred while retrieving detailed gdb backtrace,\n\n%1").arg(errorString));
200 pMessageBox->addButton(tr("Try again"), QMessageBox::AcceptRole);
201 pMessageBox->addButton(tr("Send brief backtrace"), QMessageBox::RejectRole);
202 int answer = pMessageBox->exec();
203 switch (answer) {
204 case QMessageBox::AcceptRole:
205 createGDBBacktrace();
206 return;
207 case QMessageBox::RejectRole:
208 default:
209 break;
210 }
211 // create a brief backtrace file
212 QFile stackTraceFile;
213 stackTraceFile.setFileName(OMStackTraceFilePath);
214 if (stackTraceFile.open(QIODevice::WriteOnly)) {
215 QTextStream out(&stackTraceFile);
216 out.setCodec(Helper::utf8.toUtf8().constData());
217 out.setGenerateByteOrderMark(false);
218 out << mStackTrace;
219 out.flush();
220 stackTraceFile.close();
221 }
222 }
223}
224
225/*!
226 * \brief CrashReportDialog::sendReport
227 * Slot activated when mpSendReportButton clicked signal is raised.\n
228 * Sends the crash report along with selected log files.
229 */
230void CrashReportDialog::sendReport()
231{
232 // ask for e-mail address.
233 if (mpEmailTextBox->text().isEmpty()) {
234 QMessageBox *pMessageBox = new QMessageBox;
235 pMessageBox->setWindowTitle(QString(Helper::applicationName).append(" - ").append(Helper::error));
236 pMessageBox->setIcon(QMessageBox::Critical);
237 pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
238 pMessageBox->setText(tr("We can't contact you with a possible solution if you don't provide a valid e-mail address."));
239 pMessageBox->addButton(tr("Send without e-mail"), QMessageBox::AcceptRole);
240 pMessageBox->addButton(tr("Let me enter e-mail"), QMessageBox::RejectRole);
241 int answer = pMessageBox->exec();
242 switch (answer) {
243 case QMessageBox::RejectRole:
244 mpEmailTextBox->setFocus();
245 return;
246 case QMessageBox::AcceptRole:
247 default:
248 break;
249 }
250 }
251 mpProgressLabel->show();
252 mpProgressBar->show();
253 // create the report.
254 QHttpMultiPart *pHttpMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
255 // email
256 QHttpPart emailHttpPart;
257 emailHttpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"email\""));
258 emailHttpPart.setBody(mpEmailTextBox->text().toUtf8());
259 pHttpMultiPart->append(emailHttpPart);
260 // bug description
261 QHttpPart bugDescriptionHttpPart;
262 bugDescriptionHttpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"bugdescription\""));
263 bugDescriptionHttpPart.setBody(mpBugDescriptionTextBox->toPlainText().toUtf8());
264 pHttpMultiPart->append(bugDescriptionHttpPart);
265 // OMEditCommunicationLogFile
266 if (mpOMEditCommunicationLogFileCheckBox->isChecked()) {
267 QHttpPart OMEditCommunicationLogFileHttpPart;
268 OMEditCommunicationLogFileHttpPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
269 OMEditCommunicationLogFileHttpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"omeditcommunication.log\"; filename=\"omeditcommunication.log\""));
270 QFile *pOMEditCommunicationLogFileFile = new QFile(mpOMEditCommunicationLogFileCheckBox->text());
271 pOMEditCommunicationLogFileFile->open(QIODevice::ReadOnly);
272 OMEditCommunicationLogFileHttpPart.setBodyDevice(pOMEditCommunicationLogFileFile);
273 pOMEditCommunicationLogFileFile->setParent(pHttpMultiPart); // file will be deleted when we delete pHttpMultiPart
274 pHttpMultiPart->append(OMEditCommunicationLogFileHttpPart);
275 }
276 // OMEditCommandsMosFile
277 if (mpOMEditCommandsMosFileCheckBox->isChecked()) {
278 QHttpPart OMEditCommandsMosFileHttpPart;
279 OMEditCommandsMosFileHttpPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
280 OMEditCommandsMosFileHttpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"omeditcommands.mos\"; filename=\"omeditcommands.mos\""));
281 QFile *pOMEditCommandsMosFile = new QFile(mpOMEditCommandsMosFileCheckBox->text());
282 pOMEditCommandsMosFile->open(QIODevice::ReadOnly);
283 OMEditCommandsMosFileHttpPart.setBodyDevice(pOMEditCommandsMosFile);
284 pOMEditCommandsMosFile->setParent(pHttpMultiPart); // file will be deleted when we delete pHttpMultiPart
285 pHttpMultiPart->append(OMEditCommandsMosFileHttpPart);
286 }
287 // OMStackTraceFile
288 if (mpOMStackTraceFileCheckBox->isChecked()) {
289 QHttpPart OMStackTraceFileCheckBoxHttpPart;
290 OMStackTraceFileCheckBoxHttpPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
291 OMStackTraceFileCheckBoxHttpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"openmodelica.stacktrace.OMEdit\"; filename=\"openmodelica.stacktrace.OMEdit\""));
292 QFile *pOMStackTraceFile = new QFile(mpOMStackTraceFileCheckBox->text());
293 pOMStackTraceFile->open(QIODevice::ReadOnly);
294 OMStackTraceFileCheckBoxHttpPart.setBodyDevice(pOMStackTraceFile);
295 pOMStackTraceFile->setParent(pHttpMultiPart); // file will be deleted when we delete pHttpMultiPart
296 pHttpMultiPart->append(OMStackTraceFileCheckBoxHttpPart);
297 }
298 // create the request
299 QUrl url("https://dev.openmodelica.org/omeditcrashreports/cgi-bin/server.py");
300 QNetworkRequest networkRequest(url);
301 QNetworkAccessManager *pNetworkAccessManager = new QNetworkAccessManager;
302 connect(pNetworkAccessManager, SIGNAL(finished(QNetworkReply*))"2""finished(QNetworkReply*)", SLOT(reportSent(QNetworkReply*))"1""reportSent(QNetworkReply*)");
303 QNetworkReply *pNetworkReply = pNetworkAccessManager->post(networkRequest, pHttpMultiPart);
304 pNetworkReply->ignoreSslErrors();
305 pHttpMultiPart->setParent(pNetworkReply); // delete the pHttpMultiPart with the pNetworkReply
306}
307
308/*!
309 * \brief CrashReportDialog::reportSent
310 * \param pNetworkReply
311 * Slot activated when QNetworkAccessManager finished signal is raised.\n
312 * Shows an error message if crash report was not send correctly.\n
313 * Deletes QNetworkReply object which deletes the QHttpMultiPart and QFile objects attached with it.
314 */
315void CrashReportDialog::reportSent(QNetworkReply *pNetworkReply)
316{
317 mpProgressLabel->hide();
318 mpProgressBar->hide();
319 if (pNetworkReply->error() != QNetworkReply::NoError) {
320 QMessageBox::critical(0, QString(Helper::applicationName).append(" - ").append(Helper::error),
321 QString("Following error has occurred while sending crash report \n\n%1").arg(pNetworkReply->errorString()),
322 Helper::ok);
323 }
324 pNetworkReply->deleteLater();
325 accept();
326}