Skip to content

Commit 585b29c

Browse files
Merge pull request #100 from christianhelle/copilot/resolve-sonarcloud-issues
Fix SonarCloud critical issues: thread safety, memory safety, and SQL injection
2 parents 1b9e28e + 586c744 commit 585b29c

9 files changed

Lines changed: 39 additions & 22 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ src/project/linux/translations
6464
*.snap
6565
.vs
6666
src/main.cpp
67+
*.csv

_codeql_detected_source_root

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.

src/database/dbanalyzer.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ void DbAnalyzer::loadTables(DatabaseInfo &info) const {
2727
}
2828

2929
QSqlQuery query(this->database->getDatabase());
30-
query.exec(sql);
30+
if (!query.exec(sql)) {
31+
database->close();
32+
return;
33+
}
3134

3235
while (query.next()) {
3336
Table table;
@@ -47,10 +50,12 @@ void DbAnalyzer::loadColumns(DatabaseInfo &info) const {
4750
}
4851

4952
for (auto &table: info.tables) {
50-
const QString sql = "PRAGMA table_info (" + table.name + ")";
53+
const QString sql = "PRAGMA table_info (\"" + table.name + "\")";
5154

5255
QSqlQuery query(this->database->getDatabase());
53-
query.exec(sql);
56+
if (!query.exec(sql)) {
57+
continue;
58+
}
5459

5560
while (query.next()) {
5661
Column col;

src/database/dbexportdata.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,13 @@ void DbDataExport::exportDataToSqlFile(const Database *database,
5656

5757
QSqlQuery query(database->getDatabase());
5858
query.setForwardOnly(true);
59-
query.exec(QString("SELECT * FROM %1").arg(table.name));
59+
if (!query.exec(QString("SELECT * FROM \"%1\"").arg(table.name))) {
60+
continue;
61+
}
6062
const auto columns = getColumnDefs(table).join(", ");
6163
while (query.next() && !cancellationToken->isCancellationRequested()) {
6264
const auto values = getColumnValueDefs(table, query).join(", ");
63-
out << "INSERT INTO " << table.name << "(" << columns << ") ";
65+
out << "INSERT INTO \"" << table.name << "\"(" << columns << ") ";
6466
out << "VALUES (" << values << ");\n";
6567
progress->increment();
6668
}
@@ -94,7 +96,10 @@ void DbDataExport::exportDataToCsvFile(const Database *database,
9496

9597
QSqlQuery query(database->getDatabase());
9698
query.setForwardOnly(true);
97-
query.exec(QString("SELECT * FROM %1").arg(table.name));
99+
if (!query.exec(QString("SELECT * FROM \"%1\"").arg(table.name))) {
100+
file->close();
101+
continue;
102+
}
98103

99104
while (query.next() && !cancellationToken->isCancellationRequested()) {
100105
const auto values = getColumnValueDefs(table, query).join(delimiter);

src/database/dbquery.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ void DbQuery::clearResults() {
3030
if (model != Q_NULLPTR) {
3131
model->clear();
3232
}
33-
table->setModel(Q_NULLPTR);
3433
delete model;
34+
table->setModel(Q_NULLPTR);
3535
}
3636
qDeleteAll(this->tableResults.begin(), this->tableResults.end());
3737
this->tableResults.clear();

src/gui/mainwindow.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,11 @@ void MainWindow::loadRecentFiles() const {
226226
}
227227

228228
void MainWindow::openRecentFile() {
229-
const QString file = sender()->objectName();
229+
auto *senderObject = sender();
230+
if (senderObject == nullptr) {
231+
return;
232+
}
233+
const QString file = senderObject->objectName();
230234
this->openDatabase(file);
231235
}
232236

src/gui/prompts.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
#include "../settings/settings.h"
88

99
QString Prompts::getCsvDelimiter(QWidget *parent,
10-
[[maybe_unused]] const QString &defaultDelimiter = ",") {
10+
const QString &defaultDelimiter) {
1111
bool ok{};
1212
auto input = QInputDialog::getText(parent,
13-
"CSV Delimeter",
14-
"Please enter delimeter to use",
13+
"CSV Delimiter",
14+
"Please enter delimiter to use",
1515
QLineEdit::Normal,
16-
",",
16+
defaultDelimiter,
1717
&ok);
1818
if (!ok || input.isEmpty()) {
19-
input = ",";
19+
input = defaultDelimiter;
2020
}
2121
return input;
2222
}
@@ -25,7 +25,7 @@ QString Prompts::getFolderPath(QWidget *parent) {
2525
SessionState state;
2626
Settings::getSessionState(&state);
2727
auto directory = state.lastUsedExportPath;
28-
if (state.lastUsedExportPath == Q_NULLPTR || state.lastUsedExportPath.isEmpty()) {
28+
if (state.lastUsedExportPath.isEmpty()) {
2929
directory = QDir::home().absolutePath();
3030
}
3131

@@ -41,7 +41,7 @@ QString Prompts::getFilePath(QWidget *parent,
4141
SessionState state;
4242
Settings::getSessionState(&state);
4343
auto directory = state.lastUsedExportPath;
44-
if (state.lastUsedExportPath == Q_NULLPTR || state.lastUsedExportPath.isEmpty()) {
44+
if (state.lastUsedExportPath.isEmpty()) {
4545
directory = QDir::home().absolutePath();
4646
}
4747

@@ -60,7 +60,7 @@ QString Prompts::getFilePath(QWidget *parent,
6060
}
6161
}
6262

63-
return Q_NULLPTR;
63+
return QString();
6464
}
6565

6666
bool Prompts::confirmDelete(QWidget *parent, const QString &tableName) {

src/threading/cancellation.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
#include "cancellation.h"
22

3-
CancellationToken::CancellationToken(bool *isCancelled): isCancelled(isCancelled) {
3+
CancellationToken::CancellationToken(std::atomic<bool> *isCancelled): isCancelled(isCancelled) {
44
}
55

66
bool CancellationToken::isCancellationRequested() const {
7-
return *isCancelled;
7+
return isCancelled->load();
88
}
99

1010
CancellationToken CancellationTokenSource::get() {
1111
return CancellationToken(&isCancelled);
1212
}
1313

1414
void CancellationTokenSource::cancel() {
15-
isCancelled = true;
15+
isCancelled.store(true);
1616
}

src/threading/cancellation.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
#ifndef CANCELLATION_H
22
#define CANCELLATION_H
33

4+
#include <atomic>
45

56
class CancellationToken {
67
public:
7-
explicit CancellationToken(bool *isCancelled);
8+
explicit CancellationToken(std::atomic<bool> *isCancelled);
89

910
[[nodiscard]] bool isCancellationRequested() const;
1011

1112
private:
12-
bool *isCancelled = nullptr;
13+
std::atomic<bool> *isCancelled = nullptr;
1314
};
1415

1516
class CancellationTokenSource {
@@ -19,7 +20,7 @@ class CancellationTokenSource {
1920
void cancel();
2021

2122
private:
22-
bool isCancelled = false;
23+
std::atomic<bool> isCancelled{false};
2324
};
2425

2526

0 commit comments

Comments
 (0)