New upstream version 2.11.7+dfsg1

This commit is contained in:
Mike Gabriel 2024-07-15 16:44:11 +02:00
parent 995fbfcdd7
commit ce01c78202
14 changed files with 626 additions and 247 deletions

View File

@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSION_STRING "2.11.5")
set(RAW_VERSION_STRING "2.11.7")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)

View File

@ -1,3 +1,27 @@
# 2024-04-22 Version 2.11.7
Noteworthy changes:
* Backported oss-fuzz fixes
For a complete and detailed change log since the last release run:
git log 2.11.7...2.11.6
# 2024-04-17 Version 2.11.6
CVE:
CVE-2024-32041 [Low[ OutOfBound Read in zgfx_decompress_segment
CVE-2024-32039 [Moderate] Integer overflow & OutOfBound Write in clear_decompress_residual_data
CVE-2024-32040 [Low] integer underflow in nsc_rle_decode
CVE-2024-32458 [Low] OutOfBound Read in planar_skip_plane_rle
CVE-2024-32459 [Low] OutOfBound Read in ncrush_decompress
CVE-2024-32460 [Low] OutOfBound Read in interleaved_decompress
Noteworthy changes:
* Backported #10077
For a complete and detailed change log since the last release run:
git log 2.11.6...2.11.5
# 2024-01-19 Version 2.11.5
Noteworthy changes:

View File

@ -0,0 +1,48 @@
function (clang_detect_tool VAR NAME OPTS)
set(NAMES "")
foreach(CNT RANGE 12 22)
list(APPEND NAMES "${NAME}-${CNT}")
endforeach()
list(REVERSE NAMES)
list(APPEND NAMES ${NAME})
find_program(${VAR}
NAMES ${NAMES}
${OPTS}
)
if (NOT ${VAR})
message(WARNING "clang tool ${NAME} (${VAR}) not detected, skipping")
unset(${VAR})
return()
endif()
execute_process(
COMMAND ${${VAR}} "--version"
OUTPUT_VARIABLE _CLANG_TOOL_VERSION
RESULT_VARIABLE _CLANG_TOOL_VERSION_FAILED
)
if (_CLANG_TOOL_VERSION_FAILED)
message(WARNING "A problem was encounterd with ${${VAR}}")
message(WARNING "${_CLANG_TOOL_VERSION_FAILED}")
unset(${VAR})
return()
endif()
string(REGEX MATCH "([7-9]|[1-9][0-9])\\.[0-9]\\.[0-9]" CLANG_TOOL_VERSION
"${_CLANG_TOOL_VERSION}")
if (NOT CLANG_TOOL_VERSION)
message(WARNING "problem parsing ${NAME} version for ${${VAR}}")
unset(${VAR})
return()
endif()
set(_CLANG_TOOL_MINIMUM_VERSION "12.0.0")
if (${CLANG_TOOL_VERSION} VERSION_LESS ${_CLANG_TOOL_MINIMUM_VERSION})
message(WARNING "clang-format version ${CLANG_TOOL_VERSION} not supported")
message(WARNING "Minimum version required: ${_CLANG_TOOL_MINIMUM_VERSION}")
unset(${VAR})
return()
endif()
endfunction()

View File

@ -1,43 +1,12 @@
# get all project files
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.c *.h *.m *.java)
# minimum version required
set(_CLANG_FORMAT_MINIMUM_VERSION 7.0.0)
find_program(CLANG_FORMAT
NAMES
clang-format-8
clang-format-7
clang-format
)
include(ClangDetectTool)
clang_detect_tool(CLANG_FORMAT clang-format "")
if (NOT CLANG_FORMAT)
message(WARNING "clang-format not found in path! code format target not available.")
else()
execute_process(
COMMAND ${CLANG_FORMAT} "--version"
OUTPUT_VARIABLE _CLANG_FORMAT_VERSION
RESULT_VARIABLE _CLANG_FORMAT_VERSION_FAILED
)
if (_CLANG_FORMAT_VERSION_FAILED)
message(WARNING "A problem was encounterd with ${CLANG_FORMAT}")
return()
endif()
string(REGEX MATCH "([7-9]|[1-9][0-9])\\.[0-9]\\.[0-9]" CLANG_FORMAT_VERSION
"${_CLANG_FORMAT_VERSION}")
if (NOT CLANG_FORMAT_VERSION)
message(WARNING "problem parsing clang-fromat version for ${CLANG_FORMAT}")
return()
endif()
if (${CLANG_FORMAT_VERSION} VERSION_LESS ${_CLANG_FORMAT_MINIMUM_VERSION})
message(WARNING "clang-format version ${CLANG_FORMAT_VERSION} not supported")
message(WARNING "Minimum version required: ${_CLANG_FORMAT_MINIMUM_VERSION}")
return()
endif()
add_custom_target(
clangformat
COMMAND ${CLANG_FORMAT}

View File

@ -410,7 +410,7 @@ static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, wStream* s,
}
}
if ((pixelIndex + runLengthFactor) > pixelCount)
if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex)))
{
WLog_ERR(TAG,
"pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32
@ -512,12 +512,12 @@ static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* clear, wStream* s,
{
case 0: /* Uncompressed */
{
UINT32 nSrcStep = width * GetBytesPerPixel(PIXEL_FORMAT_BGR24);
UINT32 nSrcSize = nSrcStep * height;
const UINT32 nSrcStep = width * GetBytesPerPixel(PIXEL_FORMAT_BGR24);
const size_t nSrcSize = 1ull * nSrcStep * height;
if (bitmapDataByteCount != nSrcSize)
{
WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIu32 "",
WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIuz "",
bitmapDataByteCount, nSrcSize);
return FALSE;
}
@ -821,8 +821,15 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
if (count > 0)
pSrcPixel =
&vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)];
{
const size_t offset = (1ull * y - vBarYOn) * GetBytesPerPixel(clear->format);
pSrcPixel = &vBarShortEntry->pixels[offset];
if (offset + count > vBarShortEntry->count)
{
WLog_ERR(TAG, "offset + count > vBarShortEntry->count");
return FALSE;
}
}
for (x = 0; x < count; x++)
{

View File

@ -613,6 +613,9 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32
if (!pDstData || !pSrcData)
return FALSE;
if ((nWidth == 0) || (nHeight == 0))
return TRUE;
if (nDstStep == 0)
nDstStep = nWidth * GetBytesPerPixel(DstFormat);

View File

@ -31,7 +31,10 @@ static INLINE BYTE* WRITEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd, UINT32 r
BYTE mask = 0x01;
if (cBits > 8)
{
WLog_ERR(TAG, "cBits %d > 8", cBits);
return NULL;
}
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
return NULL;
@ -46,7 +49,6 @@ static INLINE BYTE* WRITEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd, UINT32 r
data = xorPixel;
DESTWRITEPIXEL(pbDest, data);
DESTNEXTPIXEL(pbDest);
mask = mask << 1;
});
return pbDest;
@ -62,7 +64,10 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd,
BYTE mask = 0x01;
if (cBits > 8)
{
WLog_ERR(TAG, "cBits %d > 8", cBits);
return NULL;
}
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
return NULL;
@ -76,7 +81,6 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd,
data = BLACK_PIXEL;
DESTWRITEPIXEL(pbDest, data);
DESTNEXTPIXEL(pbDest);
mask = mask << 1;
});
return pbDest;
@ -88,6 +92,9 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd,
static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BYTE* pbDestBuffer,
UINT32 rowDelta, UINT32 width, UINT32 height)
{
#if defined(WITH_DEBUG_CODECS)
char sbuffer[128] = { 0 };
#endif
const BYTE* pbSrc = pbSrcBuffer;
const BYTE* pbEnd;
const BYTE* pbDestEnd;
@ -100,14 +107,22 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
PIXEL pixelA, pixelB;
UINT32 runLength;
UINT32 code;
UINT32 advance;
UINT32 advance = 0;
RLEEXTRA
if ((rowDelta == 0) || (rowDelta < width))
{
WLog_ERR(TAG, "Invalid arguments: rowDelta=%" PRIu32 " == 0 || < width=%" PRIu32, rowDelta,
width);
return FALSE;
}
if (!pbSrcBuffer || !pbDestBuffer)
{
WLog_ERR(TAG, "Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p", pbSrcBuffer,
pbDestBuffer);
return FALSE;
}
pbEnd = pbSrcBuffer + cbSrcBuffer;
pbDestEnd = pbDestBuffer + rowDelta * height;
@ -130,10 +145,17 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
*/
code = ExtractCodeId(*pbSrc);
#if defined(WITH_DEBUG_CODECS)
WLog_VRB(TAG, "pbSrc=%p code=%s, rem=%" PRIuz, pbSrc,
rle_code_str_buffer(code, sbuffer, sizeof(sbuffer)), pbEnd - pbSrc);
#endif
/* Handle Background Run Orders. */
if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN)
if ((code == REGULAR_BG_RUN) || (code == MEGA_MEGA_BG_RUN))
{
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (fFirstLine)
@ -144,17 +166,13 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
return FALSE;
DESTWRITEPIXEL(pbDest, fgPel);
DESTNEXTPIXEL(pbDest);
runLength = runLength - 1;
}
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
return FALSE;
UNROLL(runLength, {
DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
DESTNEXTPIXEL(pbDest);
});
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); });
}
else
{
@ -166,7 +184,6 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
return FALSE;
DESTWRITEPIXEL(pbDest, temp ^ fgPel);
DESTNEXTPIXEL(pbDest);
runLength--;
}
@ -176,7 +193,6 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
UNROLL(runLength, {
DESTREADPIXEL(temp, pbDest - rowDelta);
DESTWRITEPIXEL(pbDest, temp);
DESTNEXTPIXEL(pbDest);
});
}
@ -196,15 +212,16 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
case MEGA_MEGA_FG_RUN:
case LITE_SET_FG_FG_RUN:
case MEGA_MEGA_SET_FG_RUN:
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
{
if (pbSrc >= pbEnd)
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
return FALSE;
SRCREADPIXEL(fgPel, pbSrc);
SRCNEXTPIXEL(pbSrc);
}
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
@ -212,17 +229,13 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
if (fFirstLine)
{
UNROLL(runLength, {
DESTWRITEPIXEL(pbDest, fgPel);
DESTNEXTPIXEL(pbDest);
});
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, fgPel); });
}
else
{
UNROLL(runLength, {
DESTREADPIXEL(temp, pbDest - rowDelta);
DESTWRITEPIXEL(pbDest, temp ^ fgPel);
DESTNEXTPIXEL(pbDest);
});
}
@ -231,45 +244,41 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
/* Handle Dithered Run Orders. */
case LITE_DITHERED_RUN:
case MEGA_MEGA_DITHERED_RUN:
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
return FALSE;
SRCREADPIXEL(pixelA, pbSrc);
SRCNEXTPIXEL(pbSrc);
if (pbSrc >= pbEnd)
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
return FALSE;
SRCREADPIXEL(pixelB, pbSrc);
SRCNEXTPIXEL(pbSrc);
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength * 2))
return FALSE;
UNROLL(runLength, {
DESTWRITEPIXEL(pbDest, pixelA);
DESTNEXTPIXEL(pbDest);
DESTWRITEPIXEL(pbDest, pixelB);
DESTNEXTPIXEL(pbDest);
});
break;
/* Handle Color Run Orders. */
case REGULAR_COLOR_RUN:
case MEGA_MEGA_COLOR_RUN:
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
return FALSE;
SRCREADPIXEL(pixelA, pbSrc);
SRCNEXTPIXEL(pbSrc);
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
return FALSE;
UNROLL(runLength, {
DESTWRITEPIXEL(pbDest, pixelA);
DESTNEXTPIXEL(pbDest);
});
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, pixelA); });
break;
/* Handle Foreground/Background Image Orders. */
@ -277,17 +286,20 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
case MEGA_MEGA_FGBG_IMAGE:
case LITE_SET_FG_FGBG_IMAGE:
case MEGA_MEGA_SET_FGBG_IMAGE:
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
return FALSE;
if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
{
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
return FALSE;
SRCREADPIXEL(fgPel, pbSrc);
SRCNEXTPIXEL(pbSrc);
}
if (!buffer_within_range(pbSrc, runLength / 8, pbEnd))
return FALSE;
if (fFirstLine)
{
while (runLength > 8)
@ -306,8 +318,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
{
while (runLength > 8)
{
bitmask = *pbSrc;
pbSrc = pbSrc + 1;
bitmask = *pbSrc++;
pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8);
if (!pbDest)
@ -319,8 +331,9 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
if (runLength > 0)
{
bitmask = *pbSrc;
pbSrc = pbSrc + 1;
if (!buffer_within_range(pbSrc, 1, pbEnd))
return FALSE;
bitmask = *pbSrc++;
if (fFirstLine)
{
@ -342,23 +355,25 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
/* Handle Color Image Orders. */
case REGULAR_COLOR_IMAGE:
case MEGA_MEGA_COLOR_IMAGE:
runLength = ExtractRunLength(code, pbSrc, &advance);
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
if (advance == 0)
return FALSE;
pbSrc = pbSrc + advance;
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
return FALSE;
if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
return FALSE;
UNROLL(runLength, {
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(temp, pbSrc);
SRCNEXTPIXEL(pbSrc);
DESTWRITEPIXEL(pbDest, temp);
DESTNEXTPIXEL(pbDest);
});
break;
/* Handle Special Order 1. */
case SPECIAL_FGBG_1:
if (!buffer_within_range(pbSrc, 1, pbEnd))
return FALSE;
pbSrc = pbSrc + 1;
if (fFirstLine)
@ -379,6 +394,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
/* Handle Special Order 2. */
case SPECIAL_FGBG_2:
if (!buffer_within_range(pbSrc, 1, pbEnd))
return FALSE;
pbSrc = pbSrc + 1;
if (fFirstLine)
@ -399,27 +416,31 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
/* Handle White Order. */
case SPECIAL_WHITE:
if (!buffer_within_range(pbSrc, 1, pbEnd))
return FALSE;
pbSrc = pbSrc + 1;
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
return FALSE;
DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
DESTNEXTPIXEL(pbDest);
break;
/* Handle Black Order. */
case SPECIAL_BLACK:
if (!buffer_within_range(pbSrc, 1, pbEnd))
return FALSE;
pbSrc = pbSrc + 1;
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
return FALSE;
DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
DESTNEXTPIXEL(pbDest);
break;
default:
WLog_ERR(TAG, "invalid code 0x%08" PRIx32 ", pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
code, pbSrcBuffer, pbSrc, pbEnd);
return FALSE;
}
}

View File

@ -21,6 +21,7 @@
* limitations under the License.
*/
#include <winpr/assert.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -30,15 +31,16 @@
#define TAG FREERDP_TAG("codec")
#define UNROLL_BODY(_exp, _count) \
do \
{ \
size_t x; \
for (x = 0; x < (_count); x++) \
{ \
do \
_exp while (FALSE); \
} \
#define UNROLL_BODY(_exp, _count) \
do \
{ \
for (size_t x = 0; x < (_count); x++) \
{ \
do \
{ \
_exp \
} while (FALSE); \
} \
} while (FALSE)
#define UNROLL_MULTIPLE(_condition, _exp, _count) \
@ -97,6 +99,80 @@ static const BYTE g_MaskSpecialFgBg2 = 0x05;
static const BYTE g_MaskRegularRunLength = 0x1F;
static const BYTE g_MaskLiteRunLength = 0x0F;
static const char* rle_code_str(UINT32 code)
{
switch (code)
{
case REGULAR_BG_RUN:
return "REGULAR_BG_RUN";
case MEGA_MEGA_BG_RUN:
return "MEGA_MEGA_BG_RUN";
case REGULAR_FG_RUN:
return "REGULAR_FG_RUN";
case MEGA_MEGA_FG_RUN:
return "MEGA_MEGA_FG_RUN";
case LITE_SET_FG_FG_RUN:
return "LITE_SET_FG_FG_RUN";
case MEGA_MEGA_SET_FG_RUN:
return "MEGA_MEGA_SET_FG_RUN";
case LITE_DITHERED_RUN:
return "LITE_DITHERED_RUN";
case MEGA_MEGA_DITHERED_RUN:
return "MEGA_MEGA_DITHERED_RUN";
case REGULAR_COLOR_RUN:
return "REGULAR_COLOR_RUN";
case MEGA_MEGA_COLOR_RUN:
return "MEGA_MEGA_COLOR_RUN";
case REGULAR_FGBG_IMAGE:
return "REGULAR_FGBG_IMAGE";
case MEGA_MEGA_FGBG_IMAGE:
return "MEGA_MEGA_FGBG_IMAGE";
case LITE_SET_FG_FGBG_IMAGE:
return "LITE_SET_FG_FGBG_IMAGE";
case MEGA_MEGA_SET_FGBG_IMAGE:
return "MEGA_MEGA_SET_FGBG_IMAGE";
case REGULAR_COLOR_IMAGE:
return "REGULAR_COLOR_IMAGE";
case MEGA_MEGA_COLOR_IMAGE:
return "MEGA_MEGA_COLOR_IMAGE";
case SPECIAL_FGBG_1:
return "SPECIAL_FGBG_1";
case SPECIAL_FGBG_2:
return "SPECIAL_FGBG_2";
case SPECIAL_WHITE:
return "SPECIAL_WHITE";
case SPECIAL_BLACK:
return "SPECIAL_BLACK";
default:
return "UNKNOWN";
}
}
static const char* rle_code_str_buffer(UINT32 code, char* buffer, size_t size)
{
const char* str = rle_code_str(code);
_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, code);
return buffer;
}
#define buffer_within_range(pbSrc, size, pbEnd) \
buffer_within_range_((pbSrc), (size), (pbEnd), __func__, __FILE__, __LINE__)
static INLINE BOOL buffer_within_range_(const void* pbSrc, size_t size, const void* pbEnd,
const char* fkt, const char* file, size_t line)
{
WINPR_UNUSED(file);
WINPR_ASSERT(pbSrc);
WINPR_ASSERT(pbEnd);
if ((const char*)pbSrc + size > (const char*)pbEnd)
{
WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p + %" PRIuz " > pbEnd=%p", fkt, line, pbSrc, size,
pbEnd);
return FALSE;
}
return TRUE;
}
/**
* Reads the supplied order header and extracts the compression
* order code ID.
@ -127,71 +203,155 @@ static INLINE UINT32 ExtractCodeId(BYTE bOrderHdr)
/**
* Extract the run length of a compression order.
*/
static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT32* advance)
static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
{
UINT32 runLength;
UINT32 ladvance;
ladvance = 1;
runLength = 0;
UINT runLength = 0;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
if (runLength == 0)
{
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
}
runLength = *(pbOrderHdr + 1) + 1;
(*advance)++;
}
else
runLength = runLength * 8;
return runLength;
}
static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
{
UINT runLength = 0;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
runLength = *pbOrderHdr & g_MaskLiteRunLength;
if (runLength == 0)
{
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
}
runLength = *(pbOrderHdr + 1) + 1;
(*advance)++;
}
else
runLength = runLength * 8;
return runLength;
}
static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
{
UINT runLength = 0;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
runLength = *pbOrderHdr & g_MaskRegularRunLength;
if (runLength == 0)
{
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
}
runLength = *(pbOrderHdr + 1) + 32;
(*advance)++;
}
return runLength;
}
static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
{
UINT runLength = 0;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
if (!buffer_within_range(pbOrderHdr, 3, pbEnd))
{
*advance = 0;
return 0;
}
runLength = ((UINT16)pbOrderHdr[1]) | (((UINT16)pbOrderHdr[2]) << 8);
(*advance) += 2;
return runLength;
}
static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
{
UINT runLength = 0;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
runLength = *pbOrderHdr & g_MaskLiteRunLength;
if (runLength == 0)
{
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
}
runLength = *(pbOrderHdr + 1) + 16;
(*advance)++;
}
return runLength;
}
static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const BYTE* pbEnd,
UINT32* advance)
{
UINT32 runLength = 0;
UINT32 ladvance = 1;
WINPR_ASSERT(pbOrderHdr);
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
*advance = 0;
if (!buffer_within_range(pbOrderHdr, 0, pbEnd))
return 0;
switch (code)
{
case REGULAR_FGBG_IMAGE:
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
if (runLength == 0)
{
runLength = (*(pbOrderHdr + 1)) + 1;
ladvance += 1;
}
else
{
runLength = runLength * 8;
}
runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, pbEnd, &ladvance);
break;
case LITE_SET_FG_FGBG_IMAGE:
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
if (runLength == 0)
{
runLength = (*(pbOrderHdr + 1)) + 1;
ladvance += 1;
}
else
{
runLength = runLength * 8;
}
runLength = ExtractRunLengthLiteFgBg(pbOrderHdr, pbEnd, &ladvance);
break;
case REGULAR_BG_RUN:
case REGULAR_FG_RUN:
case REGULAR_COLOR_RUN:
case REGULAR_COLOR_IMAGE:
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
if (runLength == 0)
{
/* An extended (MEGA) run. */
runLength = (*(pbOrderHdr + 1)) + 32;
ladvance += 1;
}
runLength = ExtractRunLengthRegular(pbOrderHdr, pbEnd, &ladvance);
break;
case LITE_SET_FG_FG_RUN:
case LITE_DITHERED_RUN:
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
if (runLength == 0)
{
/* An extended (MEGA) run. */
runLength = (*(pbOrderHdr + 1)) + 16;
ladvance += 1;
}
runLength = ExtractRunLengthLite(pbOrderHdr, pbEnd, &ladvance);
break;
case MEGA_MEGA_BG_RUN:
@ -202,8 +362,12 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3
case MEGA_MEGA_FGBG_IMAGE:
case MEGA_MEGA_SET_FGBG_IMAGE:
case MEGA_MEGA_COLOR_IMAGE:
runLength = ((UINT16)pbOrderHdr[1]) | ((UINT16)(pbOrderHdr[2] << 8));
ladvance += 2;
runLength = ExtractRunLengthMegaMega(pbOrderHdr, pbEnd, &ladvance);
break;
default:
runLength = 0;
ladvance = 0;
break;
}
@ -211,20 +375,32 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3
return runLength;
}
static INLINE BOOL ensure_capacity(const BYTE* start, const BYTE* end, size_t size, size_t base)
#define ensure_capacity(start, end, size, base) \
ensure_capacity_((start), (end), (size), (base), __func__, __FILE__, __LINE__)
static INLINE BOOL ensure_capacity_(const BYTE* start, const BYTE* end, size_t size, size_t base,
const char* fkt, const char* file, size_t line)
{
const size_t available = (uintptr_t)end - (uintptr_t)start;
const BOOL rc = available >= size * base;
return rc && (start <= end);
const BOOL res = rc && (start <= end);
if (!res)
WLog_ERR(TAG,
"[%s:%" PRIuz "] failed: start=%p <= end=%p, available=%" PRIuz " >= size=%" PRIuz
" * base=%" PRIuz,
fkt, line, start, end, available, size, base);
return res;
}
static INLINE void write_pixel_8(BYTE* _buf, BYTE _pix)
{
WINPR_ASSERT(_buf);
*_buf = _pix;
}
static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
{
WINPR_ASSERT(_buf);
(_buf)[0] = (BYTE)(_pix);
(_buf)[1] = (BYTE)((_pix) >> 8);
(_buf)[2] = (BYTE)((_pix) >> 16);
@ -232,6 +408,7 @@ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
{
WINPR_ASSERT(_buf);
_buf[0] = _pix & 0xFF;
_buf[1] = (_pix >> 8) & 0xFF;
}
@ -239,19 +416,30 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
#undef DESTWRITEPIXEL
#undef DESTREADPIXEL
#undef SRCREADPIXEL
#undef DESTNEXTPIXEL
#undef SRCNEXTPIXEL
#undef WRITEFGBGIMAGE
#undef WRITEFIRSTLINEFGBGIMAGE
#undef RLEDECOMPRESS
#undef RLEEXTRA
#undef WHITE_PIXEL
#undef PIXEL_SIZE
#undef PIXEL
#define PIXEL_SIZE 1
#define PIXEL BYTE
#define WHITE_PIXEL 0xFF
#define DESTWRITEPIXEL(_buf, _pix) write_pixel_8(_buf, _pix)
#define DESTWRITEPIXEL(_buf, _pix) \
do \
{ \
write_pixel_8(_buf, _pix); \
_buf += 1; \
} while (0)
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0]
#define DESTNEXTPIXEL(_buf) _buf += 1
#define SRCNEXTPIXEL(_buf) _buf += 1
#define SRCREADPIXEL(_pix, _buf) \
do \
{ \
_pix = (_buf)[0]; \
_buf += 1; \
} while (0)
#define WRITEFGBGIMAGE WriteFgBgImage8to8
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
#define RLEDECOMPRESS RleDecompress8to8
@ -263,19 +451,29 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
#undef DESTWRITEPIXEL
#undef DESTREADPIXEL
#undef SRCREADPIXEL
#undef DESTNEXTPIXEL
#undef SRCNEXTPIXEL
#undef WRITEFGBGIMAGE
#undef WRITEFIRSTLINEFGBGIMAGE
#undef RLEDECOMPRESS
#undef RLEEXTRA
#undef WHITE_PIXEL
#undef PIXEL_SIZE
#undef PIXEL
#define PIXEL_SIZE 2
#define PIXEL UINT16
#define WHITE_PIXEL 0xFFFF
#define DESTWRITEPIXEL(_buf, _pix) write_pixel_16(_buf, _pix)
#define DESTWRITEPIXEL(_buf, _pix) \
do \
{ \
write_pixel_16(_buf, _pix); \
_buf += 2; \
} while (0)
#define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8)
#define DESTNEXTPIXEL(_buf) _buf += 2
#define SRCNEXTPIXEL(_buf) _buf += 2
#define SRCREADPIXEL(_pix, _buf) \
do \
{ \
_pix = (_buf)[0] | ((_buf)[1] << 8); \
_buf += 2; \
} while (0)
#define WRITEFGBGIMAGE WriteFgBgImage16to16
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
#define RLEDECOMPRESS RleDecompress16to16
@ -287,19 +485,30 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
#undef DESTWRITEPIXEL
#undef DESTREADPIXEL
#undef SRCREADPIXEL
#undef DESTNEXTPIXEL
#undef SRCNEXTPIXEL
#undef WRITEFGBGIMAGE
#undef WRITEFIRSTLINEFGBGIMAGE
#undef RLEDECOMPRESS
#undef RLEEXTRA
#undef WHITE_PIXEL
#define WHITE_PIXEL 0xFFFFFF
#define DESTWRITEPIXEL(_buf, _pix) write_pixel_24(_buf, _pix)
#undef PIXEL_SIZE
#undef PIXEL
#define PIXEL_SIZE 3
#define PIXEL UINT32
#define WHITE_PIXEL 0xffffff
#define DESTWRITEPIXEL(_buf, _pix) \
do \
{ \
write_pixel_24(_buf, _pix); \
_buf += 3; \
} while (0)
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16)
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16)
#define DESTNEXTPIXEL(_buf) _buf += 3
#define SRCNEXTPIXEL(_buf) _buf += 3
#define SRCREADPIXEL(_pix, _buf) \
do \
{ \
_pix = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16); \
_buf += 3; \
} while (0)
#define WRITEFGBGIMAGE WriteFgBgImage24to24
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
#define RLEDECOMPRESS RleDecompress24to24
@ -308,18 +517,32 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
#define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 3)
#include "include/bitmap.c"
struct S_BITMAP_INTERLEAVED_CONTEXT
{
BOOL Compressor;
UINT32 TempSize;
BYTE* TempBuffer;
wStream* bts;
};
BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE* pSrcData,
UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight, UINT32 bpp,
BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
const gdiPalette* palette)
{
UINT32 scanline;
UINT32 SrcFormat;
UINT32 BufferSize;
UINT32 scanline = 0;
UINT32 SrcFormat = 0;
UINT32 BufferSize = 0;
if (!interleaved || !pSrcData || !pDstData)
{
WLog_ERR(TAG, "invalid arguments: interleaved=%p, pSrcData=%p, pDstData=%p", interleaved,
pSrcData, pDstData);
return FALSE;
}
switch (bpp)
{
@ -352,19 +575,26 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE*
if (BufferSize > interleaved->TempSize)
{
interleaved->TempBuffer = _aligned_realloc(interleaved->TempBuffer, BufferSize, 16);
interleaved->TempBuffer =
_aligned_recalloc(interleaved->TempBuffer, BufferSize, sizeof(BYTE), 16);
interleaved->TempSize = BufferSize;
}
if (!interleaved->TempBuffer)
{
WLog_ERR(TAG, "interleaved->TempBuffer=%p", interleaved->TempBuffer);
return FALSE;
}
switch (bpp)
{
case 24:
if (!RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
nSrcWidth, nSrcHeight))
{
WLog_ERR(TAG, "RleDecompress24to24 failed");
return FALSE;
}
break;
@ -372,24 +602,36 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE*
case 15:
if (!RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
nSrcWidth, nSrcHeight))
{
WLog_ERR(TAG, "RleDecompress16to16 failed");
return FALSE;
}
break;
case 8:
if (!RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth,
nSrcHeight))
{
WLog_ERR(TAG, "RleDecompress8to8 failed");
return FALSE;
}
break;
default:
WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp);
return FALSE;
}
return freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
interleaved->TempBuffer, SrcFormat, scanline, 0, 0, palette,
FREERDP_FLIP_VERTICAL);
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
interleaved->TempBuffer, SrcFormat, scanline, 0, 0, palette,
FREERDP_FLIP_VERTICAL))
{
WLog_ERR(TAG, "freerdp_image_copy failed");
return FALSE;
}
return TRUE;
}
BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
@ -397,10 +639,10 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstDat
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette,
UINT32 bpp)
{
BOOL status;
wStream* s;
BOOL status = 0;
wStream* s = NULL;
UINT32 DstFormat = 0;
const size_t maxSize = 64 * 64 * 4;
const UINT32 maxSize = 64 * 64 * 4;
if (!interleaved || !pDstData || !pSrcData)
return FALSE;
@ -442,7 +684,7 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstDat
}
if (!freerdp_image_copy(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, nHeight, pSrcData,
SrcFormat, nSrcStep, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE))
SrcFormat, nSrcStep, nXSrc, nYSrc, palette, 0))
return FALSE;
s = Stream_New(pDstData, *pDstSize);
@ -474,33 +716,29 @@ BOOL bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
{
BITMAP_INTERLEAVED_CONTEXT* interleaved;
interleaved = (BITMAP_INTERLEAVED_CONTEXT*)calloc(1, sizeof(BITMAP_INTERLEAVED_CONTEXT));
BITMAP_INTERLEAVED_CONTEXT* interleaved = NULL;
interleaved = (BITMAP_INTERLEAVED_CONTEXT*)_aligned_recalloc(
NULL, 1, sizeof(BITMAP_INTERLEAVED_CONTEXT), 32);
if (interleaved)
{
interleaved->TempSize = 64 * 64 * 4;
interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize, 16);
interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize * sizeof(BYTE), 16);
if (!interleaved->TempBuffer)
{
free(interleaved);
WLog_ERR(TAG, "_aligned_malloc failed!");
return NULL;
}
goto fail;
interleaved->bts = Stream_New(NULL, interleaved->TempSize);
if (!interleaved->bts)
{
_aligned_free(interleaved->TempBuffer);
free(interleaved);
WLog_ERR(TAG, "Stream_New failed!");
return NULL;
}
goto fail;
}
return interleaved;
fail:
bitmap_interleaved_context_free(interleaved);
return NULL;
}
void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
@ -510,5 +748,5 @@ void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
_aligned_free(interleaved->TempBuffer);
Stream_Free(interleaved->bts, TRUE);
free(interleaved);
_aligned_free(interleaved);
}

