From 3ad8e821ec6a6e8408a9fc737b385aa863c67123 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 8 Dec 2018 12:06:17 +0100
Subject: Fixed one UAF when dealing with line text segments.

---
 src/glibext/gbufferline.c |  8 ++++----
 src/glibext/gbufferline.h |  4 ++--
 src/glibext/gbufferview.c |  9 +++++++--
 src/glibext/linecolumn.c  |  4 +++-
 src/glibext/linesegment.c | 21 ++++++++++++++++++++-
 src/glibext/linesegment.h |  3 +++
 6 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 2a3a04f..3dcbbd4 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -1029,14 +1029,14 @@ gint g_buffer_line_compute_max_width(const GBufferLine *line, BufferLineColumn i
 *                                                                             *
 ******************************************************************************/
 
-const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, const col_coord_t *coord)
+line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *line, const col_coord_t *coord)
 {
     line_segment *result;                   /* Trouvaille à retourner      */
 
     if (coord->column < BLC_COUNT)
         result = get_line_column_content_from_index(&line->columns[coord->column], coord->index);
     else
-        result = false;
+        result = NULL;
 
     return result;
 
@@ -1269,9 +1269,9 @@ bool g_buffer_line_get_coord_at(const GBufferLine *line, const line_width_summar
 *                                                                             *
 ******************************************************************************/
 
-const line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
+line_segment *g_buffer_line_get_segment_at(const GBufferLine *line, const line_width_summary *summary, const GDisplayOptions *options, const line_width_summary *offsets, gint *base, gint *offset, GdkScrollDirection dir, bool force)
 {
-    const line_segment *result;             /* Trouvaille à retourner      */
+    line_segment *result;                   /* Trouvaille à retourner      */
     col_coord_t coord;                      /* Emplacement du contenu visé */
     bool status;                            /* Bilan de la localisation    */
 
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 1d36d95..fe5cede 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -196,13 +196,13 @@ void g_buffer_line_collect_widths(GBufferLine *, line_width_summary *);
 gint g_buffer_line_compute_max_width(const GBufferLine *, BufferLineColumn, const line_width_summary *, const line_width_summary *);
 
 /* Fournit le segment présent à une position donnée. */
-const line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *, const col_coord_t *);
+line_segment *g_buffer_line_get_segment_from_coord(const GBufferLine *, const col_coord_t *);
 
 /* Fournit les coordonnées correspondant à une abscisse donnée. */
 bool g_buffer_line_get_coord_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool, col_coord_t *);
 
 /* Donne le segment présent à une abscisse donnée. */
-const line_segment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
+line_segment *g_buffer_line_get_segment_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
 
 /* Donne le créateur présent à une abscisse donnée. */
 GObject *g_buffer_line_get_creator_at(const GBufferLine *, const line_width_summary *, const GDisplayOptions *, const line_width_summary *, gint *, gint *, GdkScrollDirection, bool);
diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c
index bc8cf54..f5adc9d 100644
--- a/src/glibext/gbufferview.c
+++ b/src/glibext/gbufferview.c
@@ -725,7 +725,7 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
     line_width_summary summary;             /* Résumé concis des largeurs  */
     gint base;                              /* Position absolue de segment */
     col_coord_t coord;                      /* Coordonnées en interne      */
-    const line_segment *segment;            /* Bribe de texte trouvée      */
+    line_segment *segment;                  /* Bribe de texte trouvée      */
 
 
     result = false;
@@ -751,6 +751,8 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line
 
         result = move_caret_on_line_segment(segment, &offset, ctrl, dir);
 
+        release_line_segment(segment);
+
     }
 
     /* Tentative de déplacement chez le segment voisin ? */
@@ -1031,7 +1033,7 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G
     size_t index;                           /* Indice de ligne de tampon   */
     GBufferLine *line;                      /* Ligne à la position courante*/
     line_width_summary summary;             /* Résumé concis des largeurs  */
-    const line_segment *segment;            /* Segment sélectionnable      */
+    line_segment *segment;                  /* Segment sélectionnable      */
 
     /* Réinitialisation */
 
@@ -1075,7 +1077,10 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G
     /* Conclusion */
 
     if (segment != NULL)
+    {
         result |= add_segment_content_to_selection_list(view->highlighted, segment);
+        release_line_segment(segment);
+    }
 
     if (result)
         g_signal_emit_by_name(view, "need-redraw");
diff --git a/src/glibext/linecolumn.c b/src/glibext/linecolumn.c
index 2d24926..6b6937f 100644
--- a/src/glibext/linecolumn.c
+++ b/src/glibext/linecolumn.c
@@ -153,7 +153,7 @@ size_t append_text_to_line_column(line_column *column, const char *text, size_t
 
     segment = get_new_line_segment(type, text, length);
 
-    column->segments = (line_segment **)realloc(column->segments, ++column->count * sizeof(line_segment *));
+    column->segments = realloc(column->segments, ++column->count * sizeof(line_segment *));
 
     column->segments[result] = segment;
 
@@ -396,6 +396,8 @@ line_segment *get_line_column_content_from_index(const line_column *column, size
 
     result = column->segments[index];
 
+    ref_line_segment(result);
+
     return result;
 
 }
diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c
index dc4a128..557dff2 100644
--- a/src/glibext/linesegment.c
+++ b/src/glibext/linesegment.c
@@ -466,6 +466,25 @@ line_segment *get_new_line_segment(RenderingTagType type, const char *text, size
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : segment = fragment de texte à traiter.                       *
+*                                                                             *
+*  Description : Augmente le compteur de références d'un fragment de texte.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void ref_line_segment(line_segment *segment)
+{
+    segment->ref_count++;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : segment = fragment de texte à libérer de la mémoire.         *
 *                                                                             *
 *  Description : Retire une utilisation à un fragment de texte.               *
@@ -1037,7 +1056,7 @@ bool add_segment_content_to_selection_list(segcnt_list *list, const line_segment
 
     if (result)
     {
-        list->hashes = (fnv64_t *)realloc(list->hashes, ++list->count * sizeof(fnv64_t));
+        list->hashes = realloc(list->hashes, ++list->count * sizeof(fnv64_t));
 
         list->hashes[list->count - 1] = segment->hash;
 
diff --git a/src/glibext/linesegment.h b/src/glibext/linesegment.h
index a0b8e91..c6deb38 100644
--- a/src/glibext/linesegment.h
+++ b/src/glibext/linesegment.h
@@ -114,6 +114,9 @@ typedef enum _RenderingTagType
 /* Crée un nouveau fragment de texte avec des propriétés. */
 line_segment *get_new_line_segment(RenderingTagType, const char *, size_t);
 
+/* Augmente le compteur de références d'un fragment de texte. */
+void ref_line_segment(line_segment *);
+
 /* Retire une utilisation à un fragment de texte. */
 void release_line_segment(line_segment *);
 
-- 
cgit v0.11.2-87-g4458