Fixed invalid access in update_recv_primary_order
authorakallabeth <akallabeth@posteo.net>
Tue, 26 May 2020 05:28:33 +0000 (07:28 +0200)
committerArmin Novak <armin.novak@thincast.com>
Mon, 22 Jun 2020 10:12:41 +0000 (12:12 +0200)
CVE-2020-11095 thanks @antonio-morales for finding this.

(cherry picked from commit 733ee3208306b1ea32697b356c0215180fc3f049)

libfreerdp/core/orders.c
libfreerdp/core/orders.h
libfreerdp/core/update.c

index 87e0959..90d79f5 100644 (file)
 
 #define TAG FREERDP_TAG("core.orders")
 
-const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES,
-                                                      PATBLT_ORDER_FIELD_BYTES,
-                                                      SCRBLT_ORDER_FIELD_BYTES,
-                                                      0,
-                                                      0,
-                                                      0,
-                                                      0,
-                                                      DRAW_NINE_GRID_ORDER_FIELD_BYTES,
-                                                      MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES,
-                                                      LINE_TO_ORDER_FIELD_BYTES,
-                                                      OPAQUE_RECT_ORDER_FIELD_BYTES,
-                                                      SAVE_BITMAP_ORDER_FIELD_BYTES,
-                                                      0,
-                                                      MEMBLT_ORDER_FIELD_BYTES,
-                                                      MEM3BLT_ORDER_FIELD_BYTES,
-                                                      MULTI_DSTBLT_ORDER_FIELD_BYTES,
-                                                      MULTI_PATBLT_ORDER_FIELD_BYTES,
-                                                      MULTI_SCRBLT_ORDER_FIELD_BYTES,
-                                                      MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES,
-                                                      FAST_INDEX_ORDER_FIELD_BYTES,
-                                                      POLYGON_SC_ORDER_FIELD_BYTES,
-                                                      POLYGON_CB_ORDER_FIELD_BYTES,
-                                                      POLYLINE_ORDER_FIELD_BYTES,
-                                                      0,
-                                                      FAST_GLYPH_ORDER_FIELD_BYTES,
-                                                      ELLIPSE_SC_ORDER_FIELD_BYTES,
-                                                      ELLIPSE_CB_ORDER_FIELD_BYTES,
-                                                      GLYPH_INDEX_ORDER_FIELD_BYTES };
-
-#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES))
+BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
+{
+       if (pValid)
+               *pValid = TRUE;
+       switch (orderType)
+       {
+               case 0:
+                       return DSTBLT_ORDER_FIELD_BYTES;
+               case 1:
+                       return PATBLT_ORDER_FIELD_BYTES;
+               case 2:
+                       return SCRBLT_ORDER_FIELD_BYTES;
+               case 3:
+                       return 0;
+               case 4:
+                       return 0;
+               case 5:
+                       return 0;
+               case 6:
+                       return 0;
+               case 7:
+                       return DRAW_NINE_GRID_ORDER_FIELD_BYTES;
+               case 8:
+                       return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES;
+               case 9:
+                       return LINE_TO_ORDER_FIELD_BYTES;
+               case 10:
+                       return OPAQUE_RECT_ORDER_FIELD_BYTES;
+               case 11:
+                       return SAVE_BITMAP_ORDER_FIELD_BYTES;
+               case 12:
+                       return 0;
+               case 13:
+                       return MEMBLT_ORDER_FIELD_BYTES;
+               case 14:
+                       return MEM3BLT_ORDER_FIELD_BYTES;
+               case 15:
+                       return MULTI_DSTBLT_ORDER_FIELD_BYTES;
+               case 16:
+                       return MULTI_PATBLT_ORDER_FIELD_BYTES;
+               case 17:
+                       return MULTI_SCRBLT_ORDER_FIELD_BYTES;
+               case 18:
+                       return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES;
+               case 19:
+                       return FAST_INDEX_ORDER_FIELD_BYTES;
+               case 20:
+                       return POLYGON_SC_ORDER_FIELD_BYTES;
+               case 21:
+                       return POLYGON_CB_ORDER_FIELD_BYTES;
+               case 22:
+                       return POLYLINE_ORDER_FIELD_BYTES;
+               case 23:
+                       return 0;
+               case 24:
+                       return FAST_GLYPH_ORDER_FIELD_BYTES;
+               case 25:
+                       return ELLIPSE_SC_ORDER_FIELD_BYTES;
+               case 26:
+                       return ELLIPSE_CB_ORDER_FIELD_BYTES;
+               case 27:
+                       return GLYPH_INDEX_ORDER_FIELD_BYTES;
+               default:
+                       if (pValid)
+                               *pValid = FALSE;
+                       WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType);
+                       return 0;
+       }
+}
 
 static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
 
@@ -3240,6 +3279,7 @@ static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s,
 
 static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
 {
+       BYTE field;
        BOOL rc = FALSE;
        rdpContext* context = update->context;
        rdpPrimaryUpdate* primary = update->primary;
@@ -3263,8 +3303,11 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
        if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName))
                return FALSE;
 
-       if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags,
-                                    PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]))
+       field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
+       if (!rc)
+               return FALSE;
+
+       if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
        {
                WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed");
                return FALSE;
index 76e3d3f..d429dff 100644 (file)
 
 #define CG_GLYPH_UNICODE_PRESENT 0x0010
 
-FREERDP_LOCAL extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[];
+FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid);
 
 FREERDP_LOCAL BOOL update_recv_order(rdpUpdate* update, wStream* s);
 
index aac5881..ebb82fc 100644 (file)
@@ -1087,7 +1087,7 @@ static int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo,
        orderInfo->controlFlags = ORDER_STANDARD;
        orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
        length += 1;
-       length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType];
+       length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
        length += update_prepare_bounds(context, orderInfo);
        return length;
 }
@@ -1105,7 +1105,7 @@ static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO*
                Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
 
        update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags,
-                                PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);
+                                get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL));
        update_write_bounds(s, orderInfo);
        Stream_SetPosition(s, position);
        return 0;