Skip to content

Commit

Permalink
fix: deadlock and use-after-free in tests (#4981)
Browse files Browse the repository at this point in the history
* fix: use-after-free in settings

* refactor: put seventv api into a singleton

* chore: add changelog entry

* Add warning for when the 7TV load fails
  • Loading branch information
Nerixyz committed Nov 26, 2023
1 parent 854032f commit e8673fc
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
- Dev: Removed `Outcome` from network requests. (#4959)
- Dev: Added Tests for Windows and MacOS in CI. (#4970)
- Dev: Refactored the Image Uploader feature. (#4971)
- Dev: Fixed deadlock and use-after-free in tests. (#4981)

## 2.4.6

Expand Down
5 changes: 5 additions & 0 deletions mocks/include/mocks/EmptyApplication.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class EmptyApplication : public IApplication
{
return nullptr;
}

SeventvAPI *getSeventvAPI() override
{
return nullptr;
}
};

} // namespace chatterino::mock
2 changes: 2 additions & 0 deletions src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "controllers/hotkeys/HotkeyController.hpp"
#include "controllers/ignores/IgnoreController.hpp"
#include "controllers/notifications/NotificationController.hpp"
#include "providers/seventv/SeventvAPI.hpp"
#include "singletons/ImageUploader.hpp"
#ifdef CHATTERINO_HAVE_PLUGINS
# include "controllers/plugins/PluginController.hpp"
Expand Down Expand Up @@ -81,6 +82,7 @@ Application::Application(Settings &_settings, Paths &_paths)
, windows(&this->emplace<WindowManager>())
, toasts(&this->emplace<Toasts>())
, imageUploader(&this->emplace<ImageUploader>())
, seventvAPI(&this->emplace<SeventvAPI>())

, commands(&this->emplace<CommandController>())
, notifications(&this->emplace<NotificationController>())
Expand Down
7 changes: 7 additions & 0 deletions src/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ChatterinoBadges;
class FfzBadges;
class SeventvBadges;
class ImageUploader;
class SeventvAPI;

class IApplication
{
Expand All @@ -68,6 +69,7 @@ class IApplication
virtual IUserDataController *getUserData() = 0;
virtual ITwitchLiveController *getTwitchLiveController() = 0;
virtual ImageUploader *getImageUploader() = 0;
virtual SeventvAPI *getSeventvAPI() = 0;
};

class Application : public IApplication
Expand Down Expand Up @@ -97,6 +99,7 @@ class Application : public IApplication
WindowManager *const windows{};
Toasts *const toasts{};
ImageUploader *const imageUploader{};
SeventvAPI *const seventvAPI{};

CommandController *const commands{};
NotificationController *const notifications{};
Expand Down Expand Up @@ -174,6 +177,10 @@ class Application : public IApplication
{
return this->imageUploader;
}
SeventvAPI *getSeventvAPI() override
{
return this->seventvAPI;
}

pajlada::Signals::NoArgSignal streamerModeChanged;

Expand Down
6 changes: 0 additions & 6 deletions src/providers/seventv/SeventvAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,5 @@ void SeventvAPI::updatePresence(const QString &twitchChannelID,
.execute();
}

SeventvAPI &getSeventvAPI()
{
static SeventvAPI instance;
return instance;
}

} // namespace chatterino
// NOLINTEND(readability-convert-member-functions-to-static)
36 changes: 23 additions & 13 deletions src/providers/seventv/SeventvAPI.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "common/Singleton.hpp"

#include <functional>

class QString;
Expand All @@ -9,25 +11,33 @@ namespace chatterino {

class NetworkResult;

class SeventvAPI
class SeventvAPI : public Singleton
{
using ErrorCallback = std::function<void(const NetworkResult &)>;
template <typename... T>
using SuccessCallback = std::function<void(T...)>;

public:
void getUserByTwitchID(const QString &twitchID,
SuccessCallback<const QJsonObject &> &&onSuccess,
ErrorCallback &&onError);
void getEmoteSet(const QString &emoteSet,
SuccessCallback<const QJsonObject &> &&onSuccess,
ErrorCallback &&onError);

void updatePresence(const QString &twitchChannelID,
const QString &seventvUserID,
SuccessCallback<> &&onSuccess, ErrorCallback &&onError);
SeventvAPI() = default;
~SeventvAPI() override = default;

SeventvAPI(const SeventvAPI &) = delete;
SeventvAPI(SeventvAPI &&) = delete;
SeventvAPI &operator=(const SeventvAPI &) = delete;
SeventvAPI &operator=(SeventvAPI &&) = delete;

virtual void getUserByTwitchID(
const QString &twitchID,
SuccessCallback<const QJsonObject &> &&onSuccess,
ErrorCallback &&onError);
virtual void getEmoteSet(const QString &emoteSet,
SuccessCallback<const QJsonObject &> &&onSuccess,
ErrorCallback &&onError);

virtual void updatePresence(const QString &twitchChannelID,
const QString &seventvUserID,
SuccessCallback<> &&onSuccess,
ErrorCallback &&onError);
};

SeventvAPI &getSeventvAPI();

} // namespace chatterino
3 changes: 0 additions & 3 deletions src/providers/seventv/SeventvBadges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

#include "messages/Emote.hpp"
#include "messages/Image.hpp"
#include "providers/seventv/SeventvAPI.hpp"
#include "providers/seventv/SeventvEmotes.hpp"

#include <QJsonArray>
#include <QUrl>
#include <QUrlQuery>

#include <map>

namespace chatterino {

std::optional<EmotePtr> SeventvBadges::getBadge(const UserId &id) const
Expand Down
7 changes: 4 additions & 3 deletions src/providers/seventv/SeventvEmotes.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "providers/seventv/SeventvEmotes.hpp"

#include "Application.hpp"
#include "common/Literals.hpp"
#include "common/NetworkResult.hpp"
#include "common/QLogging.hpp"
Expand Down Expand Up @@ -214,7 +215,7 @@ void SeventvEmotes::loadGlobalEmotes()

qCDebug(chatterinoSeventv) << "Loading 7TV Global Emotes";

getSeventvAPI().getEmoteSet(
getIApp()->getSeventvAPI()->getEmoteSet(
u"global"_s,
[this](const auto &json) {
QJsonArray parsedEmotes = json["emotes"].toArray();
Expand Down Expand Up @@ -243,7 +244,7 @@ void SeventvEmotes::loadChannelEmotes(
qCDebug(chatterinoSeventv)
<< "Reloading 7TV Channel Emotes" << channelId << manualRefresh;

getSeventvAPI().getUserByTwitchID(
getIApp()->getSeventvAPI()->getUserByTwitchID(
channelId,
[callback = std::move(callback), channel, channelId,
manualRefresh](const auto &json) {
Expand Down Expand Up @@ -405,7 +406,7 @@ void SeventvEmotes::getEmoteSet(
{
qCDebug(chatterinoSeventv) << "Loading 7TV Emote Set" << emoteSetId;

getSeventvAPI().getEmoteSet(
getIApp()->getSeventvAPI()->getEmoteSet(
emoteSetId,
[callback = std::move(successCallback), emoteSetId](const auto &json) {
auto parsedEmotes = json["emotes"].toArray();
Expand Down
10 changes: 9 additions & 1 deletion src/providers/twitch/TwitchAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,15 @@ void TwitchAccount::loadSeventvUserID()
return;
}

getSeventvAPI().getUserByTwitchID(
auto *seventv = getIApp()->getSeventvAPI();
if (!seventv)
{
qCWarning(chatterinoSeventv)
<< "Not loading 7TV User ID because the 7TV API is not initialized";
return;
}

seventv->getUserByTwitchID(
this->getUserId(),
[this](const auto &json) {
const auto id = json["user"]["id"].toString();
Expand Down
2 changes: 1 addition & 1 deletion src/providers/twitch/TwitchChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,7 @@ void TwitchChannel::updateSevenTVActivity()

qCDebug(chatterinoSeventv) << "Sending activity in" << this->getName();

getSeventvAPI().updatePresence(
getIApp()->getSeventvAPI()->updatePresence(
this->roomId(), currentSeventvUserID,
[chan = weakOf<Channel>(this)]() {
const auto self =
Expand Down
6 changes: 5 additions & 1 deletion src/singletons/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ bool Settings::toggleMutedChannel(const QString &channelName)
Settings *Settings::instance_ = nullptr;

Settings::Settings(const QString &settingsDirectory)
: prevInstance_(Settings::instance_)
{
QString settingsPath = settingsDirectory + "/settings.json";

Expand Down Expand Up @@ -188,7 +189,10 @@ Settings::Settings(const QString &settingsDirectory)
false);
}

Settings::~Settings() = default;
Settings::~Settings()
{
Settings::instance_ = this->prevInstance_;
}

void Settings::saveSnapshot()
{
Expand Down
1 change: 1 addition & 0 deletions src/singletons/Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum UsernameRightClickBehavior : int {
class Settings
{
static Settings *instance_;
Settings *prevInstance_ = nullptr;

public:
Settings(const QString &settingsDirectory);
Expand Down

0 comments on commit e8673fc

Please sign in to comment.