Skip to content

Commit b8beb55

Browse files
committed
Fixed OOB read in update_read_cache_bitmap_v3_order
CVE-2020-11096 thanks @antonio-morales for finding this.
1 parent 733ee32 commit b8beb55

File tree

1 file changed

+98
-24
lines changed

1 file changed

+98
-24
lines changed

Diff for: libfreerdp/core/orders.c

+98-24
Original file line numberDiff line numberDiff line change
@@ -113,20 +113,74 @@ BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
113113
}
114114
}
115115

116-
static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
117-
118-
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,
119-
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
120-
121-
static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
122-
123-
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,
124-
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
125-
126-
static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 };
116+
static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
117+
{
118+
if (pValid)
119+
*pValid = TRUE;
120+
switch (bpp)
121+
{
122+
case 3:
123+
return 8;
124+
case 4:
125+
return 16;
126+
case 5:
127+
return 24;
128+
case 6:
129+
return 32;
130+
default:
131+
WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
132+
if (pValid)
133+
*pValid = FALSE;
134+
return 0;
135+
}
136+
}
127137

128-
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,
129-
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
138+
static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid)
139+
{
140+
if (pValid)
141+
*pValid = TRUE;
142+
switch (bmf)
143+
{
144+
case 1:
145+
return 1;
146+
case 3:
147+
return 8;
148+
case 4:
149+
return 16;
150+
case 5:
151+
return 24;
152+
case 6:
153+
return 32;
154+
default:
155+
WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf);
156+
if (pValid)
157+
*pValid = FALSE;
158+
return 0;
159+
}
160+
}
161+
static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
162+
{
163+
if (pValid)
164+
*pValid = TRUE;
165+
switch (bpp)
166+
{
167+
case 1:
168+
return 1;
169+
case 8:
170+
return 3;
171+
case 16:
172+
return 4;
173+
case 24:
174+
return 5;
175+
case 32:
176+
return 6;
177+
default:
178+
WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp);
179+
if (pValid)
180+
*pValid = FALSE;
181+
return 0;
182+
}
183+
}
130184

131185
static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,
132186
BOOL condition)
@@ -814,9 +868,11 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag
814868

815869
if (brush->style & CACHED_BRUSH)
816870
{
871+
BOOL rc;
817872
brush->index = brush->hatch;
818-
brush->bpp = BMF_BPP[brush->style & 0x07];
819-
873+
brush->bpp = get_bmf_bpp(brush->style, &rc);
874+
if (!rc)
875+
return FALSE;
820876
if (brush->bpp == 0)
821877
brush->bpp = 1;
822878
}
@@ -858,9 +914,11 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla
858914

859915
if (brush->style & CACHED_BRUSH)
860916
{
917+
BOOL rc;
861918
brush->hatch = brush->index;
862-
brush->bpp = BMF_BPP[brush->style & 0x07];
863-
919+
brush->bpp = get_bmf_bpp(brush->style, &rc);
920+
if (!rc)
921+
return FALSE;
864922
if (brush->bpp == 0)
865923
brush->bpp = 1;
866924
}
@@ -2016,6 +2074,7 @@ BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache
20162074
static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
20172075
BOOL compressed, UINT16 flags)
20182076
{
2077+
BOOL rc;
20192078
BYTE bitsPerPixelId;
20202079
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
20212080

@@ -2030,7 +2089,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat
20302089
cache_bitmap_v2->cacheId = flags & 0x0003;
20312090
cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
20322091
bitsPerPixelId = (flags & 0x0078) >> 3;
2033-
cache_bitmap_v2->bitmapBpp = CBR2_BPP[bitsPerPixelId];
2092+
cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2093+
if (!rc)
2094+
goto fail;
20342095

20352096
if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
20362097
{
@@ -2109,13 +2170,16 @@ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap
21092170
BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
21102171
BOOL compressed, UINT16* flags)
21112172
{
2173+
BOOL rc;
21122174
BYTE bitsPerPixelId;
21132175

21142176
if (!Stream_EnsureRemainingCapacity(
21152177
s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
21162178
return FALSE;
21172179

2118-
bitsPerPixelId = BPP_CBR2[cache_bitmap_v2->bitmapBpp];
2180+
bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
2181+
if (!rc)
2182+
return FALSE;
21192183
*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
21202184
((cache_bitmap_v2->flags << 7) & 0xFF80);
21212185

@@ -2177,6 +2241,7 @@ BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache
21772241
static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
21782242
UINT16 flags)
21792243
{
2244+
BOOL rc;
21802245
BYTE bitsPerPixelId;
21812246
BITMAP_DATA_EX* bitmapData;
21822247
UINT32 new_len;
@@ -2194,7 +2259,9 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat
21942259
cache_bitmap_v3->cacheId = flags & 0x00000003;
21952260
cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
21962261
bitsPerPixelId = (flags & 0x00000078) >> 3;
2197-
cache_bitmap_v3->bpp = CBR23_BPP[bitsPerPixelId];
2262+
cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2263+
if (!rc)
2264+
goto fail;
21982265

21992266
if (Stream_GetRemainingLength(s) < 21)
22002267
goto fail;
@@ -2242,6 +2309,7 @@ int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap
22422309
BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
22432310
UINT16* flags)
22442311
{
2312+
BOOL rc;
22452313
BYTE bitsPerPixelId;
22462314
BITMAP_DATA_EX* bitmapData;
22472315

@@ -2250,7 +2318,9 @@ BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache
22502318
return FALSE;
22512319

22522320
bitmapData = &cache_bitmap_v3->bitmapData;
2253-
bitsPerPixelId = BPP_CBR23[cache_bitmap_v3->bpp];
2321+
bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
2322+
if (!rc)
2323+
return FALSE;
22542324
*flags = (cache_bitmap_v3->cacheId & 0x00000003) |
22552325
((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
22562326
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)
25742644
static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
25752645
{
25762646
int i;
2647+
BOOL rc;
25772648
BYTE iBitmapFormat;
25782649
BOOL compressed = FALSE;
25792650
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
25872658
Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
25882659
Stream_Read_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */
25892660

2590-
if (iBitmapFormat >= ARRAYSIZE(BMF_BPP))
2661+
cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
2662+
if (!rc)
25912663
goto fail;
25922664

2593-
cache_brush->bpp = BMF_BPP[iBitmapFormat];
25942665
Stream_Read_UINT8(s, cache_brush->cx); /* cx (1 byte) */
25952666
Stream_Read_UINT8(s, cache_brush->cy); /* cy (1 byte) */
25962667
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
26612732
{
26622733
int i;
26632734
BYTE iBitmapFormat;
2735+
BOOL rc;
26642736
BOOL compressed = FALSE;
26652737

26662738
if (!Stream_EnsureRemainingCapacity(s,
26672739
update_approximate_cache_brush_order(cache_brush, flags)))
26682740
return FALSE;
26692741

2670-
iBitmapFormat = BPP_BMF[cache_brush->bpp];
2742+
iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
2743+
if (!rc)
2744+
return FALSE;
26712745
Stream_Write_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
26722746
Stream_Write_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */
26732747
Stream_Write_UINT8(s, cache_brush->cx); /* cx (1 byte) */

0 commit comments

Comments
 (0)