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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 return false; | 359 return false; |
360 } | 360 } |
361 | 361 |
362 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 362 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); |
363 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 363 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); |
364 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 364 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); |
365 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 365 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); |
366 return true; | 366 return true; |
367 } | 367 } |
368 | 368 |
| 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 |
369 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); | 383 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); |
370 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); | 384 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); |
371 | 385 |
372 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { | 386 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { |
373 for (uint32_t i = 0; i < numGammas; i++) { | 387 for (uint32_t i = 0; i < numGammas; i++) { |
374 if (len < 12) { | 388 if (len < 12) { |
375 // FIXME (msarett): | 389 // FIXME (msarett): |
376 // We could potentially return false here after correctly parsing *s
ome* of the | 390 // We could potentially return false here after correctly parsing *s
ome* of the |
377 // gammas correctly. Should we somehow try to indicate a partial su
ccess? | 391 // gammas correctly. Should we somehow try to indicate a partial su
ccess? |
378 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 392 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
379 return false; | 393 return false; |
380 } | 394 } |
381 | 395 |
382 // We need to count the number of bytes in the tag, so we are able to mo
ve to the | 396 // We need to count the number of bytes in the tag, so we are able to mo
ve to the |
383 // next tag on the next loop iteration. | 397 // next tag on the next loop iteration. |
384 size_t tagBytes; | 398 size_t tagBytes; |
385 | 399 |
386 uint32_t type = read_big_endian_uint(src); | 400 uint32_t type = read_big_endian_uint(src); |
387 switch (type) { | 401 switch (type) { |
388 case kTAG_CurveType: { | 402 case kTAG_CurveType: { |
389 uint32_t count = read_big_endian_uint(src + 8); | 403 uint32_t count = read_big_endian_uint(src + 8); |
390 tagBytes = 12 + count * 2; | 404 |
| 405 // tagBytes = 12 + 2 * count |
| 406 // We need to do safe addition here to avoid integer overflow. |
| 407 if (!safe_add(count, count, &tagBytes) || |
| 408 !safe_add((size_t) 12, tagBytes, &tagBytes)) |
| 409 { |
| 410 SkColorSpacePrintf("Invalid gamma count"); |
| 411 return false; |
| 412 } |
| 413 |
391 if (0 == count) { | 414 if (0 == count) { |
392 // Some tags require a gamma curve, but the author doesn't a
ctually want | 415 // Some tags require a gamma curve, but the author doesn't a
ctually want |
393 // to transform the data. In this case, it is common to see
a curve with | 416 // to transform the data. In this case, it is common to see
a curve with |
394 // a count of 0. | 417 // a count of 0. |
395 gammas[i].fValue = 1.0f; | 418 gammas[i].fValue = 1.0f; |
396 break; | 419 break; |
397 } else if (len < tagBytes) { | 420 } else if (len < tagBytes) { |
398 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; | 421 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; |
399 return false; | 422 return false; |
400 } | 423 } |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1071 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1049 ptr += kTAG_XYZ_Bytes; | 1072 ptr += kTAG_XYZ_Bytes; |
1050 | 1073 |
1051 // Write copyright tag | 1074 // Write copyright tag |
1052 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1075 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1053 | 1076 |
1054 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1077 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
1055 // the client calls again? | 1078 // the client calls again? |
1056 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1079 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1057 } | 1080 } |
OLD | NEW |