From 649beed45c87a1aa8d64bd815b46d1ae8071405b Mon Sep 17 00:00:00 2001 From: Sebastian Beckmann Date: Wed, 17 Sep 2025 13:37:37 +0200 Subject: [PATCH] frontend: Don't store QT_TO_UTF8 to std::string QT_TO_UTF8 returns a const char * that, in general, shouldn't be stored. This is because QT_TO_UTF8(str) expands to str.toUtf8().constData(): toUtf8() returns a QByteArray, and constData() the pointer to its data which is only valid until the QByteArray goes out of scope, which is immediately after the call. The original code that is changed here only works because in all of the situations, the object that is stored to is actually a std::string that gets constructed implicitly, so the constData() pointer is valid long enough for the std::string constructor to copy the data. The issue is that any "... = QT_TO_UTF8" code *looks* unsafe, and may lead new or unfamiliar contributors to assume that they can also use it, only to do "const char *... = QT_TO_UTF8(...)" which is dangerous. Additionally, it introduces an unnecessary round of implicit conversions and copies when QString.toStdString() already exists and copies into the string buffer directly. --- frontend/components/SourceTreeItem.cpp | 2 +- frontend/components/TextSourceToolbar.cpp | 2 +- frontend/dialogs/OBSBasicFilters.cpp | 2 +- frontend/settings/OBSBasicSettings.cpp | 7 +++---- frontend/settings/OBSBasicSettings_Stream.cpp | 10 +++++----- frontend/widgets/OBSBasic_Browser.cpp | 2 +- frontend/widgets/OBSBasic_Scenes.cpp | 2 +- frontend/wizards/AutoConfigStreamPage.cpp | 20 ++++++++++--------- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/frontend/components/SourceTreeItem.cpp b/frontend/components/SourceTreeItem.cpp index 97236a2a4..9d7971e28 100644 --- a/frontend/components/SourceTreeItem.cpp +++ b/frontend/components/SourceTreeItem.cpp @@ -370,7 +370,7 @@ void SourceTreeItem::ExitEditModeInternal(bool save) OBSBasic *main = OBSBasic::Get(); OBSScene scene = main->GetCurrentScene(); - newName = QT_TO_UTF8(editor->text()); + newName = editor->text().toStdString(); setFocusProxy(nullptr); int index = boxLayout->indexOf(editor); diff --git a/frontend/components/TextSourceToolbar.cpp b/frontend/components/TextSourceToolbar.cpp index be2d46525..673c3b1c7 100644 --- a/frontend/components/TextSourceToolbar.cpp +++ b/frontend/components/TextSourceToolbar.cpp @@ -137,7 +137,7 @@ void TextSourceToolbar::on_text_textChanged() if (!source) { return; } - std::string newText = QT_TO_UTF8(ui->text->text()); + std::string newText = ui->text->text().toStdString(); OBSDataAutoRelease settings = obs_source_get_settings(source); if (newText == obs_data_get_string(settings, "text")) { return; diff --git a/frontend/dialogs/OBSBasicFilters.cpp b/frontend/dialogs/OBSBasicFilters.cpp index cbc2f7654..e54a4f5fc 100644 --- a/frontend/dialogs/OBSBasicFilters.cpp +++ b/frontend/dialogs/OBSBasicFilters.cpp @@ -947,7 +947,7 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list) QListWidgetItem *listItem = list->currentItem(); OBSSource filter = listItem->data(Qt::UserRole).value(); QLineEdit *edit = qobject_cast(editor); - string name = QT_TO_UTF8(edit->text().trimmed()); + string name = edit->text().trimmed().toStdString(); const char *prevName = obs_source_get_name(filter); bool sameName = (name == prevName); diff --git a/frontend/settings/OBSBasicSettings.cpp b/frontend/settings/OBSBasicSettings.cpp index 7896a8d84..ddf9ea5a3 100644 --- a/frontend/settings/OBSBasicSettings.cpp +++ b/frontend/settings/OBSBasicSettings.cpp @@ -3153,7 +3153,7 @@ void OBSBasicSettings::SaveAdvancedSettings() #endif #ifdef _WIN32 - std::string priority = QT_TO_UTF8(ui->processPriority->currentData().toString()); + std::string priority = ui->processPriority->currentData().toString().toStdString(); config_set_string(App()->GetAppConfig(), "General", "ProcessPriority", priority.c_str()); if (main->Active()) SetProcessPriority(priority.c_str()); @@ -4168,9 +4168,8 @@ void OBSBasicSettings::ReloadAudioSources() void OBSBasicSettings::SpeakerLayoutChanged(int idx) { - QString speakerLayoutQstr = ui->channelSetup->itemText(idx); - std::string speakerLayout = QT_TO_UTF8(speakerLayoutQstr); - bool surround = IsSurround(speakerLayout.c_str()); + QByteArray speakerLayout = ui->channelSetup->itemText(idx).toUtf8(); + bool surround = IsSurround(speakerLayout.constData()); bool isOpus = ui->simpleOutStrAEncoder->currentData().toString() == "opus"; if (surround) { diff --git a/frontend/settings/OBSBasicSettings_Stream.cpp b/frontend/settings/OBSBasicSettings_Stream.cpp index 5179f44d8..05890b31b 100644 --- a/frontend/settings/OBSBasicSettings_Stream.cpp +++ b/frontend/settings/OBSBasicSettings_Stream.cpp @@ -621,7 +621,7 @@ void OBSBasicSettings::on_customServer_textChanged(const QString &) void OBSBasicSettings::ServiceChanged(bool resetFields) { - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); bool custom = IsCustomService(); bool whip = IsWHIP(); @@ -838,7 +838,7 @@ void OBSBasicSettings::OnOAuthStreamKeyConnected() void OBSBasicSettings::OnAuthConnected() { - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); Auth::Type type = Auth::AuthType(service); if (type == Auth::Type::OAuth_StreamKey || type == Auth::Type::OAuth_LinkedAccount) { @@ -853,7 +853,7 @@ void OBSBasicSettings::OnAuthConnected() void OBSBasicSettings::on_connectAccount_clicked() { - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); OAuth::DeleteCookies(service); @@ -890,7 +890,7 @@ void OBSBasicSettings::on_disconnectAccount_clicked() auth.reset(); main->SetBroadcastFlowEnabled(false); - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); #ifdef BROWSER_AVAILABLE OAuth::DeleteCookies(service); @@ -1154,7 +1154,7 @@ bool OBSBasicSettings::ResFPSValid(obs_service_resolution *res_list, size_t res_ if (fpsType != 0) return false; - std::string fps_str = QT_TO_UTF8(ui->fpsCommon->currentText()); + std::string fps_str = ui->fpsCommon->currentText().toStdString(); float fps; sscanf(fps_str.c_str(), "%f", &fps); if (fps > (float)max_fps) diff --git a/frontend/widgets/OBSBasic_Browser.cpp b/frontend/widgets/OBSBasic_Browser.cpp index ecac24957..641f01d39 100644 --- a/frontend/widgets/OBSBasic_Browser.cpp +++ b/frontend/widgets/OBSBasic_Browser.cpp @@ -132,7 +132,7 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url, con std::string script; script = "Object.defineProperty(document, 'referrer', { get: () => '"; script += "https://twitch.tv/"; - script += QT_TO_UTF8(username); + script += username.toStdString(); script += "/dashboard/live"; script += "'});"; browser->setStartupScript(script); diff --git a/frontend/widgets/OBSBasic_Scenes.cpp b/frontend/widgets/OBSBasic_Scenes.cpp index 4fa69941a..2e08b19a5 100644 --- a/frontend/widgets/OBSBasic_Scenes.cpp +++ b/frontend/widgets/OBSBasic_Scenes.cpp @@ -903,7 +903,7 @@ void OBSBasic::SceneNameEdited(QWidget *editor) { OBSScene scene = GetCurrentScene(); QLineEdit *edit = qobject_cast(editor); - string text = QT_TO_UTF8(edit->text().trimmed()); + string text = edit->text().trimmed().toStdString(); if (!scene) return; diff --git a/frontend/wizards/AutoConfigStreamPage.cpp b/frontend/wizards/AutoConfigStreamPage.cpp index 1e5c47536..365e66f96 100644 --- a/frontend/wizards/AutoConfigStreamPage.cpp +++ b/frontend/wizards/AutoConfigStreamPage.cpp @@ -136,10 +136,12 @@ bool AutoConfigStreamPage::validatePage() if (wiz->customServer) { QString server = ui->customServer->text().trimmed(); - wiz->server = wiz->serverName = QT_TO_UTF8(server); + const std::string name = server.toStdString(); + wiz->server = name; + wiz->serverName = name; } else { - wiz->serverName = QT_TO_UTF8(ui->server->currentText()); - wiz->server = QT_TO_UTF8(ui->server->currentData().toString()); + wiz->serverName = ui->server->currentText().toStdString(); + wiz->server = ui->server->currentData().toString().toStdString(); } wiz->bandwidthTest = ui->doBandwidthTest->isChecked(); @@ -149,10 +151,10 @@ bool AutoConfigStreamPage::validatePage() wiz->regionEU = ui->regionEU->isChecked(); wiz->regionAsia = ui->regionAsia->isChecked(); wiz->regionOther = ui->regionOther->isChecked(); - wiz->serviceName = QT_TO_UTF8(ui->service->currentText()); + wiz->serviceName = ui->service->currentText().toStdString(); if (ui->preferHardware) wiz->preferHardware = ui->preferHardware->isChecked(); - wiz->key = QT_TO_UTF8(ui->key->text()); + wiz->key = ui->key->text().toStdString(); if (!wiz->customServer) { if (wiz->serviceName == "Twitch") @@ -302,7 +304,7 @@ void AutoConfigStreamPage::OnOAuthStreamKeyConnected() void AutoConfigStreamPage::OnAuthConnected() { - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); Auth::Type type = Auth::AuthType(service); if (type == Auth::Type::OAuth_StreamKey || type == Auth::Type::OAuth_LinkedAccount) { @@ -312,7 +314,7 @@ void AutoConfigStreamPage::OnAuthConnected() void AutoConfigStreamPage::on_connectAccount_clicked() { - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); OAuth::DeleteCookies(service); @@ -342,7 +344,7 @@ void AutoConfigStreamPage::on_disconnectAccount_clicked() main->auth.reset(); auth.reset(); - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); #ifdef BROWSER_AVAILABLE OAuth::DeleteCookies(service); @@ -438,7 +440,7 @@ void AutoConfigStreamPage::ServiceChanged() if (showMore) return; - std::string service = QT_TO_UTF8(ui->service->currentText()); + std::string service = ui->service->currentText().toStdString(); bool regionBased = service == "Twitch"; bool testBandwidth = ui->doBandwidthTest->isChecked(); bool custom = IsCustomService();