View File

@ -2041,6 +2041,12 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
return 1;
}
if (SrcSize < 4)
{
WLog_ERR(TAG, "Input size short: SrcSize %" PRIu32 " < 4", SrcSize);
return -1;
}
const BYTE* SrcEnd = &pSrcData[SrcSize];
const BYTE* SrcPtr = pSrcData + 4;

View File

@ -95,8 +95,8 @@ static BOOL nsc_decode(NSC_CONTEXT* context)
for (x = 0; x < context->width; x++)
{
INT16 y_val = (INT16)*yplane;
INT16 co_val = (INT16)(INT8)(*coplane << shift);
INT16 cg_val = (INT16)(INT8)(*cgplane << shift);
INT16 co_val = (INT16)(INT8)(((INT16)*coplane) << shift);
INT16 cg_val = (INT16)(INT8)(((INT16)*cgplane) << shift);
INT16 r_val = y_val + co_val - cg_val;
INT16 g_val = y_val + cg_val;
INT16 b_val = y_val - co_val - cg_val;
@ -169,7 +169,7 @@ static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outS
len |= ((UINT32)(*in++)) << 24U;
}
if (outSize < len)
if ((outSize < len) || (left < len))
return FALSE;
outSize -= len;
@ -259,6 +259,13 @@ static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
}
Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */
if ((context->ColorLossLevel < 1) || (context->ColorLossLevel > 7))
{
WLog_Print(context->priv->log, WLOG_ERROR,
"ColorLossLevel=%" PRIu8 " out of range, must be [1,7] inclusive",
context->ColorLossLevel);
return FALSE;
}
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Seek(s, 2); /* Reserved (2 bytes) */
context->Planes = Stream_Pointer(s);

