Vulnerability: In FreeRDP before version 2.1.2, there is a global OOB read in update_read_cache_bitmap_v3_order. As a workaround, one can disable bitmap cache with -bitmap-cache (default). This is fixed in version 2.1.2.
Vulnerability ID: CVE-2020-11096
CWE: CWE-125
Severity score: 4.9
Project: https://github.com/FreeRDP/FreeRDP
Published: 2020-06-22
File: libfreerdp/core/orders.c
Commit message: Fixed OOB read in update_read_cache_bitmap_v3_order

CVE-2020-11096 thanks @antonio-morales for finding this.
Commit author: akallabeth

Vulnerable version (before fix):
 BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) 	} }  static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };  static const BYTE BPP_CBR2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 	                             0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };  static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };  static const BYTE BPP_CBR23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 	                              0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };  static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 };  static const BYTE BPP_BMF[] = { 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 	                            0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };  static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,                                   BOOL condition) static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag  	if (brush->style & CACHED_BRUSH) 	{ 		brush->index = brush->hatch; 		brush->bpp = BMF_BPP[brush->style & 0x07];  		if (brush->bpp == 0) 			brush->bpp = 1; 	} static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla  	if (brush->style & CACHED_BRUSH) 	{ 		brush->hatch = brush->index; 		brush->bpp = BMF_BPP[brush->style & 0x07];  		if (brush->bpp == 0) 			brush->bpp = 1; 	} BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,                                                                 BOOL compressed, UINT16 flags) { 	BYTE bitsPerPixelId; 	CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;  static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat 	cache_bitmap_v2->cacheId = flags & 0x0003; 	cache_bitmap_v2->flags = (flags & 0xFF80) >> 7; 	bitsPerPixelId = (flags & 0x0078) >> 3; 	cache_bitmap_v2->bitmapBpp = CBR2_BPP[bitsPerPixelId];  	if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT) 	{ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,                                         BOOL compressed, UINT16* flags) { 	BYTE bitsPerPixelId;  	if (!Stream_EnsureRemainingCapacity( 	        s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags))) 		return FALSE;  	bitsPerPixelId = BPP_CBR2[cache_bitmap_v2->bitmapBpp]; 	*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) | 	         ((cache_bitmap_v2->flags << 7) & 0xFF80);  BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,                                                                 UINT16 flags) { 	BYTE bitsPerPixelId; 	BITMAP_DATA_EX* bitmapData; 	UINT32 new_len; static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat 	cache_bitmap_v3->cacheId = flags & 0x00000003; 	cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7; 	bitsPerPixelId = (flags & 0x00000078) >> 3; 	cache_bitmap_v3->bpp = CBR23_BPP[bitsPerPixelId];  	if (Stream_GetRemainingLength(s) < 21) 		goto fail; int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,                                         UINT16* flags) { 	BYTE bitsPerPixelId; 	BITMAP_DATA_EX* bitmapData;  BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache 		return FALSE;  	bitmapData = &cache_bitmap_v3->bitmapData; 	bitsPerPixelId = BPP_CBR23[cache_bitmap_v3->bpp]; 	*flags = (cache_bitmap_v3->cacheId & 0x00000003) | 	         ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078); 	Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp) static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags) { 	int i; 	BYTE iBitmapFormat; 	BOOL compressed = FALSE; 	CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER)); static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre 	Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */ 	Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */  	if (iBitmapFormat >= ARRAYSIZE(BMF_BPP)) 		goto fail;  	cache_brush->bpp = BMF_BPP[iBitmapFormat]; 	Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */ 	Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */ 	Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */ BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_b { 	int i; 	BYTE iBitmapFormat; 	BOOL compressed = FALSE;  	if (!Stream_EnsureRemainingCapacity(s, 	                                    update_approximate_cache_brush_order(cache_brush, flags))) 		return FALSE;  	iBitmapFormat = BPP_BMF[cache_brush->bpp]; 	Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */ 	Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */ 	Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */

Fixed version (after fix):
 BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) 	} }  static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid) { 	if (pValid) 		*pValid = TRUE; 	switch (bpp) 	{ 		case 3: 			return 8; 		case 4: 			return 16; 		case 5: 			return 24; 		case 6: 			return 32; 		default: 			WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp); 			if (pValid) 				*pValid = FALSE; 			return 0; 	} }  static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid) { 	if (pValid) 		*pValid = TRUE; 	switch (bmf) 	{ 		case 1: 			return 1; 		case 3: 			return 8; 		case 4: 			return 16; 		case 5: 			return 24; 		case 6: 			return 32; 		default: 			WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf); 			if (pValid) 				*pValid = FALSE; 			return 0; 	} } static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid) { 	if (pValid) 		*pValid = TRUE; 	switch (bpp) 	{ 		case 1: 			return 1; 		case 8: 			return 3; 		case 16: 			return 4; 		case 24: 			return 5; 		case 32: 			return 6; 		default: 			WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp); 			if (pValid) 				*pValid = FALSE; 			return 0; 	} }  static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,                                   BOOL condition) static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag  	if (brush->style & CACHED_BRUSH) 	{ 		BOOL rc; 		brush->index = brush->hatch; 		brush->bpp = get_bmf_bpp(brush->style, &rc); 		if (!rc) 			return FALSE; 		if (brush->bpp == 0) 			brush->bpp = 1; 	} static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla  	if (brush->style & CACHED_BRUSH) 	{ 		BOOL rc; 		brush->hatch = brush->index; 		brush->bpp = get_bmf_bpp(brush->style, &rc); 		if (!rc) 			return FALSE; 		if (brush->bpp == 0) 			brush->bpp = 1; 	} BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,                                                                 BOOL compressed, UINT16 flags) { 	BOOL rc; 	BYTE bitsPerPixelId; 	CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;  static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat 	cache_bitmap_v2->cacheId = flags & 0x0003; 	cache_bitmap_v2->flags = (flags & 0xFF80) >> 7; 	bitsPerPixelId = (flags & 0x0078) >> 3; 	cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc); 	if (!rc) 		goto fail;  	if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT) 	{ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,                                         BOOL compressed, UINT16* flags) { 	BOOL rc; 	BYTE bitsPerPixelId;  	if (!Stream_EnsureRemainingCapacity( 	        s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags))) 		return FALSE;  	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc); 	if (!rc) 		return FALSE; 	*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) | 	         ((cache_bitmap_v2->flags << 7) & 0xFF80);  BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,                                                                 UINT16 flags) { 	BOOL rc; 	BYTE bitsPerPixelId; 	BITMAP_DATA_EX* bitmapData; 	UINT32 new_len; static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat 	cache_bitmap_v3->cacheId = flags & 0x00000003; 	cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7; 	bitsPerPixelId = (flags & 0x00000078) >> 3; 	cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc); 	if (!rc) 		goto fail;  	if (Stream_GetRemainingLength(s) < 21) 		goto fail; int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,                                         UINT16* flags) { 	BOOL rc; 	BYTE bitsPerPixelId; 	BITMAP_DATA_EX* bitmapData;  BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache 		return FALSE;  	bitmapData = &cache_bitmap_v3->bitmapData; 	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc); 	if (!rc) 		return FALSE; 	*flags = (cache_bitmap_v3->cacheId & 0x00000003) | 	         ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078); 	Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp) static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags) { 	int i; 	BOOL rc; 	BYTE iBitmapFormat; 	BOOL compressed = FALSE; 	CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER)); static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre 	Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */ 	Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */  	cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc); 	if (!rc) 		goto fail;  	Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */ 	Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */ 	Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */ BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_b { 	int i; 	BYTE iBitmapFormat; 	BOOL rc; 	BOOL compressed = FALSE;  	if (!Stream_EnsureRemainingCapacity(s, 	                                    update_approximate_cache_brush_order(cache_brush, flags))) 		return FALSE;  	iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc); 	if (!rc) 		return FALSE; 	Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */ 	Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */ 	Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */

