rom c313849c2e5133802e21b13fa0b141b360171d39 Mon Sep 17 00:00:00 2001
From: Christian Persch <chpe@src.gnome.org>
Date: Sun, 2 Jun 2024 19:19:35 +0200
Subject: [PATCH] widget: Add safety limit to widget size requests

https://gitlab.gnome.org/GNOME/vte/-/issues/2786
(cherry picked from commit 1803ba866053a3d7840892b9d31fe2944a183eda)

Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/vte/-/commit/c313849c2e5133802e21b13fa0b141b360171d39]
CVE: CVE-2024-37535
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 src/vtegtk.cc | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 0f4641d..060d27e 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -91,6 +91,38 @@
 template<typename T>
 constexpr bool check_enum_value(T value) noexcept;
 
+static inline void
+sanitise_widget_size_request(int* minimum,
+                             int* natural) noexcept
+{
+        // Overly large size requests will make gtk happily allocate
+        // a window size over the window system's limits (see
+        // e.g. https://gitlab.gnome.org/GNOME/vte/-/issues/2786),
+        // leading to aborting the whole process.
+        // The toolkit should be in a better position to know about
+        // these limits and not exceed them (which here is certainly
+        // possible since our minimum sizes are very small), let's
+        // limit the widget's size request to some large value
+        // that hopefully is within the absolute limits of
+        // the window system (assumed here to be int16 range,
+        // and leaving some space for the widgets that contain
+        // the terminal).
+        auto const limit = (1 << 15) - (1 << 12);
+
+        if (*minimum > limit || *natural > limit) {
+                static auto warned = false;
+
+                if (!warned) {
+                        g_warning("Widget size request (minimum %d, natural %d) exceeds limits\n",
+                                  *minimum, *natural);
+                        warned = true;
+                }
+        }
+
+        *minimum = std::min(*minimum, limit);
+        *natural = std::clamp(*natural, *minimum, limit);
+}
+
 struct _VteTerminalClassPrivate {
         GtkStyleProvider *style_provider;
 };
@@ -497,6 +529,7 @@ try
 {
 	VteTerminal *terminal = VTE_TERMINAL(widget);
         WIDGET(terminal)->get_preferred_width(minimum_width, natural_width);
+        sanitise_widget_size_request(minimum_width, natural_width);
 }
 catch (...)
 {
@@ -511,6 +544,7 @@ try
 {
 	VteTerminal *terminal = VTE_TERMINAL(widget);
         WIDGET(terminal)->get_preferred_height(minimum_height, natural_height);
+        sanitise_widget_size_request(minimum_height, natural_height);
 }
 catch (...)
 {
@@ -748,6 +782,7 @@ try
         WIDGET(terminal)->measure(orientation, for_size,
                                   minimum, natural,
                                   minimum_baseline, natural_baseline);
+        sanitise_widget_size_request(minimum, natural);
 }
 catch (...)
 {
-- 
2.25.1