View File

@ -689,6 +689,13 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
rawHeights[3] = nSrcHeight;
}
const size_t diff = srcp - pSrcData;
if (SrcSize < diff)
{
WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
return FALSE;
}
if (!rle) /* RAW */
{
UINT32 base = planeSize * 3;
@ -697,8 +704,12 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
if ((SrcSize - (srcp - pSrcData)) < (planeSize + base))
if ((SrcSize - diff) < (planeSize + base))
{
WLog_ERR(TAG, "Alpha plane size mismatch %" PRIuz " < %" PRIu32, SrcSize - diff,
(planeSize + base));
return FALSE;
}
planes[3] = srcp; /* AlphaPlane */
planes[0] = planes[3] + rawSizes[3]; /* LumaOrRedPlane */
@ -710,8 +721,11 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
}
else
{
if ((SrcSize - (srcp - pSrcData)) < base)
if ((SrcSize - diff) < base)
{
WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32, SrcSize - diff, base);
return FALSE;
}
planes[0] = srcp; /* LumaOrRedPlane */
planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */
@ -726,8 +740,8 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
planes[3] = srcp;
rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData),
rawWidths[3], rawHeights[3]); /* AlphaPlane */
rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - diff, rawWidths[3],
rawHeights[3]); /* AlphaPlane */
if (rleSizes[3] < 0)
return FALSE;
@ -737,22 +751,41 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
else
planes[0] = srcp;
rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
rawWidths[0], rawHeights[0]); /* RedPlane */
const size_t diff0 = (planes[0] - pSrcData);
if (SrcSize < diff0)
{
WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff0);
return FALSE;
}
rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - diff0, rawWidths[0],
rawHeights[0]); /* RedPlane */
if (rleSizes[0] < 0)
return FALSE;
planes[1] = planes[0] + rleSizes[0];
rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
rawWidths[1], rawHeights[1]); /* GreenPlane */
const size_t diff1 = (planes[1] - pSrcData);
if (SrcSize < diff1)
{
WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff1);
return FALSE;
}
rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - diff1, rawWidths[1],
rawHeights[1]); /* GreenPlane */
if (rleSizes[1] < 1)
return FALSE;
planes[2] = planes[1] + rleSizes[1];
rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
rawWidths[2], rawHeights[2]); /* BluePlane */
const size_t diff2 = (planes[2] - pSrcData);
if (SrcSize < diff2)
{
WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
return FALSE;
}
rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - diff2, rawWidths[2],
rawHeights[2]); /* BluePlane */
if (rleSizes[2] < 1)
return FALSE;

