| Index: src/core/SkColorSpace.cpp
|
| diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
|
| index ec8de725c129fdf79c400a1784771a2ab45eed81..5df45fff4126d7e9a08a1251e9b9cde029ae7de8 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;
|
|
|