From 6052846bc3b8e659244e88a4f0f4ebaedaca6267 Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 19 Apr 2020 21:05:40 +0200 Subject: [PATCH] added checks to mitigate floating point crashes --- src/messages/Image.cpp | 17 ++++++++++++-- src/providers/twitch/IrcMessageHandler.cpp | 5 ++++- src/providers/twitch/TwitchMessageBuilder.cpp | 1 + src/widgets/BaseWidget.cpp | 4 +++- src/widgets/BaseWindow.cpp | 4 ++-- src/widgets/Label.cpp | 6 +++-- src/widgets/Scrollbar.cpp | 19 ++++++++-------- src/widgets/dialogs/ColorPickerDialog.cpp | 1 + src/widgets/helper/ChannelView.cpp | 17 ++++++++------ src/widgets/helper/NotebookTab.cpp | 11 +++++----- src/widgets/settingspages/AboutPage.cpp | 7 ++++-- src/widgets/splits/SplitContainer.cpp | 22 ++++++++++++------- 12 files changed, 74 insertions(+), 40 deletions(-) diff --git a/src/messages/Image.cpp b/src/messages/Image.cpp index 4b115af37..37a8a644b 100644 --- a/src/messages/Image.cpp +++ b/src/messages/Image.cpp @@ -46,8 +46,16 @@ namespace detail { this->items_.begin(), this->items_.end(), 0UL, [](auto init, auto &&frame) { return init + frame.duration; }); - this->durationOffset_ = std::min( - int(getApp()->emotes->gifTimer.position() % totalLength), 60000); + if (totalLength == 0) + { + this->durationOffset_ = 0; + } + else + { + this->durationOffset_ = std::min( + int(getApp()->emotes->gifTimer.position() % totalLength), + 60000); + } this->processOffset(); } @@ -72,6 +80,11 @@ namespace detail { void Frames::processOffset() { + if (this->items_.isEmpty()) + { + return; + } + while (true) { this->index_ %= this->items_.size(); diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 833586d44..2abf3b9e0 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -53,7 +53,10 @@ static float relativeSimilarity(const QString &str1, const QString &str2) } } - return z == 0 ? 0.f : float(z) / std::max(str1.size(), str2.size()); + // ensure that no div by 0 + return z == 0 ? 0.f + : float(z) / + std::max(1, std::max(str1.size(), str2.size())); }; float IrcMessageHandler::similarity( diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 02a45a8f5..e064b5cea 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -60,6 +60,7 @@ QColor getRandomColor(const QVariant &userId) colorSeed = std::rand(); } + assert(twitchUsernameColors.size() != 0); const auto colorIndex = colorSeed % twitchUsernameColors.size(); return twitchUsernameColors[colorIndex]; } diff --git a/src/widgets/BaseWidget.cpp b/src/widgets/BaseWidget.cpp index 14c78040d..871c80f40 100644 --- a/src/widgets/BaseWidget.cpp +++ b/src/widgets/BaseWidget.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace chatterino { @@ -113,7 +114,8 @@ float BaseWidget::qtFontScale() const { if (auto window = dynamic_cast(this->window())) { - return this->scale() / window->nativeScale_; + // ensure no div by 0 + return this->scale() / std::max(0.01f, window->nativeScale_); } else { diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index c3bc34c95..1292fff6b 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -104,12 +104,12 @@ QRect BaseWindow::getBounds() float BaseWindow::scale() const { - return this->overrideScale().value_or(this->scale_); + return std::max(0.01f, this->overrideScale().value_or(this->scale_)); } float BaseWindow::qtFontScale() const { - return this->scale() / this->nativeScale_; + return this->scale() / std::max(0.01, this->nativeScale_); } void BaseWindow::init() diff --git a/src/widgets/Label.cpp b/src/widgets/Label.cpp index 330ab8528..e1a839e03 100644 --- a/src/widgets/Label.cpp +++ b/src/widgets/Label.cpp @@ -93,10 +93,12 @@ void Label::paintEvent(QPaintEvent *) QFontMetrics metrics = getFonts()->getFontMetrics( this->getFontStyle(), - this->scale() * 96.f / this->logicalDpiX() * deviceDpi); + this->scale() * 96.f / + std::max(0.01, this->logicalDpiX() * deviceDpi)); painter.setFont(getFonts()->getFont( this->getFontStyle(), - this->scale() * 96.f / this->logicalDpiX() * deviceDpi)); + this->scale() * 96.f / + std::max(0.02, this->logicalDpiX() * deviceDpi))); int offset = this->getOffset(); diff --git a/src/widgets/Scrollbar.cpp b/src/widgets/Scrollbar.cpp index bdecc3613..6f4288fd5 100644 --- a/src/widgets/Scrollbar.cpp +++ b/src/widgets/Scrollbar.cpp @@ -276,7 +276,8 @@ void Scrollbar::paintEvent(QPaintEvent *) int w = this->width(); float y = 0; - float dY = float(this->height()) / float(snapshotLength); + float dY = + float(this->height()) / std::max(1.0f, float(snapshotLength)); int highlightHeight = int(std::ceil(std::max(this->scale() * 2, dY))); @@ -356,8 +357,10 @@ void Scrollbar::mouseMoveEvent(QMouseEvent *event) { int delta = event->pos().y() - this->lastMousePosition_.y(); - setDesiredValue(this->desiredValue_ + - qreal(delta) / this->trackHeight_ * this->maximum_); + setDesiredValue( + this->desiredValue_ + + qreal(delta) / + std::max(0.02, this->trackHeight_ * this->maximum_)); } this->lastMousePosition_ = event->pos(); @@ -442,13 +445,11 @@ void Scrollbar::updateScroll() this->trackHeight_ = this->height() - this->buttonHeight_ - this->buttonHeight_ - MIN_THUMB_HEIGHT - 1; + auto div = std::max(0.01, this->maximum_ * this->trackHeight_); + this->thumbRect_ = - QRect(0, - int(this->currentValue_ / this->maximum_ * this->trackHeight_) + - 1 + this->buttonHeight_, - this->width(), - int(this->largeChange_ / this->maximum_ * this->trackHeight_) + - MIN_THUMB_HEIGHT); + QRect(0, int(this->currentValue_ / div) + 1 + this->buttonHeight_, + this->width(), int(this->largeChange_ / div) + MIN_THUMB_HEIGHT); this->update(); } diff --git a/src/widgets/dialogs/ColorPickerDialog.cpp b/src/widgets/dialogs/ColorPickerDialog.cpp index 669edf4f3..080442104 100644 --- a/src/widgets/dialogs/ColorPickerDialog.cpp +++ b/src/widgets/dialogs/ColorPickerDialog.cpp @@ -210,6 +210,7 @@ void ColorPickerDialog::initRecentColors(LayoutCreator &creator) this->ui_.recent.colors.push_back(new ColorButton(*it, this)); auto *button = this->ui_.recent.colors[ind]; + static_assert(RECENT_COLORS_PER_ROW != 0); const int rowInd = (ind / RECENT_COLORS_PER_ROW) + 1; const int columnInd = ind % RECENT_COLORS_PER_ROW; diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index ff29dc1aa..a069db0b9 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -319,7 +319,9 @@ void ChannelView::scaleChangedEvent(float scale) { auto factor = this->qtFontScale(); #ifdef Q_OS_MACOS - factor = scale * 80.f / this->logicalDpiX() * this->devicePixelRatioF(); + factor = scale * 80.f / + std::max( + 0.01, this->logicalDpiX() * this->devicePixelRatioF()); #endif this->goToBottom_->getLabel().setFont( getFonts()->getFont(FontStyle::UiMedium, factor)); @@ -426,8 +428,9 @@ void ChannelView::updateScrollbar( if (h < 0) // break condition { - this->scrollBar_->setLargeChange((messages.size() - i) + - qreal(h) / message->getHeight()); + this->scrollBar_->setLargeChange( + (messages.size() - i) + + qreal(h) / std::max(1, message->getHeight())); showScrollbar = true; break; @@ -964,8 +967,8 @@ void ChannelView::wheelEvent(QWheelEvent *event) if (delta > 0) { qreal scrollFactor = fmod(desired, 1); - qreal currentScrollLeft = - int(scrollFactor * snapshot[i]->getHeight()); + qreal currentScrollLeft = std::max( + 0.01, int(scrollFactor * snapshot[i]->getHeight())); for (; i >= 0; i--) { @@ -997,8 +1000,8 @@ void ChannelView::wheelEvent(QWheelEvent *event) { delta = -delta; qreal scrollFactor = 1 - fmod(desired, 1); - qreal currentScrollLeft = - int(scrollFactor * snapshot[i]->getHeight()); + qreal currentScrollLeft = std::max( + 0.01, int(scrollFactor * snapshot[i]->getHeight())); for (; i < snapshotLength; i++) { diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index e82424ecd..235aa99ce 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -282,12 +282,11 @@ void NotebookTab::paintEvent(QPaintEvent *) QPainter painter(this); float scale = this->scale(); - painter.setFont(getApp()->fonts->getFont( - FontStyle::UiTabs, - scale * 96.f / this->logicalDpiX() * deviceDpi(this))); - QFontMetrics metrics = app->fonts->getFontMetrics( - FontStyle::UiTabs, - scale * 96.f / this->logicalDpiX() * deviceDpi(this)); + auto div = std::max(0.01f, this->logicalDpiX() * deviceDpi(this)); + painter.setFont( + getApp()->fonts->getFont(FontStyle::UiTabs, scale * 96.f / div)); + QFontMetrics metrics = + app->fonts->getFontMetrics(FontStyle::UiTabs, scale * 96.f / div); int height = int(scale * NOTEBOOK_TAB_HEIGHT); diff --git a/src/widgets/settingspages/AboutPage.cpp b/src/widgets/settingspages/AboutPage.cpp index 4a51feda0..7587b244d 100644 --- a/src/widgets/settingspages/AboutPage.cpp +++ b/src/widgets/settingspages/AboutPage.cpp @@ -32,8 +32,11 @@ AboutPage::AboutPage() auto logo = layout.emplace().assign(&this->logo_); logo->setPixmap(pixmap); - logo->setFixedSize(PIXMAP_WIDTH, - PIXMAP_WIDTH * pixmap.height() / pixmap.width()); + if (pixmap.width() != 0) + { + logo->setFixedSize(PIXMAP_WIDTH, + PIXMAP_WIDTH * pixmap.height() / pixmap.width()); + } logo->setScaledContents(true); // this does nothing diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 004cb0d1e..feb59a1e5 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -962,8 +962,10 @@ void SplitContainer::Node::insertNextToThis(Split *_split, Direction _direction) { auto &siblings = this->parent_->children_; - qreal width = this->parent_->geometry_.width() / siblings.size(); - qreal height = this->parent_->geometry_.height() / siblings.size(); + qreal width = this->parent_->geometry_.width() / + std::max(0.0001, siblings.size()); + qreal height = this->parent_->geometry_.height() / + std::max(0.0001, siblings.size()); if (siblings.size() == 1) { @@ -1117,16 +1119,20 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, // vars qreal minSize = qreal(48 * _scale); - qreal totalFlex = this->getChildrensTotalFlex(isVertical); + qreal totalFlex = std::max( + 0.0001, this->getChildrensTotalFlex(isVertical)); qreal totalSize = std::accumulate( this->children_.begin(), this->children_.end(), qreal(0), [=](int val, std::unique_ptr &node) { - return val + std::max(this->getSize(isVertical) / - totalFlex * - node->getFlex(isVertical), - minSize); + return val + std::max( + this->getSize(isVertical) / + std::max(0.0001, totalFlex) * + node->getFlex(isVertical), + minSize); }); + totalSize = std::max(0.0001, totalSize); + qreal sizeMultiplier = this->getSize(isVertical) / totalSize; QRectF childRect = this->geometry_; @@ -1242,7 +1248,7 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, } } break; - }; + } } SplitContainer::Node::Type SplitContainer::Node::toContainerType(Direction _dir)