OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkEndian.h" | 10 #include "SkEndian.h" |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && | 307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && |
308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), | 308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), |
309 "Illuminant must be D50"); | 309 "Illuminant must be D50"); |
310 | 310 |
311 return_if_false(fTagCount <= 100, "Too many tags"); | 311 return_if_false(fTagCount <= 100, "Too many tags"); |
312 | 312 |
313 return true; | 313 return true; |
314 } | 314 } |
315 }; | 315 }; |
316 | 316 |
| 317 template <class T> |
| 318 static bool safe_add(T arg1, T arg2, size_t* result) { |
| 319 SkASSERT(arg1 >= 0); |
| 320 SkASSERT(arg2 >= 0); |
| 321 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { |
| 322 T sum = arg1 + arg2; |
| 323 if (sum <= std::numeric_limits<size_t>::max()) { |
| 324 *result = static_cast<size_t>(sum); |
| 325 return true; |
| 326 } |
| 327 } |
| 328 return false; |
| 329 } |
| 330 |
317 struct ICCTag { | 331 struct ICCTag { |
318 uint32_t fSignature; | 332 uint32_t fSignature; |
319 uint32_t fOffset; | 333 uint32_t fOffset; |
320 uint32_t fLength; | 334 uint32_t fLength; |
321 | 335 |
322 const uint8_t* init(const uint8_t* src) { | 336 const uint8_t* init(const uint8_t* src) { |
323 fSignature = read_big_endian_uint(src); | 337 fSignature = read_big_endian_uint(src); |
324 fOffset = read_big_endian_uint(src + 4); | 338 fOffset = read_big_endian_uint(src + 4); |
325 fLength = read_big_endian_uint(src + 8); | 339 fLength = read_big_endian_uint(src + 8); |
326 return src + 12; | 340 return src + 12; |
327 } | 341 } |
328 | 342 |
329 bool valid(size_t len) { | 343 bool valid(size_t len) { |
330 return_if_false(fOffset + fLength <= len, "Tag too large for ICC profile
"); | 344 size_t tagEnd; |
| 345 return_if_false(safe_add(fOffset, fLength, &tagEnd), |
| 346 "Tag too large, overflows integer addition"); |
| 347 return_if_false(tagEnd <= len, "Tag too large for ICC profile"); |
331 return true; | 348 return true; |
332 } | 349 } |
333 | 350 |
334 const uint8_t* addr(const uint8_t* src) const { | 351 const uint8_t* addr(const uint8_t* src) const { |
335 return src + fOffset; | 352 return src + fOffset; |
336 } | 353 } |
337 | 354 |
338 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature
) { | 355 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature
) { |
339 for (int i = 0; i < count; ++i) { | 356 for (int i = 0; i < count; ++i) { |
340 if (tags[i].fSignature == signature) { | 357 if (tags[i].fSignature == signature) { |
(...skipping 18 matching lines...) Expand all Loading... |
359 return false; | 376 return false; |
360 } | 377 } |
361 | 378 |
362 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 379 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); |
363 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 380 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); |
364 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 381 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); |
365 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 382 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); |
366 return true; | 383 return true; |
367 } | 384 } |
368 | 385 |
369 template <class T> | |
370 static bool safe_add(T arg1, T arg2, size_t* result) { | |
371 SkASSERT(arg1 >= 0); | |
372 SkASSERT(arg2 >= 0); | |
373 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { | |
374 T sum = arg1 + arg2; | |
375 if (sum <= std::numeric_limits<size_t>::max()) { | |
376 *result = static_cast<size_t>(sum); | |
377 return true; | |
378 } | |
379 } | |
380 return false; | |
381 } | |
382 | |
383 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); | 386 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); |
384 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); | 387 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); |
385 | 388 |
386 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { | 389 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { |
387 for (uint32_t i = 0; i < numGammas; i++) { | 390 for (uint32_t i = 0; i < numGammas; i++) { |
388 if (len < 12) { | 391 if (len < 12) { |
389 // FIXME (msarett): | 392 // FIXME (msarett): |
390 // We could potentially return false here after correctly parsing *s
ome* of the | 393 // We could potentially return false here after correctly parsing *s
ome* of the |
391 // gammas correctly. Should we somehow try to indicate a partial su
ccess? | 394 // gammas correctly. Should we somehow try to indicate a partial su
ccess? |
392 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 395 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 if (0 != offsetToMatrix && offsetToMatrix < len) { | 804 if (0 != offsetToMatrix && offsetToMatrix < len) { |
802 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { | 805 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { |
803 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 806 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
804 } | 807 } |
805 } | 808 } |
806 | 809 |
807 return true; | 810 return true; |
808 } | 811 } |
809 | 812 |
810 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { | 813 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { |
811 if (len < kICCHeaderSize) { | 814 if (!input || len < kICCHeaderSize) { |
812 return_null("Data is not large enough to contain an ICC profile"); | 815 return_null("Data is null or not large enough to contain an ICC profile"
); |
813 } | 816 } |
814 | 817 |
815 // Create our own copy of the input. | 818 // Create our own copy of the input. |
816 void* memory = sk_malloc_throw(len); | 819 void* memory = sk_malloc_throw(len); |
817 memcpy(memory, input, len); | 820 memcpy(memory, input, len); |
818 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); | 821 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); |
819 const void* base = data->data(); | 822 const void* base = data->data(); |
820 const uint8_t* ptr = (const uint8_t*) base; | 823 const uint8_t* ptr = (const uint8_t*) base; |
821 | 824 |
822 // Read the ICC profile header and check to make sure that it is valid. | 825 // Read the ICC profile header and check to make sure that it is valid. |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1141 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1139 ptr += kTAG_XYZ_Bytes; | 1142 ptr += kTAG_XYZ_Bytes; |
1140 | 1143 |
1141 // Write copyright tag | 1144 // Write copyright tag |
1142 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1145 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1143 | 1146 |
1144 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1147 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
1145 // the client calls again? | 1148 // the client calls again? |
1146 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1149 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1147 } | 1150 } |
OLD | NEW |