Patch:
patch: @@ -113,20 +113,74 @@ BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
 	}
 }
 
-static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
-
-static const BYTE BPP_CBR2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-	                             0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
-
-static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
-
-static const BYTE BPP_CBR23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-	                              0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
-
-static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 };
+static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
+{
+	if (pValid)
+		*pValid = TRUE;
+	switch (bpp)
+	{
+		case 3:
+			return 8;
+		case 4:
+			return 16;
+		case 5:
+			return 24;
+		case 6:
+			return 32;
+		default:
+			WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
+			if (pValid)
+				*pValid = FALSE;
+			return 0;
+	}
+}
 
-static const BYTE BPP_BMF[] = { 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-	                            0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
+static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid)
+{
+	if (pValid)
+		*pValid = TRUE;
+	switch (bmf)
+	{
+		case 1:
+			return 1;
+		case 3:
+			return 8;
+		case 4:
+			return 16;
+		case 5:
+			return 24;
+		case 6:
+			return 32;
+		default:
+			WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf);
+			if (pValid)
+				*pValid = FALSE;
+			return 0;
+	}
+}
+static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
+{
+	if (pValid)
+		*pValid = TRUE;
+	switch (bpp)
+	{
+		case 1:
+			return 1;
+		case 8:
+			return 3;
+		case 16:
+			return 4;
+		case 24:
+			return 5;
+		case 32:
+			return 6;
+		default:
+			WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp);
+			if (pValid)
+				*pValid = FALSE;
+			return 0;
+	}
+}
 
 static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,
                                   BOOL condition)
@@ -814,9 +868,11 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag
 
 	if (brush->style & CACHED_BRUSH)
 	{
+		BOOL rc;
 		brush->index = brush->hatch;
-		brush->bpp = BMF_BPP[brush->style & 0x07];
-
+		brush->bpp = get_bmf_bpp(brush->style, &rc);
+		if (!rc)
+			return FALSE;
 		if (brush->bpp == 0)
 			brush->bpp = 1;
 	}
@@ -858,9 +914,11 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla
 
 	if (brush->style & CACHED_BRUSH)
 	{
+		BOOL rc;
 		brush->hatch = brush->index;
-		brush->bpp = BMF_BPP[brush->style & 0x07];
-
+		brush->bpp = get_bmf_bpp(brush->style, &rc);
+		if (!rc)
+			return FALSE;
 		if (brush->bpp == 0)
 			brush->bpp = 1;
 	}
@@ -2016,6 +2074,7 @@ BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache
 static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
                                                                 BOOL compressed, UINT16 flags)
 {
+	BOOL rc;
 	BYTE bitsPerPixelId;
 	CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
 
@@ -2030,7 +2089,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat
 	cache_bitmap_v2->cacheId = flags & 0x0003;
 	cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
 	bitsPerPixelId = (flags & 0x0078) >> 3;
-	cache_bitmap_v2->bitmapBpp = CBR2_BPP[bitsPerPixelId];
+	cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
+	if (!rc)
+		goto fail;
 
 	if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
 	{
@@ -2109,13 +2170,16 @@ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap
 BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
                                         BOOL compressed, UINT16* flags)
 {
+	BOOL rc;
 	BYTE bitsPerPixelId;
 
 	if (!Stream_EnsureRemainingCapacity(
 	        s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
 		return FALSE;
 
-	bitsPerPixelId = BPP_CBR2[cache_bitmap_v2->bitmapBpp];
+	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
+	if (!rc)
+		return FALSE;
 	*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
 	         ((cache_bitmap_v2->flags << 7) & 0xFF80);
 
@@ -2177,6 +2241,7 @@ BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache
 static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
                                                                 UINT16 flags)
 {
+	BOOL rc;
 	BYTE bitsPerPixelId;
 	BITMAP_DATA_EX* bitmapData;
 	UINT32 new_len;
@@ -2194,7 +2259,9 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat
 	cache_bitmap_v3->cacheId = flags & 0x00000003;
 	cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
 	bitsPerPixelId = (flags & 0x00000078) >> 3;
-	cache_bitmap_v3->bpp = CBR23_BPP[bitsPerPixelId];
+	cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
+	if (!rc)
+		goto fail;
 
 	if (Stream_GetRemainingLength(s) < 21)
 		goto fail;
@@ -2242,6 +2309,7 @@ int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap
 BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
                                         UINT16* flags)
 {
+	BOOL rc;
 	BYTE bitsPerPixelId;
 	BITMAP_DATA_EX* bitmapData;
 
@@ -2250,7 +2318,9 @@ BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache
 		return FALSE;
 
 	bitmapData = &cache_bitmap_v3->bitmapData;
-	bitsPerPixelId = BPP_CBR23[cache_bitmap_v3->bpp];
+	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
+	if (!rc)
+		return FALSE;
 	*flags = (cache_bitmap_v3->cacheId & 0x00000003) |
 	         ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
 	Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
@@ -2574,6 +2644,7 @@ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp)
 static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
 {
 	int i;
+	BOOL rc;
 	BYTE iBitmapFormat;
 	BOOL compressed = FALSE;
 	CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER));
@@ -2587,10 +2658,10 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
 	Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
 	Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */
 
-	if (iBitmapFormat >= ARRAYSIZE(BMF_BPP))
+	cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
+	if (!rc)
 		goto fail;
 
-	cache_brush->bpp = BMF_BPP[iBitmapFormat];
 	Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
 	Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
 	Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */
@@ -2661,13 +2732,16 @@ BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_b
 {
 	int i;
 	BYTE iBitmapFormat;
+	BOOL rc;
 	BOOL compressed = FALSE;
 
 	if (!Stream_EnsureRemainingCapacity(s,
 	                                    update_approximate_cache_brush_order(cache_brush, flags)))
 		return FALSE;
 
-	iBitmapFormat = BPP_BMF[cache_brush->bpp];
+	iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
+	if (!rc)
+		return FALSE;
 	Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */
 	Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */
 	Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
path: libfreerdp/core/orders.c