From 200f50c1f633edaa97153e0696a063ff9752e341 Mon Sep 17 00:00:00 2001 From: Kobi Mizrachi Date: Tue, 17 Dec 2019 11:16:54 +0200 Subject: [PATCH] update: add proper stream checks --- libfreerdp/core/update.c | 235 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 164 insertions(+), 71 deletions(-) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index b32cf8c..a330f20 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -2016,130 +2016,185 @@ static BOOL update_send_set_keyboard_ime_status(rdpContext* context, UINT16 imeI return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId); } +static UINT16 update_calculate_new_or_existing_window(const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_STATE_ORDER* stateOrder) +{ + UINT16 orderSize = 11; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0) + orderSize += 4; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0) + orderSize += 1; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0) + orderSize += 2 + stateOrder->titleInfo.length; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0) + orderSize += 1; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0) + orderSize += 4; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0) + orderSize += 2 + stateOrder->numWindowRects * sizeof(RECTANGLE_16); + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0) + orderSize += 8; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0) + orderSize += 2 + stateOrder->numVisibilityRects * sizeof(RECTANGLE_16); + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0) + orderSize += 2 + stateOrder->OverlayDescription.length; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0) + orderSize += 1; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0) + orderSize += 1; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0) + orderSize += 1; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0) + orderSize += 1; + + return orderSize; +} + BOOL update_send_new_or_existing_window(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const WINDOW_STATE_ORDER* stateOrder) { wStream* s; rdpUpdate* update = context->update; BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2); - UINT16 orderSize = 11; - size_t orderSizePos, orderEndPos; + UINT16 orderSize; s = update->us; if (!s) return FALSE; - Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ - orderSizePos = Stream_GetPosition(s); - Stream_Seek_UINT16(s); /* OrderSize (2 bytes) */ + orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder); + + if (!Stream_EnsureRemainingCapacity(s, orderSize)) + return FALSE; + + Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ + Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */ Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */ Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */ - orderSize = 11; if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0) - { - orderSize += 4; Stream_Write_UINT32(s, stateOrder->ownerWindowId); - } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->style); Stream_Write_UINT32(s, stateOrder->extendedStyle); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->showState); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0) { - orderSize += 2 + stateOrder->titleInfo.length; Stream_Write_UINT16(s, stateOrder->titleInfo.length); Stream_Write(s, stateOrder->titleInfo.string, stateOrder->titleInfo.length); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->clientOffsetX); Stream_Write_UINT32(s, stateOrder->clientOffsetY); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->clientAreaWidth); Stream_Write_UINT32(s, stateOrder->clientAreaHeight); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->resizeMarginLeft); Stream_Write_UINT32(s, stateOrder->resizeMarginRight); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->resizeMarginTop); Stream_Write_UINT32(s, stateOrder->resizeMarginBottom); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->RPContent); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0) { - orderSize += 4; Stream_Write_UINT32(s, stateOrder->rootParentHandle); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->windowOffsetX); Stream_Write_UINT32(s, stateOrder->windowOffsetY); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->windowClientDeltaX); Stream_Write_UINT32(s, stateOrder->windowClientDeltaY); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->windowWidth); Stream_Write_UINT32(s, stateOrder->windowHeight); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0) { - orderSize += 2 + stateOrder->numWindowRects * sizeof(RECTANGLE_16); Stream_Write_UINT16(s, stateOrder->numWindowRects); Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects * sizeof(RECTANGLE_16)); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0) { - orderSize += 8; Stream_Write_UINT32(s, stateOrder->visibleOffsetX); Stream_Write_UINT32(s, stateOrder->visibleOffsetY); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0) { - orderSize += 2 + stateOrder->numVisibilityRects * sizeof(RECTANGLE_16); Stream_Write_UINT16(s, stateOrder->numVisibilityRects); Stream_Write(s, stateOrder->visibilityRects, stateOrder->numVisibilityRects * sizeof(RECTANGLE_16)); @@ -2147,7 +2202,6 @@ BOOL update_send_new_or_existing_window(rdpContext* context, const WINDOW_ORDER_ if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0) { - orderSize += 2 + stateOrder->OverlayDescription.length; Stream_Write_UINT16(s, stateOrder->OverlayDescription.length); Stream_Write(s, stateOrder->OverlayDescription.string, stateOrder->OverlayDescription.length); @@ -2155,33 +2209,24 @@ BOOL update_send_new_or_existing_window(rdpContext* context, const WINDOW_ORDER_ if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->TaskbarButton); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->AppBarState); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0) { - orderSize += 1; Stream_Write_UINT8(s, stateOrder->AppBarEdge); } - /* Write size */ - orderEndPos = Stream_GetPosition(s); - Stream_SetPosition(s, orderSizePos); - Stream_Write_UINT16(s, orderSize); - Stream_SetPosition(s, orderEndPos); update->numberOrders++; return TRUE; } @@ -2198,24 +2243,40 @@ BOOL update_send_window_update(rdpContext* context, const WINDOW_ORDER_INFO* ord return update_send_new_or_existing_window(context, orderInfo, stateOrder); } +static UINT16 update_calculate_window_icon_order(const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_ICON_ORDER* iconOrder) +{ + UINT16 orderSize = 23; + ICON_INFO* iconInfo = iconOrder->iconInfo; + + orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask; + + if (iconInfo->bpp <= 8) + orderSize += 2 + iconInfo->cbColorTable; + + return orderSize; +} + BOOL update_send_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const WINDOW_ICON_ORDER* iconOrder) { wStream* s; rdpUpdate* update = context->update; BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2); - UINT16 orderSize = 23; - size_t orderSizePos, orderEndPos; + UINT16 orderSize; ICON_INFO* iconInfo = iconOrder->iconInfo; s = update->us; - if (!s) + if (!s || !iconInfo) + return FALSE; + + orderSize = update_calculate_window_icon_order(orderInfo, iconOrder); + if (!Stream_EnsureRemainingCapacity(s, orderSize)) return FALSE; /* Write Hdr */ - Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ - orderSizePos = Stream_GetPosition(s); - Stream_Seek_UINT16(s); /* OrderSize (2 bytes) */ + Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ + Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */ Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */ Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */ /* Write body */ @@ -2228,27 +2289,19 @@ BOOL update_send_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* order if (iconInfo->bpp <= 8) { Stream_Write_UINT16(s, iconInfo->cbColorTable); /* CbColorTable (2 bytes) */ - orderSize += 2; } Stream_Write_UINT16(s, iconInfo->cbBitsMask); /* CbBitsMask (2 bytes) */ Stream_Write_UINT16(s, iconInfo->cbBitsColor); /* CbBitsColor (2 bytes) */ Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask); /* BitsMask (variable) */ - orderSize += iconInfo->cbBitsMask; if (iconInfo->bpp <= 8) { Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable); /* ColorTable (variable) */ - orderSize += iconInfo->cbColorTable; } Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor); /* BitsColor (variable) */ - orderSize += iconInfo->cbBitsColor; - /* Write size */ - orderEndPos = Stream_GetPosition(s); - Stream_SetPosition(s, orderSizePos); - Stream_Write_UINT16(s, orderSize); - Stream_SetPosition(s, orderEndPos); + update->numberOrders++; return TRUE; } @@ -2266,6 +2319,9 @@ BOOL update_send_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO if (!s) return FALSE; + if (!Stream_EnsureRemainingCapacity(s, orderSize)) + return FALSE; + /* Write Hdr */ Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */ @@ -2289,6 +2345,9 @@ BOOL update_send_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* ord if (!s) return FALSE; + if (!Stream_EnsureRemainingCapacity(s, orderSize)) + return FALSE; + /* Write Hdr */ Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */ @@ -2298,6 +2357,48 @@ BOOL update_send_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* ord return TRUE; } +static UINT16 update_calculate_new_or_existing_notification_icons_order( + const WINDOW_ORDER_INFO* orderInfo, const NOTIFY_ICON_STATE_ORDER* iconStateOrder) +{ + UINT16 orderSize = 15; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0) + orderSize += 4; + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0) + { + orderSize += 2 + iconStateOrder->toolTip.length; + } + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0) + { + NOTIFY_ICON_INFOTIP infoTip = iconStateOrder->infoTip; + orderSize += 12 + infoTip.text.length + infoTip.title.length; + } + + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0) + { + orderSize += 4; + } + + if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0) + { + ICON_INFO iconInfo = iconStateOrder->icon; + orderSize += 12; + + if (iconInfo.bpp <= 8) + orderSize += 2 + iconInfo.cbColorTable; + + orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor; + } + else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0) + { + orderSize += 3; + } + + return orderSize; +} + BOOL update_send_new_or_existing_notification_icons(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const NOTIFY_ICON_STATE_ORDER* iconStateOrder) @@ -2305,18 +2406,22 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, wStream* s; rdpUpdate* update = context->update; BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2); - UINT16 orderSize = 15; - size_t orderSizePos, orderEndPos; + UINT16 orderSize; BOOL versionFieldPresent = FALSE; s = update->us; if (!s) return FALSE; + orderSize = + update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder); + + if (!Stream_EnsureRemainingCapacity(s, orderSize)) + return FALSE; + /* Write Hdr */ - Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ - orderSizePos = Stream_GetPosition(s); - Stream_Seek_UINT16(s); /* OrderSize (2 bytes) */ + Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */ + Stream_Write_INT16(s, orderSize); /* OrderSize (2 bytes) */ Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */ Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */ Stream_Write_UINT32(s, orderInfo->notifyIconId); /* NotifyIconId (4 bytes) */ @@ -2325,14 +2430,11 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0) { versionFieldPresent = TRUE; - - orderSize += 4; Stream_Write_UINT32(s, iconStateOrder->version); } if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0) { - orderSize += 2 + iconStateOrder->toolTip.length; Stream_Write_UINT16(s, iconStateOrder->toolTip.length); Stream_Write(s, iconStateOrder->toolTip.string, iconStateOrder->toolTip.length); } @@ -2345,7 +2447,6 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, if (versionFieldPresent && iconStateOrder->version == 0) return FALSE; - orderSize += 12 + infoTip.text.length + infoTip.title.length; Stream_Write_UINT32(s, infoTip.timeout); /* Timeout (4 bytes) */ Stream_Write_UINT32(s, infoTip.flags); /* InfoFlags (4 bytes) */ Stream_Write_UINT16(s, infoTip.text.length); /* InfoTipText (variable) */ @@ -2354,17 +2455,18 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, Stream_Write(s, infoTip.title.string, infoTip.title.length); } - if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0 && - iconStateOrder->version != 0) + if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0) { - orderSize += 4; + /* notify state should not be sent when version is 0 */ + if (versionFieldPresent && iconStateOrder->version == 0) + return FALSE; + Stream_Write_UINT32(s, iconStateOrder->state); } if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0) { ICON_INFO iconInfo = iconStateOrder->icon; - orderSize += 12; Stream_Write_UINT16(s, iconInfo.cacheEntry); /* CacheEntry (2 bytes) */ Stream_Write_UINT8(s, iconInfo.cacheId); /* CacheId (1 byte) */ Stream_Write_UINT8(s, iconInfo.bpp); /* Bpp (1 byte) */ @@ -2374,7 +2476,6 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, if (iconInfo.bpp <= 8) { Stream_Write_UINT16(s, iconInfo.cbColorTable); /* CbColorTable (2 bytes) */ - orderSize += 2; } Stream_Write_UINT16(s, iconInfo.cbBitsMask); /* CbBitsMask (2 bytes) */ @@ -2385,25 +2486,17 @@ BOOL update_send_new_or_existing_notification_icons(rdpContext* context, if (iconInfo.bpp <= 8) { Stream_Write(s, iconInfo.colorTable, iconInfo.cbColorTable); /* ColorTable (variable) */ - orderSize += iconInfo.cbColorTable; } Stream_Write(s, iconInfo.bitsColor, iconInfo.cbBitsColor); /* BitsColor (variable) */ - orderSize += iconInfo.cbBitsColor; } else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0) { CACHED_ICON_INFO cachedIcon = iconStateOrder->cachedIcon; - orderSize += 3; Stream_Write_UINT16(s, cachedIcon.cacheEntry); /* CacheEntry (2 bytes) */ Stream_Write_UINT8(s, cachedIcon.cacheId); /* CacheId (1 byte) */ } - /* Write size */ - orderEndPos = Stream_GetPosition(s); - Stream_SetPosition(s, orderSizePos); - Stream_Write_UINT16(s, orderSize); - Stream_SetPosition(s, orderEndPos); update->numberOrders++; return TRUE; } -- 2.7.4