From 5db0b81f7c1c7c18c11fe06e58892ed64e347ef1 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 15 Jun 2018 14:01:07 -0700 Subject: Bug 1464039 - Reject some invalid transforms in qcms. r=mwoodrow, a=RyanVM --- gfx/qcms/chain.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gfx') diff --git a/gfx/qcms/chain.c b/gfx/qcms/chain.c index e382fbe00..2b0e707c4 100644 --- a/gfx/qcms/chain.c +++ b/gfx/qcms/chain.c @@ -972,6 +972,10 @@ static float* qcms_modular_transform_data(struct qcms_modular_transform *transfo assert(0 && "Unsupported transform module"); return NULL; } + if (transform->grid_size <= 0) { + assert(0 && "Invalid transform"); + return NULL; + } transform->transform_module_fn(transform,src,dest,len); dest = src; src = new_src; -- cgit v1.2.3 From 3858dd6de2f4d510b42ca8675235469b8b78ed02 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Tue, 19 Jun 2018 15:32:29 +0200 Subject: Bug 1464039 - Only reject qcms transform with invalid grid size if the transform function uses the grid size. r=Bas a=jcristau --- gfx/qcms/chain.c | 4 +++- gfx/thebes/gfxPlatform.cpp | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'gfx') diff --git a/gfx/qcms/chain.c b/gfx/qcms/chain.c index 2b0e707c4..dbae18378 100644 --- a/gfx/qcms/chain.c +++ b/gfx/qcms/chain.c @@ -972,7 +972,9 @@ static float* qcms_modular_transform_data(struct qcms_modular_transform *transfo assert(0 && "Unsupported transform module"); return NULL; } - if (transform->grid_size <= 0) { + if (transform->grid_size <= 0 && + (transform_fn == qcms_transform_module_clut || + transform_fn == qcms_transform_module_clut_only)) { assert(0 && "Invalid transform"); return NULL; } diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 684117788..171d1bec9 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -156,6 +156,7 @@ static Mutex* gGfxPlatformPrefsLock = nullptr; static qcms_profile *gCMSOutputProfile = nullptr; static qcms_profile *gCMSsRGBProfile = nullptr; +static bool gCMSRGBTransformFailed = false; static qcms_transform *gCMSRGBTransform = nullptr; static qcms_transform *gCMSInverseRGBTransform = nullptr; static qcms_transform *gCMSRGBATransform = nullptr; @@ -1856,7 +1857,7 @@ gfxPlatform::GetCMSsRGBProfile() qcms_transform * gfxPlatform::GetCMSRGBTransform() { - if (!gCMSRGBTransform) { + if (!gCMSRGBTransform && !gCMSRGBTransformFailed) { qcms_profile *inProfile, *outProfile; outProfile = GetCMSOutputProfile(); inProfile = GetCMSsRGBProfile(); @@ -1867,6 +1868,9 @@ gfxPlatform::GetCMSRGBTransform() gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8, outProfile, QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); + if (!gCMSRGBTransform) { + gCMSRGBTransformFailed = true; + } } return gCMSRGBTransform; -- cgit v1.2.3 From bad62e9a44f446eb78de3d4368d1385a58156797 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 1 Jul 2018 14:33:10 +0200 Subject: Rework gfxFontUtils::MapCharToGlyphFormat4 to be more robust. DiD --- gfx/thebes/gfxFontUtils.cpp | 89 ++++++++++++++++++++++------------------ gfx/thebes/gfxFontUtils.h | 2 +- gfx/thebes/gfxHarfBuzzShaper.cpp | 8 +++- 3 files changed, 57 insertions(+), 42 deletions(-) (limited to 'gfx') diff --git a/gfx/thebes/gfxFontUtils.cpp b/gfx/thebes/gfxFontUtils.cpp index cb505e87b..54ca03ff6 100644 --- a/gfx/thebes/gfxFontUtils.cpp +++ b/gfx/thebes/gfxFontUtils.cpp @@ -575,55 +575,64 @@ typedef struct { #pragma pack() uint32_t -gfxFontUtils::MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh) +gfxFontUtils::MapCharToGlyphFormat4(const uint8_t* aBuf, uint32_t aLength, + char16_t aCh) { const Format4Cmap *cmap4 = reinterpret_cast(aBuf); - uint16_t segCount; - const AutoSwap_PRUint16 *endCodes; - const AutoSwap_PRUint16 *startCodes; - const AutoSwap_PRUint16 *idDelta; - const AutoSwap_PRUint16 *idRangeOffset; - uint16_t probe; - uint16_t rangeShiftOver2; - uint16_t index; - - segCount = (uint16_t)(cmap4->segCountX2) / 2; - - endCodes = &cmap4->arrays[0]; - startCodes = &cmap4->arrays[segCount + 1]; // +1 for reserved word between arrays - idDelta = &startCodes[segCount]; - idRangeOffset = &idDelta[segCount]; - - probe = 1 << (uint16_t)(cmap4->entrySelector); - rangeShiftOver2 = (uint16_t)(cmap4->rangeShift) / 2; - - if ((uint16_t)(startCodes[rangeShiftOver2]) <= aCh) { - index = rangeShiftOver2; - } else { - index = 0; - } - - while (probe > 1) { - probe >>= 1; - if ((uint16_t)(startCodes[index + probe]) <= aCh) { - index += probe; + + uint16_t segCount = (uint16_t)(cmap4->segCountX2) / 2; + + const AutoSwap_PRUint16* endCodes = &cmap4->arrays[0]; + const AutoSwap_PRUint16* startCodes = &cmap4->arrays[segCount + 1]; + const AutoSwap_PRUint16* idDelta = &startCodes[segCount]; + const AutoSwap_PRUint16* idRangeOffset = &idDelta[segCount]; + + // Sanity-check that the fixed-size arrays don't exceed the buffer. + const uint8_t* const limit = aBuf + aLength; + if ((const uint8_t*)(&idRangeOffset[segCount]) > limit) { + return 0; // broken font, just bail out safely + } + + // For most efficient binary search, we want to work on a range of segment + // indexes that is a power of 2 so that we can always halve it by shifting. + // So we find the largest power of 2 that is <= segCount. + // We will offset this range by segOffset so as to reach the end + // of the table, provided that doesn't put us beyond the target + // value from the outset. + uint32_t powerOf2 = mozilla::FindHighestBit(segCount); + uint32_t segOffset = segCount - powerOf2; + uint32_t idx = 0; + + if (uint16_t(startCodes[segOffset]) <= aCh) { + idx = segOffset; + } + + // Repeatedly halve the size of the range until we find the target group + while (powerOf2 > 1) { + powerOf2 >>= 1; + if (uint16_t(startCodes[idx + powerOf2]) <= aCh) { + idx += powerOf2; } } - if (aCh >= (uint16_t)(startCodes[index]) && aCh <= (uint16_t)(endCodes[index])) { + if (aCh >= uint16_t(startCodes[idx]) && aCh <= uint16_t(endCodes[idx])) { uint16_t result; - if ((uint16_t)(idRangeOffset[index]) == 0) { + if (uint16_t(idRangeOffset[idx]) == 0) { result = aCh; } else { - uint16_t offset = aCh - (uint16_t)(startCodes[index]); - const AutoSwap_PRUint16 *glyphIndexTable = - (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[index] + - (uint16_t)(idRangeOffset[index])); + uint16_t offset = aCh - uint16_t(startCodes[idx]); + const AutoSwap_PRUint16* glyphIndexTable = + (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[idx] + + uint16_t(idRangeOffset[idx])); + if ((const uint8_t*)(glyphIndexTable + offset + 1) > limit) { + return 0; // broken font, just bail out safely + } result = glyphIndexTable[offset]; } - // note that this is unsigned 16-bit arithmetic, and may wrap around - result += (uint16_t)(idDelta[index]); + // Note that this is unsigned 16-bit arithmetic, and may wrap around + // (which is required behavior per spec) + result += uint16_t(idDelta[idx]); return result; } @@ -761,7 +770,8 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, switch (format) { case 4: gid = aUnicode < UNICODE_BMP_LIMIT ? - MapCharToGlyphFormat4(aCmapBuf + offset, char16_t(aUnicode)) : 0; + MapCharToGlyphFormat4(aCmapBuf + offset, aBufLength - offset, + char16_t(aUnicode)) : 0; break; case 10: gid = MapCharToGlyphFormat10(aCmapBuf + offset, aUnicode); @@ -785,6 +795,7 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, case 4: if (aUnicode < UNICODE_BMP_LIMIT) { varGID = MapCharToGlyphFormat4(aCmapBuf + offset, + aBufLength - offset, char16_t(aUnicode)); } break; diff --git a/gfx/thebes/gfxFontUtils.h b/gfx/thebes/gfxFontUtils.h index dd6a76558..1e87e5436 100644 --- a/gfx/thebes/gfxFontUtils.h +++ b/gfx/thebes/gfxFontUtils.h @@ -804,7 +804,7 @@ public: bool& aUnicodeFont, bool& aSymbolFont); static uint32_t - MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh); + MapCharToGlyphFormat4(const uint8_t *aBuf, uint32_t aLength, char16_t aCh); static uint32_t MapCharToGlyphFormat10(const uint8_t *aBuf, uint32_t aCh); diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index 4b9dbbc14..f2264bc1f 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -111,13 +111,15 @@ gfxHarfBuzzShaper::GetNominalGlyph(hb_codepoint_t unicode) const NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), "cmap data not correctly set up, expect disaster"); + uint32_t length; const uint8_t* data = - (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); + (const uint8_t*)hb_blob_get_data(mCmapTable, &length); switch (mCmapFormat) { case 4: gid = unicode < UNICODE_BMP_LIMIT ? gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, + length - mSubtableOffset, unicode) : 0; break; case 10: @@ -157,8 +159,9 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), "cmap data not correctly set up, expect disaster"); + uint32_t length; const uint8_t* data = - (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); + (const uint8_t*)hb_blob_get_data(mCmapTable, &length); if (mUVSTableOffset) { hb_codepoint_t gid = @@ -176,6 +179,7 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, case 4: if (compat < UNICODE_BMP_LIMIT) { return gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, + length - mSubtableOffset, compat); } break; -- cgit v1.2.3