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 "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 void init(const uint8_t* src, size_t len) { | 103 void init(const uint8_t* src, size_t len) { |
104 SkASSERT(kICCHeaderSize == sizeof(*this)); | 104 SkASSERT(kICCHeaderSize == sizeof(*this)); |
105 | 105 |
106 uint32_t* dst = (uint32_t*) this; | 106 uint32_t* dst = (uint32_t*) this; |
107 for (uint32_t i = 0; i < kICCHeaderSize / 4; i++, src+=4) { | 107 for (uint32_t i = 0; i < kICCHeaderSize / 4; i++, src+=4) { |
108 dst[i] = read_big_endian_u32(src); | 108 dst[i] = read_big_endian_u32(src); |
109 } | 109 } |
110 } | 110 } |
111 | 111 |
112 bool valid() const { | 112 bool valid() const { |
113 return_if_false(fSize >= kICCHeaderSize, "Size is too small"); | 113 SkASSERT(fSize >= kICCHeaderSize); |
114 | 114 |
115 uint8_t majorVersion = fVersion >> 24; | 115 uint8_t majorVersion = fVersion >> 24; |
116 return_if_false(majorVersion <= 4, "Unsupported version"); | 116 return_if_false(majorVersion <= 4, "Unsupported version"); |
117 | 117 |
118 // These are the four basic classes of profiles that we might expect to
see embedded | 118 // These are the four basic classes of profiles that we might expect to
see embedded |
119 // in images. Additional classes exist, but they generally are used as
a convenient | 119 // in images. Additional classes exist, but they generally are used as
a convenient |
120 // way for CMMs to store calculated transforms. | 120 // way for CMMs to store calculated transforms. |
121 return_if_false(fProfileClass == kDisplay_Profile || | 121 return_if_false(fProfileClass == kDisplay_Profile || |
122 fProfileClass == kInput_Profile || | 122 fProfileClass == kInput_Profile || |
123 fProfileClass == kOutput_Profile || | 123 fProfileClass == kOutput_Profile || |
(...skipping 18 matching lines...) Expand all Loading... |
142 // Warn rather than fail here. Occasionally, we see perfectly | 142 // Warn rather than fail here. Occasionally, we see perfectly |
143 // normal profiles with wacky rendering intents. | 143 // normal profiles with wacky rendering intents. |
144 SkColorSpacePrintf("Warning, bad rendering intent.\n"); | 144 SkColorSpacePrintf("Warning, bad rendering intent.\n"); |
145 } | 145 } |
146 | 146 |
147 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0
]), 0.96420f) && | 147 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0
]), 0.96420f) && |
148 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && | 148 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && |
149 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), | 149 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), |
150 "Illuminant must be D50"); | 150 "Illuminant must be D50"); |
151 | 151 |
| 152 // Arbitrary, but there's no reason to exceed 100 tags. |
152 return_if_false(fTagCount <= 100, "Too many tags"); | 153 return_if_false(fTagCount <= 100, "Too many tags"); |
153 | 154 |
154 return true; | 155 return true; |
155 } | 156 } |
156 }; | 157 }; |
157 | 158 |
158 template <class T> | 159 template <class T> |
159 static bool safe_add(T arg1, T arg2, size_t* result) { | 160 static bool safe_add(T arg1, T arg2, size_t* result) { |
160 SkASSERT(arg1 >= 0); | 161 SkASSERT(arg1 >= 0); |
161 SkASSERT(arg2 >= 0); | 162 SkASSERT(arg2 >= 0); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 // In the case of consecutive gamma tags, we need to count the number of byt
es in the | 285 // In the case of consecutive gamma tags, we need to count the number of byt
es in the |
285 // tag, so that we can move on to the next tag. | 286 // tag, so that we can move on to the next tag. |
286 size_t tagBytes; | 287 size_t tagBytes; |
287 | 288 |
288 uint32_t type = read_big_endian_u32(src); | 289 uint32_t type = read_big_endian_u32(src); |
289 // Bytes 4-7 are reserved and should be set to zero. | 290 // Bytes 4-7 are reserved and should be set to zero. |
290 switch (type) { | 291 switch (type) { |
291 case kTAG_CurveType: { | 292 case kTAG_CurveType: { |
292 uint32_t count = read_big_endian_u32(src + 8); | 293 uint32_t count = read_big_endian_u32(src + 8); |
293 | 294 |
| 295 // This is arbitrary, but one million entries is more than enough fo
r a table. |
| 296 static constexpr size_t kMaxGammaTableSize = 2 << 20; |
| 297 if (count > kMaxGammaTableSize) { |
| 298 SkColorSpacePrintf("Gamma table too large"); |
| 299 return SkGammas::Type::kNone_Type; |
| 300 } |
| 301 |
294 // tagBytes = 12 + 2 * count | 302 // tagBytes = 12 + 2 * count |
295 // We need to do safe addition here to avoid integer overflow. | 303 // We need to do safe addition here to avoid integer overflow. |
296 if (!safe_add(count, count, &tagBytes) || | 304 if (!safe_add(count, count, &tagBytes) || |
297 !safe_add((size_t) 12, tagBytes, &tagBytes)) | 305 !safe_add((size_t) 12, tagBytes, &tagBytes)) |
298 { | 306 { |
299 SkColorSpacePrintf("Invalid gamma count"); | 307 SkColorSpacePrintf("Invalid gamma count"); |
300 return SkGammas::Type::kNone_Type; | 308 return SkGammas::Type::kNone_Type; |
301 } | 309 } |
302 | 310 |
303 if (len < tagBytes) { | 311 if (len < tagBytes) { |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 } | 874 } |
867 | 875 |
868 if (a->fOffset == b->fOffset) { | 876 if (a->fOffset == b->fOffset) { |
869 return true; | 877 return true; |
870 } | 878 } |
871 | 879 |
872 return !memcmp(a->addr(base), b->addr(base), a->fLength); | 880 return !memcmp(a->addr(base), b->addr(base), a->fLength); |
873 } | 881 } |
874 | 882 |
875 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { | 883 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { |
876 if (!input || len < kICCHeaderSize) { | 884 // This is arbitrary, but there's no need for a sane profile to exceed 4 MB. |
| 885 static constexpr size_t kMaxICCSize = 2 << 22; |
| 886 |
| 887 if (!input || kICCHeaderSize > len || len > kMaxICCSize) { |
877 return_null("Data is null or not large enough to contain an ICC profile"
); | 888 return_null("Data is null or not large enough to contain an ICC profile"
); |
878 } | 889 } |
879 | 890 |
880 // Create our own copy of the input. | 891 // Create our own copy of the input. |
881 void* memory = sk_malloc_throw(len); | 892 void* memory = sk_malloc_throw(len); |
882 memcpy(memory, input, len); | 893 memcpy(memory, input, len); |
883 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); | 894 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); |
884 const uint8_t* base = data->bytes(); | 895 const uint8_t* base = data->bytes(); |
885 const uint8_t* ptr = base; | 896 const uint8_t* ptr = base; |
886 | 897 |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1313 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1303 ptr += kTAG_XYZ_Bytes; | 1314 ptr += kTAG_XYZ_Bytes; |
1304 | 1315 |
1305 // Write copyright tag | 1316 // Write copyright tag |
1306 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1317 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1307 | 1318 |
1308 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1319 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
1309 // the client calls again? | 1320 // the client calls again? |
1310 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1321 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1311 } | 1322 } |
OLD | NEW |