File gtk-vnc-CVE-2017-5885.patch of Package gtk-vnc.20718

diff --git a/src/vnccolormap.c b/src/vnccolormap.c
index 25cd2fc..f3e153a 100644
--- a/src/vnccolormap.c
+++ b/src/vnccolormap.c
@@ -119,7 +119,7 @@ gboolean vnc_color_map_set(VncColorMap *map,
                            guint16 green,
                            guint16 blue)
 {
-    if (idx >= (map->size + map->offset))
+    if (idx < map->offset || idx >= (map->size + map->offset))
         return FALSE;
 
     map->colors[idx - map->offset].red = red;
@@ -149,7 +149,7 @@ gboolean vnc_color_map_lookup(VncColorMap *map,
                               guint16 *green,
                               guint16 *blue)
 {
-    if (idx >= (map->size + map->offset))
+    if (idx < map->offset || idx >= (map->size + map->offset))
         return FALSE;
 
     *red = map->colors[idx - map->offset].red;
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 39f1966..efd1517 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -3339,8 +3339,13 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
 
         VNC_DEBUG("Colour map from %d with %d entries",
                   first_color, n_colors);
-        map = vnc_color_map_new(first_color, n_colors);
 
+        if (first_color > (65536 - n_colors)) {
+            vnc_connection_set_error(conn, "Colormap start %d out of range %d", first_color, 65536 - n_colors);
+            break;
+        }
+
+        map = vnc_color_map_new(first_color, n_colors);
         for (i = 0; i < n_colors; i++) {
             guint16 red, green, blue;
 
@@ -3348,9 +3353,14 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
             green = vnc_connection_read_u16(conn);
             blue = vnc_connection_read_u16(conn);
 
-            vnc_color_map_set(map,
-                              i + first_color,
-                              red, green, blue);
+            if (!vnc_color_map_set(map,
+                                   i + first_color,
+                                   red, green, blue)) {
+                /* Should not be reachable given earlier range check */
+                vnc_connection_set_error(conn, "Colormap index %d out of range %d,%d",
+                                         i + first_color, first_color, 65536 - n_colors);
+                break;
+            }
         }
 
         vnc_framebuffer_set_color_map(priv->fb, map);
diff --git a/src/vncconnectiontest.c b/src/vncconnectiontest.c
index 7ae7265..a4ea9eb 100644
--- a/src/vncconnectiontest.c
+++ b/src/vncconnectiontest.c
@@ -88,6 +88,21 @@ static void test_recv_u8(GInputStream *is, guint8 v)
     g_assert(e == v);
 }
 
+static void test_recv_u16(GInputStream *is, guint16 v)
+{
+    guint16 e;
+    g_assert(g_input_stream_read_all(is, &e, 2, NULL, NULL, NULL));
+    e = GINT16_FROM_BE(e);
+    g_assert(e == v);
+}
+
+static void test_recv_s32(GInputStream *is, gint32 v)
+{
+    gint32 e;
+    g_assert(g_input_stream_read_all(is, &e, 4, NULL, NULL, NULL));
+    e = GINT32_FROM_BE(e);
+    g_assert(e == v);
+}
 
 static gpointer test_helper_server(gpointer opaque)
 {
@@ -136,6 +151,8 @@ static gpointer test_helper_server(gpointer opaque)
     }
 
     g_object_unref(client);
+
+    return NULL;
 }
 
 static void test_helper_desktop_resize(VncConnection *conn,
@@ -359,6 +376,76 @@ static void test_copyrect_bounds_server(GInputStream *is, GOutputStream *os)
 }
 
 
+static void test_overflow_cmap_server(GInputStream *is, GOutputStream *os)
+{
+    /* Frame buffer width / height */
+    test_send_u16(os, 100);
+    test_send_u16(os, 100);
+
+    /* BPP, depth, endian, true color */
+    test_send_u8(os, 32);
+    test_send_u8(os, 8);
+    test_send_u8(os, 1);
+    test_send_u8(os, 0);
+
+    /* RGB max + shift*/
+    test_send_u16(os, 255);
+    test_send_u16(os, 255);
+    test_send_u16(os, 255);
+    test_send_u8(os, 0);
+    test_send_u8(os, 8);
+    test_send_u8(os, 16);
+
+    guint8 pad[3] = {0};
+    test_send_bytes(os, pad, G_N_ELEMENTS(pad));
+
+    /* name */
+    guint8 name[] = { 'T', 'e', 's', 't' };
+    test_send_u32(os, G_N_ELEMENTS(name));
+    test_send_bytes(os, name, G_N_ELEMENTS(name));
+
+    /* n-encodings */
+    test_recv_u8(is, 2);
+    /* pad */
+    test_recv_u8(is, 0);
+    /* num encodings */
+    test_recv_u16(is, 5);
+
+    /* encodings */
+    test_recv_s32(is, 16);
+    test_recv_s32(is, 5);
+    test_recv_s32(is, 2);
+    test_recv_s32(is, 1);
+    test_recv_s32(is, 0);
+
+    /* update request */
+    test_recv_u8(is, 3);
+    /* ! incremental */
+    test_recv_u8(is, 0);
+
+    /* x, y, w, h */
+    test_recv_u16(is, 0);
+    test_recv_u16(is, 0);
+    test_recv_u16(is, 100);
+    test_recv_u16(is, 100);
+
+    /* set color map */
+    test_send_u8(os, 1);
+    /* pad */
+    test_send_u8(os, 0);
+    /* first color, ncolors */
+    test_send_u16(os, 65535);
+    test_send_u16(os, 2);
+
+    /* r,g,b */
+    for (int i = 0 ; i < 2; i++) {
+        test_send_u16(os, i);
+        test_send_u16(os, i);
+        test_send_u16(os, i);
+    }
+}
+
+
 static void test_validation(void (*test_func)(GInputStream *, GOutputStream *))
 {
     struct GVncTest *test;
@@ -435,6 +522,11 @@ static void test_validation_copyrect(void)
 {
     test_validation(test_copyrect_bounds_server);
 }
+
+static void test_validation_overflow_cmap(void)
+{
+    test_validation(test_overflow_cmap_server);
+}
 #endif
 
 int main(int argc, char **argv) {
@@ -449,6 +541,7 @@ int main(int argc, char **argv) {
     g_test_add_func("/conn/validation/rre", test_validation_rre);
     g_test_add_func("/conn/validation/copyrect", test_validation_copyrect);
     g_test_add_func("/conn/validation/hextile", test_validation_hextile);
+    g_test_add_func("/conn/validation/overflowcmap", test_validation_overflow_cmap);
 #endif
 
     return g_test_run();
openSUSE Build Service is sponsored by