New upstream version 2.11.7+dfsg1
This commit is contained in:
parent
995fbfcdd7
commit
ce01c78202
@ -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)
|
||||
|
||||
24
ChangeLog
24
ChangeLog
@ -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:
|
||||
|
||||
48
cmake/ClangDetectTool.cmake
Normal file
48
cmake/ClangDetectTool.cmake
Normal 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()
|
||||
@ -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}
|
||||
|
||||
@ -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++)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user