diff options
author | msarett <msarett@google.com> | 2016-06-20 08:08:28 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-20 08:08:28 -0700 |
commit | 0ed057542ce545da57cda92dc09c1da8b5fdc363 (patch) | |
tree | 611ccdbd9a6ab8c0b10a272282497e9f313d7f60 /src | |
parent | d2809573deb7b99e764f7f71fe34a5b5322df0b2 (diff) |
Sanitize parsing of color look-up table
BUG=skia:5443
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2079243003
Review-Url: https://codereview.chromium.org/2079243003
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkColorSpace.cpp | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index ec8de725c1..5df45fff41 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -319,6 +319,17 @@ static bool safe_add(T arg1, T arg2, size_t* result) { return false; } +static bool safe_mul(uint32_t arg1, uint32_t arg2, uint32_t* result) { + uint64_t product64 = (uint64_t) arg1 * (uint64_t) arg2; + uint32_t product32 = (uint32_t) product64; + if (product32 != product64) { + return false; + } + + *result = product32; + return true; +} + struct ICCTag { uint32_t fSignature; uint32_t fOffset; @@ -658,10 +669,14 @@ static constexpr uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32_t outputChannels, const uint8_t* src, size_t len) { - if (len < 20) { + // 16 bytes reserved for grid points, 2 for precision, 2 for padding. + // The color LUT data follows after this header. + static constexpr uint32_t kColorLUTHeaderSize = 20; + if (len < kColorLUTHeaderSize) { SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); return false; } + size_t dataLen = len - kColorLUTHeaderSize; SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputChannels); colorLUT->fInputChannels = inputChannels; @@ -669,9 +684,21 @@ bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32 uint32_t numEntries = 1; for (uint32_t i = 0; i < inputChannels; i++) { colorLUT->fGridPoints[i] = src[i]; - numEntries *= src[i]; + if (0 == src[i]) { + SkColorSpacePrintf("Each input channel must have at least one grid point."); + return false; + } + + if (!safe_mul(numEntries, src[i], &numEntries)) { + SkColorSpacePrintf("Too many entries in Color LUT."); + return false; + } + } + + if (!safe_mul(numEntries, outputChannels, &numEntries)) { + SkColorSpacePrintf("Too many entries in Color LUT."); + return false; } - numEntries *= outputChannels; // Space is provided for a maximum of the 16 input channels. Now we determine the precision // of the table values. @@ -681,18 +708,24 @@ bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32 case 2: // 16-bit data break; default: - SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n", len); + SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n"); return false; } - if (len < 20 + numEntries * precision) { + uint32_t clutBytes; + if (!safe_mul(numEntries, precision, &clutBytes)) { + SkColorSpacePrintf("Too many entries in Color LUT."); + return false; + } + + if (dataLen < clutBytes) { SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); return false; } // Movable struct colorLUT has ownership of fTable. colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); - const uint8_t* ptr = src + 20; + const uint8_t* ptr = src + kColorLUTHeaderSize; for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { if (1 == precision) { colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |