CVE-2020-11095 (C, published 2020-06-22T22:15Z)
Description: value: In FreeRDP before version 2.1.2, an out of bound reads occurs resulting in accessing a memory location that is outside of the boundaries of the static array PRIMARY_DRAWING_ORDER_FIELD_BYTES. This is fixed in version 2.1.2.
Severity: MEDIUM (CVSS v3 base score: 5.4)
Weakness: CWE-125 \u2014 Out-of-bounds Read
The product reads data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/FreeRDP/FreeRDP
Files changed:
libfreerdp/core/orders.c
libfreerdp/core/orders.h
libfreerdp/core/update.c
Commit message: Fixed invalid access in update_recv_primary_order

CVE-2020-11095 thanks @antonio-morales for finding this.


Vulnerable code:
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))
	if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags,
	                             PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]))
FREERDP_LOCAL extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[];
	length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType];
	                         PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);

Fixed code:
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;
	}
}
	BYTE field;
	field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
	if (!rc)
		return FALSE;

	if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid);
	length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
	                         get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL));