[gtksourceview/gnome-3-24] contextengine: disable highlighting in presence of long lines



commit 380d8d0b9a04d2811dd78764a74d1c1bdcba74fb
Author: Christian Hergert <chergert redhat com>
Date:   Fri Apr 19 13:59:47 2019 -0700

    contextengine: disable highlighting in presence of long lines
    
    If we come across a pathologically long line (defined as 2000 characters),
    then disable highlighting. As highlighting is line-based, this allows us
    to protect ourselves and keep the text editor working as fast as
    GtkTextView is willing to support.
    
    In particular, this also helps mitigate against libpcre's insistance on
    stack-overflow'ing in some situations from long input combined with
    complex regexes.
    
    It would be nice if we could determine what type of regexes are likely to
    be a potential failure for this and only limit those, but this solution
    is more likely to have the secondary effect of improving performance for
    minified HTML, CSS, etc.
    
    I think a pre-requisite to remove this feature would be for GLib to move
    to using libpcre2 for GRegex (also allowing for JIT support) as well as
    GtkTextView improving beyond line-based layout/rendering (which probably
    requires character indexes within lines).
    
    Fixes #47

 gtksourceview/gtksourcecontextengine.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
---
diff --git a/gtksourceview/gtksourcecontextengine.c b/gtksourceview/gtksourcecontextengine.c
index f74ec78e..6c549b2b 100644
--- a/gtksourceview/gtksourcecontextengine.c
+++ b/gtksourceview/gtksourcecontextengine.c
@@ -87,6 +87,12 @@
  */
 #define MAX_TIME_FOR_ONE_LINE          2000
 
+/* Maximum number of characters supported in one line or else highlighting
+ * is dsiabled. This helps mitigate chances that libpcre can cause us to
+ * overflow from poorly crafted regexes.
+ */
+#define LINE_MAX_SUPPORTED_CHARS       2000
+
 #define GTK_SOURCE_CONTEXT_ENGINE_ERROR (gtk_source_context_engine_error_quark ())
 
 #define HAS_OPTION(def,opt) (((def)->flags & GTK_SOURCE_CONTEXT_##opt) != 0)
@@ -4202,6 +4208,16 @@ next_segment (GtkSourceContextEngine  *ce,
        g_assert (!ce->priv->hint2 || ce->priv->hint2->parent == state);
        g_assert (pos <= line->byte_length);
 
+       /* Bail on pathologically long lines to protect against possible
+        * recursion in regexes, as libpcre can stack-overflow. Also help to
+        * keep things fast in the presence of such difficult input.
+        */
+       if (line->char_length > LINE_MAX_SUPPORTED_CHARS)
+       {
+               ce->priv->disabled = TRUE;
+               return FALSE;
+       }
+
        while (pos <= line->byte_length)
        {
                DefinitionsIter def_iter;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]