View File

@ -230,7 +230,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
BYTE* pbSegment;
size_t cbSegment;
if (!zgfx || !stream || (segmentSize < 2))
WINPR_ASSERT(zgfx);
WINPR_ASSERT(stream);
if (segmentSize < 2)
return FALSE;
cbSegment = segmentSize - 1;
@ -349,8 +352,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
if (count > zgfx->cBitsRemaining / 8)
else if (count > zgfx->cBitsRemaining / 8)
return FALSE;
else if (zgfx->pbInputCurrent + count > zgfx->pbInputEnd)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
@ -381,15 +385,45 @@ static BYTE* aligned_zgfx_malloc(size_t size)
return malloc(size + 64);
}
static BOOL zgfx_append(ZGFX_CONTEXT* zgfx, BYTE** ppConcatenated, size_t uncompressedSize,
size_t* pUsed)
{
WINPR_ASSERT(zgfx);
WINPR_ASSERT(ppConcatenated);
WINPR_ASSERT(pUsed);
const size_t used = *pUsed;
if (zgfx->OutputCount > UINT32_MAX - used)
return FALSE;
if (used + zgfx->OutputCount > uncompressedSize)
return FALSE;
BYTE* tmp = realloc(*ppConcatenated, used + zgfx->OutputCount + 64ull);
if (!tmp)
return FALSE;
*ppConcatenated = tmp;
CopyMemory(&tmp[used], zgfx->OutputBuffer, zgfx->OutputCount);
*pUsed = used + zgfx->OutputCount;
return TRUE;
}
int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
UINT32* pDstSize, UINT32 flags)
{
int status = -1;
BYTE descriptor;
BYTE descriptor = 0;
size_t used = 0;
BYTE* pConcatenated = NULL;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
if (!stream)
return -1;
WINPR_ASSERT(zgfx);
WINPR_ASSERT(stream);
WINPR_ASSERT(ppDstData);
WINPR_ASSERT(pDstSize);
*ppDstData = NULL;
*pDstSize = 0;
if (Stream_GetRemainingLength(stream) < 1)
goto fail;
@ -401,16 +435,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream)))
goto fail;
*ppDstData = NULL;
if (zgfx->OutputCount > 0)
*ppDstData = aligned_zgfx_malloc(zgfx->OutputCount);
if (!*ppDstData)
goto fail;
*pDstSize = zgfx->OutputCount;
CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount);
{
if (!zgfx_append(zgfx, &pConcatenated, zgfx->OutputCount, &used))
goto fail;
if (used != zgfx->OutputCount)
goto fail;
*ppDstData = pConcatenated;
*pDstSize = zgfx->OutputCount;
}
}
else if (descriptor == ZGFX_SEGMENTED_MULTIPART)
{
@ -418,8 +451,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
UINT16 segmentNumber;
UINT16 segmentCount;
UINT32 uncompressedSize;
BYTE* pConcatenated;
size_t used = 0;
if (Stream_GetRemainingLength(stream) < 6)
goto fail;
@ -427,17 +458,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */
Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */
if (Stream_GetRemainingLength(stream) < segmentCount * sizeof(UINT32))
goto fail;
pConcatenated = aligned_zgfx_malloc(uncompressedSize);
if (!pConcatenated)
goto fail;
*ppDstData = pConcatenated;
*pDstSize = uncompressedSize;
for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++)
{
if (Stream_GetRemainingLength(stream) < sizeof(UINT32))
@ -448,16 +468,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
goto fail;
if (zgfx->OutputCount > UINT32_MAX - used)
if (!zgfx_append(zgfx, &pConcatenated, uncompressedSize, &used))
goto fail;
if (used + zgfx->OutputCount > uncompressedSize)
goto fail;
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
pConcatenated += zgfx->OutputCount;
used += zgfx->OutputCount;
}
if (used != uncompressedSize)
goto fail;
*ppDstData = pConcatenated;
*pDstSize = uncompressedSize;
}
else
{
@ -466,6 +485,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
status = 1;
fail:
if (status < 0)
free(pConcatenated);
Stream_Free(stream, FALSE);
return status;
}

View File

@ -797,6 +797,7 @@ static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value)
static INLINE BOOL update_read_delta(wStream* s, INT32* value)
{
BYTE byte;
UINT32 uvalue = 0;
if (Stream_GetRemainingLength(s) < 1)
{
@ -807,9 +808,9 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value)
Stream_Read_UINT8(s, byte);
if (byte & 0x40)
*value = (byte | ~0x3F);
uvalue = (byte | ~0x3F);
else
*value = (byte & 0x3F);
uvalue = (byte & 0x3F);
if (byte & 0x80)
{
@ -820,8 +821,9 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value)
}
Stream_Read_UINT8(s, byte);
*value = (*value << 8) | byte;
uvalue = (uvalue << 8) | byte;
}
*value = (INT32)uvalue;
return TRUE;
}

View File

@ -57,7 +57,7 @@ if (NOT WIN32)
endif()
# Soname versioning
set(RAW_VERSION_STRING "2.11.5")
set(RAW_VERSION_STRING "2.11.7")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)